Question

So, the title is pretty self-explanatory. I'm trying to use jQuery mobile and Handlebars, yet I'm having issues with the CSS of the tables or rather listviews that are generated by handlebars. It appears the CSS gets ignored.

EDIT: here's an actual live example: http://jsbin.com/adurar/1/edit

In the <head> section, I have the following code:

<script id="articles-template" type="text/x-handlebars-template">
<ul data-role="listview" data-autodividers="true"  data-filter="true" data-inset="true">
  {{#entries}} 
    <li><a href="#" onClick="">{{msg}}</a></li>
  {{/entries}}
</ul>
</script>

The body of the HTML is pretty straight forward jquery mobile:

<div data-role="page" data-theme="b">

    <div data-role="header">
        <h1>Page Title</h1>
    </div><!-- /header -->

    <div data-role="content">   
        <p>
          <div id="articleHandlebars" data-demo-html="true"></div>
        </p>        
    </div><!-- /content -->

    <div data-role="footer">
        <h4>Page Footer</h4>
    </div><!-- /footer -->
</div><!-- /page -->

and in the .js file I have this code:

function showData(data)
{
  var source   = $("#articles-template").html();
  var template = Handlebars.compile(source);
  var html = template(data);
  $("#articleHandlebars").html(html);   
 }

I also tried adding this to no avail:

$("#articleHandlebars").trigger('create');
$("#articleHandlebars").listview('refresh');

Any kind of help is greatly appreciated!

Était-ce utile?

La solution

You have few errors in your code, I will explain everything with solutions.

Code changes:

Lets change your page a bit:

<div data-role="page" data-theme="b" id="listview-page">

    <div data-role="header">
        <h1>Page Title</h1>
    </div><!-- /header -->

    <div data-role="content"  id="listview-content">   
        <p>
          <div id="articleHandlebars" data-demo-html="true"></div>
        </p>        
    </div><!-- /content -->

    <div data-role="footer">
        <h4>Page Footer</h4>
    </div><!-- /footer -->
</div><!-- /page -->

I have added an id listview-page to the page container and an id listview-content to the content container. We will use it in our solution.

Solutions:

First, this line:

$("#articleHandlebars").listview('refresh');

is not going to work, you can trigger listview refresh only on a listview widget or ul elemenet with an attribute data-role="listview". If ul element is appended directly to the div #articleHandlebars try this:

$("#articleHandlebars ul").listview('refresh');

or go deep until you reach ul tag. But from my experience it is not going to work because your listview is dynamically generated, so you will need to initialize listview before you can refresh it. So if top solution is not working try this one:

$("#articleHandlebars ul").listview().listview('refresh');

First listview() call will initialize widget and second one listview('refresh') will style it.

Second thing, you are using:

$("#articleHandlebars").trigger('create');

It should usually trigger on a content div, so if listview('refresh') is not working try this:

$("#listview-content").trigger('create');

This will only work if you have changed your page like I advised you at the beginning of this answer. Or worst case scenario try this one:

$("#listview-page").trigger('pagecreate');

EDIT :

I have fixed your example: http://jsbin.com/ivezat/1/edit

HTML :

<!DOCTYPE html>
<html>
<head>
<link href="http://code.jquery.com/mobile/latest/jquery.mobile.css" rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://code.jquery.com/mobile/latest/jquery.mobile.js"></script>

        <script type="text/javascript" src="http://cloud.github.com/downloads/wycats/handlebars.js/handlebars-1.0.rc.1.js"></script>

<script id="articles-template" type="text/x-handlebars-template">
<ul id="listv" data-role="listview" data-autodividers="true"  data-filter="true" data-inset="true">
  {{#entries}} 
    <li><a href="#" onClick="alert('{{title}}')">{{title}}</a></li>
  {{/entries}}
</ul>
</script>   

<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
<div data-role="page" data-theme="b" id="listview-page">

    <div data-role="header">
        <h1>Page Title</h1>
    </div><!-- /header -->

    <div data-role="content" id="listview-content"> 
        <p>
          <div id="articleHandlebars" data-demo-html="true"></div>
        </p>        
    </div><!-- /content -->

    <div data-role="footer">
        <h4>Page Footer</h4>
    </div><!-- /footer -->
</div><!-- /page -->


</body>
</html>

Javascript:

$(document).on('pagebeforeshow', '#listview-page', function(){
    parseRSS(); 
});

function parseRSS() {
      var articles = { entries: []};
      for (var i = 0; i <=4; i++)
      {
        var obj = {
          title: "test" + i
        };
        articles.entries.push(obj);
      }
      showData(articles);

}

function showData(data)
{
 var source   = $("#articles-template").html();
  var template = Handlebars.compile(source);
  var html = template(data);
  $("#articleHandlebars").html(html);   
  $("#articleHandlebars ul").listview().listview('refresh');
 }

Autres conseils

Use this syntax after you append the JSON response

$("your_list_view_id").listview('refresh');

Just a note on using handlebars (1.3.0) with jQuery Mobile (1.4.1), based on the experience we have after using it for a real life project:

Technically it works like expected and you are able to implement any UI you need with any component jQuery Mobile provides.

We faced some performance problems though, which occur because of the double-rendering required on the client side.

  1. We used the handlebar templates to generate markup, like it is suggested in the jQuery Mobile docs.
  2. After this rendering process we use .trigger("create"); to start the "enhancement" process of jQuery Mobile.

Using this approach the performance in the browser is not good, even if your REST service in the backend responds very fast (in our case 20-35ms).

The working example is refreshing twice. The page, and then the listview. A better (for me) solution, is to put the tag outside the template. So you have the id, and refreshing the listview works.

<!DOCTYPE html> 
<html>

<head>
<meta charset="utf-8">
<link href="http://code.jquery.com/mobile/latest/jquery.mobile.css" rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://code.jquery.com/mobile/latest/jquery.mobile.js"></script>
<script type="text/javascript" src="http://cloud.github.com/downloads/wycats/handlebars.js/handlebars-1.0.rc.1.js"></script>
<script>
$(document).bind('pageinit', function () {
    $.mobile.defaultPageTransition = 'none';
});
</script>
</head>     
<body> 

<div data-role="page" data-theme="d"> 
<div role="main" class="ui-content" id="Content">

<button onclick="foo()">render listview</button>

<ul data-role="listview" data-inset="true" id="listviewMenu">
</ul>

<script id="templateLV" type="text/x-handlebars-template">
    {{#.}}<li><a href="#" id="{{cat}}" class="nodeLevel1">{{label}}</a></li>{{/.}}      
</script>

</div><!-- .ui-content -->
</div><!-- Page body -->

<script>
function foo()
{
    var source   = $("#templateLV").html();
    var template = Handlebars.compile(source);
    var context = [{cat: "sample1", label: "Label One"}, {cat: "sample2", label: "Label Two"}]
    var html    = template(context);
    $("#listviewMenu").html(html);
    $('#listviewMenu').listview('refresh');
}
</script>
</body>
</html>

So there, you are only refreshing once, and you don't have that screen flashing effect when refreshing entire page

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top