Working with jQuery Mobile is sometimes messy, especially when working on a large project. It becomes even worse if client-server communication is somehow involved. So why not do it a little bit better?
 
 

Note: If this tutorial was helpful, need further clarification, something is not working or do you have a request for another Ionic post? Furthermore, if you don't like something about this blog, if something is bugging you, don't like how I'm doing stuff here, again leave me a comment below. I'm here to help you, I expect the same from you. Feel free to comment below, subscribe to my blog, mail me to dragan.gaic@gmail.com, or follow and mention me on twitter (@gajotres). Thanks and have a nice day!

PS. If you want my help, if possible (even if it takes you some time to do that), create a working example I can play with. Use Plunker for AngularJS based questions or jsFiddle for jQuery/jQuery Mobile based questions.


 

Intro

 
Even if you never used them before, when you build a JavaScript application, you have almost certainly heard someone talking about JavaScript templates. Rather than use a library like jQuery (or vanilla JavaScript) to update your HTML, you can use templates, which cleans up your code hugely.
 
In this example, we will use Handlebars js template framework. Handlebars provide the power necessary to let you build semantic templates effectively with no frustration. Mustache templates are compatible with Handlebars, so you can take a Mustache template, import it into Handlebars, and start taking advantage of the extra Handlebars features.
 

Example:

 
Before we continue lets create a basic HTML page, we will fill it with dynamically retrieved content. To achieve some consistency we will use an example from one of my previous answers.
 
Initial pages :
As you can see we have a pretty light page, we will fill only listview, no point in doing anything major.
 
<div data-role="page" id="home">
	<div data-theme="a" data-role="header">
		<h3>
			Movie List
		</h3>
	</div>        
	<div data-role="content">
		<div class="example-wrapper" data-iscroll>
			<input name="movie-title" id="movie-title" value="" type="text" placeholder="Enter Movie Title"/>            
			<a href="#" class="ui-btn" id="search-movie">Search</a>
			<ul data-role="listview"  id="movie-list" data-theme="a">
				
			</ul>
		</div>
	</div>            
</div>
 
