Dynamically Appending Elements to jQuery Mobile ListView
24 Feb 2011I’ve been developing with jQuery Mobile the past several weeks and the application I’m working on has a listing page where I am retrieving the results via $.ajax and then dynamically appending the results to the current page. I started out with a page very much like the following…
<pre><div data-role="page" id="hackerNews">
<div data-role="header" data-backbtn="false">
Refresh
<h1>Hacker News
0
</h1>
</div>
<div id="content" data-role="content">
<ol class="newsList" data-role="listview"></ol>
</div>
</div>
</pre>…but when I tried to dynamically render the ListView into the content area the browser ended up rendering something like the screenshot below on the left, where I had expected it to render something like the screenshot on the right.
<div></div><div></div>In the following example, I will pull the most recent items from Hacker News and display them inside of a jQuery Mobile ListView.
After some digging and researching, it turns out the difference between the left screenshot and the right is just one line of code. All you have to do is to call the $.listview() widget off of your list jQuery object… so, something like $( "#myUnorderedList" ).listview();
.
Make sure to notice line #61, which is the main difference between the screenshot above!
<pre>var hackerNews = (function( $, undefined ) {
var pub = {};
pub.init = function() {
//Refresh news when btnRefresh is clicked
$( “#btnRefresh” ).live( “click”,
function() {
pub.getAndDisplayNews();
});
//When news updated, display items in list
amplify.subscribe( “news.updated”,
function( news ) {
displayNews( news );
});
//When news updated, then set item count
amplify.subscribe( “news.updated”,
function( news ) {
$(“#itemCount”).text( news.items.length );
});
};
pub.getAndDisplayNews = function() {
//Starting loading animation
$.mobile.pageLoading();
//Get news and add success callback using then
getNews().then( function() {
//Stop loading animation on success
$.mobile.pageLoading( true );
});
};
function getNews() {
//Get news via ajax and return jqXhr
return $.ajax({
url: “http://api.ihackernews.com/” +
“page?format=jsonp”,
dataType: “jsonp”
}).then( function( data, textStatus, jqXHR ) {
//Publish that news has been updated & allow
//the 2 subscribers to update the UI content
amplify.publish( “news.updated”, data );
});
}
function displayNews( news ) {
var newsList = $( “#hackerNews” )
.find( “.newsList” );
//Empty current list
newsList.empty();
//Use template to create items & add to list
$( “#newsItem” ).tmpl( news.items )
.appendTo( newsList );
//Call listview jQuery UI Widget after adding
//items to the list for correct rendering
newsList.listview( “refresh” );
}
return pub;
}( jQuery ));
hackerNews.init();
hackerNews.getAndDisplayNews();
</pre>I am utilizing some of the new jQuery 1.5 Deferred syntax and also the publish/subscribe methods from the Amplify Library released by appendTo recently. I’m also using the Revealing Module Pattern to protect the global scope.
View Demo Edit Demo