4

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!

Gajotres
  • 57,309
  • 16
  • 102
  • 130
None None
  • 537
  • 2
  • 8
  • 15
  • In which order to you include your custom css compared to the jqueryui css? Specificity is very important when trying to override jquery ui styling. – Lowkase Apr 08 '13 at 19:31
  • I don't have any custom CSS yet. The problem is, the generated view doesn't inherit the native jquery mobile CSS. If I insert the same code directly into the body and make the content of the listview static, the CSS is applied. But when I use handlebars, CSS gets ignored. – None None Apr 08 '13 at 19:34
  • 1
    Tell me at what point you execute function showData? Or what are you using to execute it, document ready or jQuery Mobile page event? – Gajotres Apr 08 '13 at 19:36
  • I have several functions, but the flow is as follows: - It all starts in document.ready, where I call a function called "ParseRSS" - Within ParseRSS, I use $.ajax, and on "success:" I handle data that is returned. When array of JSON objects is created, I call showData. – None None Apr 08 '13 at 19:45

4 Answers4

5

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');
 }
Lou Franco
  • 87,846
  • 14
  • 132
  • 192
Gajotres
  • 57,309
  • 16
  • 102
  • 130
  • Unfortunately, this doesn't seem to work. I've done everything as you suggested, did all the combinations, to no avail. – None None Apr 08 '13 at 20:09
  • I've put an example in the original post, here's the link: http://jsbin.com/adurar/1/edit – None None Apr 08 '13 at 20:14
  • 1
    You had 2 problems. First you can initialize jQuery Mobile before jQuery. And never used documen ready with jQuery Mobile page. Usualy it will trigger before content is in DOM. Instead use jQM page events, like in my fix. – Gajotres Apr 08 '13 at 20:20
  • Thank you very much! I see the code, but I'm not fully sure I understand why you changed the order of includes... care to elaborate? – None None Apr 08 '13 at 20:22
  • Simply jQuery Mobile needs jQuery to work correctly, thus you need to initialize jQuery first. Do you have more questions? – Gajotres Apr 08 '13 at 20:23
  • Thanks for explanation. I will defiantly take your comments into the consideration. – None None Apr 08 '13 at 20:24
  • 1
    This could also interest you: http://stackoverflow.com/a/14469041/1848600. It is my other answer about difference between document ready and jQM page events. – Gajotres Apr 08 '13 at 20:24
0

Use this syntax after you append the JSON response

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

Java Devil
  • 10,629
  • 7
  • 33
  • 48
user1452840
  • 221
  • 1
  • 4
  • 9
0

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).

staabm
  • 1,535
  • 22
  • 20
0

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

Gonzalo
  • 752
  • 8
  • 23