<div data-role="page" id="headline">
	<div data-theme="a" data-role="header">
		<a href="#home" class="ui-btn-left" data-transition="slide" data-direction="reverse">Back</a>                        
		<h3>
			Movie Info
		</h3>
	</div>        
	<div data-role="content">
		<script id="movie-template" type="text/x-handlebars-template">
			{{#.}}
			<li><img src="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w185{{this.poster_path}}"/></li>
			<li>Title: {{this.original_title}}</li>
			<li>Release date : {{this.release_date}}</li>
			<li>Popularity : {{this.popularity}}</li>
			<li>Popularity : {{this.vote_average}}</li>
			{{/.}}
		</script>                  
		<ul data-role="listview"  id="movie-data" data-theme="a">
			
		</ul>
	</div>
</div>  
 
Templates:
Not let’s create templates, first one will look like this:
 
<script id="movie-template" type="text/x-handlebars-template">
	{{#.}}
	<li><a data-id="{{this.id}}"><img src="{{this.poster_path}}"/><h3>{{this.title}}</h3><p>{{this.release_date}}</p></a></li>
	{{/.}}
</script>   
 
While second one will look like this:
 
<script id="movie-template" type="text/x-handlebars-template">
	{{#.}}
	<li><img src="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w185{{this.poster_path}}"/></li>
	<li>Title: {{this.original_title}}</li>
	<li>Release date : {{this.release_date}}</li>
	<li>Popularity : {{this.popularity}}</li>
	<li>Popularity : {{this.vote_average}}</li>
	{{/.}}
</script>  
 
If you want to learn what’s what just hop to official plugin website. In few words, {{#.}} and {{/.}} are keywords telling Handlebars to loop this content as long as there something to show. We will use the first template at our initial page, it will show listview of found movie titles. Second template will show movie details on application second page.
 
Lets mix pages and templates:
It is going to look like this:
 
<!DOCTYPE html>
<html>
    <head>
        <title>jQM Complex Demo</title>
        <meta name="viewport" content="initial-scale=1, maximum-scale=1"/>
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.css" /> 
        <script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.min.js"></script>        
        <script src="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.js"></script>    
    </head>
    <body>
        <div data-role="page" id="home">
            <div data-theme="a" data-role="header">
                <h3>
                    Movie List
                </h3>
            </div>        
            <div data-role="content">
                <div class="example-wrapper" data-iscroll>
                    <input name="movie-title" id="movie-title" value="" type="text" placeholder="Enter Movie Title"/>            
                    <a href="#" class="ui-btn" id="search-movie">Search</a>
                    <script id="movies-template" type="text/x-handlebars-template">
                        {{#.}}
                        <li><a data-id="{{this.id}}"><img src="{{this.poster_path}}"/><h3>{{this.title}}</h3><p>{{this.release_date}}</p></a></li>
                        {{/.}}
                    </script>                      
                    <ul data-role="listview"  id="movie-list" data-theme="a">
                        
                    </ul>
                </div>
            </div>            
        </div>
        <div data-role="page" id="headline">
            <div data-theme="a" data-role="header">
                <a href="#home" class="ui-btn-left" data-transition="slide" data-direction="reverse">Back</a>                        
                <h3>
                    Movie Info
                </h3>
            </div>        
            <div data-role="content">
                <script id="movie-template" type="text/x-handlebars-template">
                    {{#.}}
                    <li><img src="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w185{{this.poster_path}}"/></li>
                    <li>Title: {{this.original_title}}</li>
                    <li>Release date : {{this.release_date}}</li>
                    <li>Popularity : {{this.popularity}}</li>
                    <li>Popularity : {{this.vote_average}}</li>
                    {{/.}}
                </script>                  
                <ul data-role="listview"  id="movie-data" data-theme="a">
                    
                </ul>
            </div>
        </div>    
    </body>
</html>   
 
Lets make it work with JavaScript:
Before we can use shown templates we first need to compile them:
 
var movieListHandler = Handlebars.compile($("#movies-template").html());
 
ID used is template id, example:
 
<script id="movie-template" type="text/x-handlebars-template">
 
In the end, we need to initialize the template and pass it JSON data, and append processed template to intended listview, like this:
 
$('#movie-data').html(movieHandler(row));  
 
Used JavaScript:
$(document).on('pageinit', '#home', function(){      
    
    $(document).on('click', '#search-movie', function(){ 
        if($('#movie-title').val().length > 0) {
            var url = 'http://api.themoviedb.org/3/',
                mode = 'search/movie?query=',
                movieName = '&query='+encodeURI($('#movie-title').val()),        
                key = '&api_key=470fd2ec8853e25d2f8d86f685d2270e';        
            
            $.ajax({
                url: url + mode + key + movieName ,
                dataType: "jsonp",
                async: true,
                success: function (result) {
                    ajax.parseJSONP(result);
                },
                error: function (request,error) {
                    alert('Network error has occurred please try again!');
                }
            });          
        } else {
            alert('Please enter mobie title!');
        }       
    });        
});

$(document).on('pagebeforeshow', '#headline', function(){      
    $('#movie-data').empty();
    $.each(movieInfo.result, function(i, row) {
        if(row.id == movieInfo.id) {
            var movieHandler = Handlebars.compile($("#movie-template").html());
            $('#movie-data').html(movieHandler(row));                
        } 
    });          
    $('#movie-data').listview('refresh');     
});

$(document).on('vclick', '#movie-list li a', function(){  
    movieInfo.id = $(this).attr('data-id');
    $.mobile.changePage( "#headline", { transition: "slide", changeHash: false });
});

var movieInfo = {
    id : null,
    result : null
}

var ajax = {  
    parseJSONP:function(result){  
        movieInfo.result = result.results;
        $('#movie-list').empty(); 
        var movieListHandler = Handlebars.compile($("#movies-template").html());
        $('#movie-list').html(movieListHandler(result.results));         
        $('#movie-list').listview('refresh');
    }
}

 

Working example:

 
Working jsFiddle example can be found here: http://jsfiddle.net/Gajotres/M7aTF/
 
To make things even better you should compare it with my original example, or you can test it directly here:
 
 

Who Am I?

Between working as a senior Java developer in one of the largest insurance companies in the world and traveling, in my free time, I work as a professional mobile development adviser. I'm also a major jQuery Mobile supporter back at StackOverflow and a forum moderator at the official Ionic Framework forum.

Blogs worth reading

If you're here looking for information related to the Ionic Framework, you will also like these blogs: