3

I load a html-partial into a ng-view directiv via a controller in AngularJS. The html-partial looks like this:

<div>
    <ul data-role="listview" data-inset="true" data-theme="c">
        <li><a href="#/detailsuser/a">A</a></li>
        <li><a href="#/detailsuser/b">B</a></li>
        <li><a href="#/detailsuser/c">C</a></li>
        <li><a href="#/detailsuser/d">D</a></li>
    </ul>
</div>

The problem is that the listview does not get rendered into a jquery-mobile-control. What is wrong?

5
  • you need to use jQuery code $('[data-role=listview]').listview('refresh'); Commented Jun 5, 2013 at 14:51
  • @Omar where should I put that code? Commented Jun 5, 2013 at 14:57
  • it depends how you append the items. Commented Jun 5, 2013 at 16:14
  • I append them through binding like this: <ul data-role="listview" data-inset="true" data-theme="c" data-ng-repeat="customer in customers | orderBy:'lastName'"> <li><a href="#/customerdetails/{{customer.id}}" rel="external">{{customer.firstName + ' ' + customer.lastName}}</a></li> </ul> Commented Jun 5, 2013 at 16:16
  • 1
    hmmm..try this $(document).on('pagebeforeshow, '#pageID', function () { $('[data-role=listview]').listview('refresh'); }); put it inside body. Commented Jun 5, 2013 at 16:49

2 Answers 2

4

I got it to work. Here is what I did:
I made a new directive that I append on the ul-element. It waits until the last li-element is rendered, then I call the trigger on the jqueryMobileTpl directive.

app.directive('jqueryMobileTpl', function () {
    return {
        link: function (scope, elm, attr) {
            //elm.trigger('create');
        }
    };
});
app.directive('repeatDone', function () {
    return function (scope, element, attrs) {
        // When the last element is rendered
        if (scope.$last) { 
            element.parent().parent().trigger('create');
        }
    }
});

and

<div jquery-mobile-tpl>
    <ul data-role="listview" data-inset="true" data-theme="c" data-ng-repeat="customer in customers | orderBy:'lastName'" repeat-done="" ng-cloak>
        <li><a href="#/customerdetails/{{customer.id}}" rel="external">{{customer.firstName + ' ' + customer.lastName}}</a></li>
    </ul>
</div>

Thank you @CaioToOn and @Omar !!!

Sign up to request clarification or add additional context in comments.

Comments

3

This problem is not related to AngularJs. It happend that jQuery Mobile is not aware of every DOM change, and you need to give it a tip. To adivice jQuery Mobile about the change, you need to trigger a create event on the element.

According to the docs (look at "Enhancing new markup"):

However, if you generate new markup client-side or load in content via Ajax and inject it into a page, you can trigger the create event to handle the auto-initialization for all the plugins contained within the new markup. This can be triggered on any element (even the page div itself), saving you the task of manually initializing each plugin (listview button, select, etc.).

So all you got to do is to trigger the create event just after the content has been included.

I'd suggest you to create a directive that simply triggers the event on the templates for you. Something like:

app.directive('jqueryMobileTpl', function() {
  return {
    link: function(scope, elm, attr) {
      elm.trigger('create');
    }
  };
});

Then you just add this directive to the root element of the template:

<div jquery-mobile-tpl>
  <ul data-role="listview" data-inset="true" data-theme="c">
    <li><a href="#/detailsuser/a">A</a></li>
    <li><a href="#/detailsuser/b">B</a></li>
    <li><a href="#/detailsuser/c">C</a></li>
    <li><a href="#/detailsuser/d">D</a></li>
  </ul>
</div>

You could make this directive low priority, so if you use other directives that might change the template, this one would wait for all changes before telling jQuery Mobile to render. Working sample here.

5 Comments

I tried your solution and it works! But if I try to load the list dynamically, the control does not get rendered. <div jquery-mobile-tpl> <ul data-role="listview" data-inset="true" data-theme="c" data-ng-repeat="customer in customers | orderBy:'lastName'"> <li><a href="#/customerdetails/{{customer.id}}" rel="external">{{customer.firstName + ' ' + customer.lastName}}</a></li> </ul> </div>
Which control? Angular controller?
The <ul data-role="listview" does not get rendered if I apply data-ng-repeat="customer in customers | orderBy:'lastName'"
Your question is answered in the start of my answer, you need to trigger create event to tell jQuery Mobile to render the content. The problem is that jQuery Mobile is rendering the content before AngularJS changes the DOM, and this is changing the HTML. So you can't use this directive I've suggested, instead, you need to figure out the better moment to trigger. You should google for how to use AngularJs and jQuery Mobile. I found this guy in a search, don't know, but might be a good one, still, for another question.
Using @Omar suggestion of listview('refresh') after some seconds did worked on the Plunker I sent you. But this is going to be a hard task. I'd rather search for some already written integration solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.