18

I'm using jQuery Mobile and Backbone JS for a project. It's mostly working, using jQuery Mobile's event 'pagebeforeshow' to trigger the correct Backbone View. In the Backbone View for that particular jQuery Mobile page, that's where it's doing all the dynamic things needed. Some of the things the views do is pull in certain bits using Underscore's templating system.

This is all great until where I pulling in form bits using the templating system. For example, a set of dynamic radio buttons (which are generated from a Backbone Collection). These radio buttons I want to style up using what jQuery Mobile has to offer. At the moment, jQuery Mobile is not picking up these dynamically injected radio buttons. I solved this issue previously when doing sliders by just calling the jQuery Mobile widget "slider()" method again and it seemed to refresh them... This doesn't seem to be the case with these radio buttons.

In the Backbone View, I tried calling the widget methods again:

$(this.el).find("input[type='radio']").checkboxradio();
$(this.el).find(":jqmData(role='controlgroup')").controlgroup();

I tried them the other way around too, but it seemed I need to do it this way for the grouping styling to work etc. But this just doesn't seem right! ...doing this also caused errors when I clicked on the radio buttons, saying: "cannot call methods on checkboxradio prior to initialization; attempted to call method 'refresh'"?

It seems there should be a way in jQuery Mobile to re-initialize the page or something?! I noticed there is a 'page' widget in the source code.

How does jQuery Mobile handle forms/elements being injected into the DOM after the page is made? Is there a clean way of handling how it makes up the forms? There must be a clean way of calling on the forms to render 'the jQuery Mobile way' without it just relying on data attribute tags in the base HTML?

Any help or insight into this problem would be greatly appreciated... I'm very much on this quest of trying to get Backbone JS and jQuery Mobile to work nicely together.

Many thanks, James

littlejim84
  • 9,071
  • 15
  • 54
  • 77

11 Answers11

19

update

Since jQueryMobile beta2 there is an event to do this. .trigger('create') on an element to cause everything inside it to be painted correctly.

Another question that is not a duplicate, but requires an answet I posted over 10 times :)

[old answer]

try .page()

More details in my faq: http://jquerymobiledictionary.pl/faq.html

naugtur
  • 16,827
  • 5
  • 70
  • 113
  • Thank you. I followed your words. In this particular case I had to use $(element).page("destroy").page() for some reason? But even this didn't quite work. It rendered the content correctly, but it's not working right. Getting the same error: "cannot call methods on checkboxradio prior to initialization; attempted to call method 'refresh'"... strange. – littlejim84 Apr 14 '11 at 10:28
  • `.page` can be called once on an element. you have to create a wrapping div around the content you add dynamically. – naugtur Apr 14 '11 at 11:04
  • ugh, that is stoopid. so if i have a page thats 100% ajax and i want to re load my options over and over, I have to create a wrapping element each time! must be a better way. – Michael Dausmann Jun 06 '11 at 23:52
  • 1
    If you want it to be nice - create the HTML once - in a .html file and never overwrite any DOM nodes, just get data as JSON and put it in correct places with $(element).text(). When expanding listviews, use .listview('refresh'). When using form elements - use their refresh methods. If not avaliable - rebuild only the problematic control. – naugtur Jun 08 '11 at 17:22
5

I'm not sure if this helps but when adding dynamic elements I was using .page() in the sucess ajax call itself (example here and here) but I found that it was not working as expected. I found that in the ajax call it's better to refresh the element (if it's a form element) to use these documented methods:

  • Checkboxes:

    $("input[type='checkbox']").attr("checked",true).checkboxradio("refresh");
    
  • Radios:

    $("input[type='radio']").attr("checked",true).checkboxradio("refresh");
    
  • Selects:

    var myselect = $("select#foo");
    myselect[0].selectedIndex = 3;
    myselect.selectmenu("refresh");
    
  • Sliders:

    $("input[type=range]").val(60).slider("refresh");
    
  • Flip switches (they use slider):

    var myswitch = $("select#bar");
    myswitch[0].selectedIndex = 1;
    myswitch .slider("refresh");
    

and for adding a non-form element use .page()

Community
  • 1
  • 1
Phill Pafford
  • 83,471
  • 91
  • 263
  • 383
5

Refreshing the whole page worked for me:

$('#pageId').page('destroy').page();
Jaime Botero
  • 2,263
  • 2
  • 22
  • 14
2

Try calling .trigger("create") on the element with the new content.

Pavel Savara
  • 3,427
  • 1
  • 30
  • 35
2

JQuery Mobile now supports .trigger("create"); which will resolve this for you

Rob Fuller
  • 514
  • 2
  • 7
1

It worked for me when I called .trigger('create') on the enclosing div element. See example below:

In .html file:

<div id="status-list" data-role="fieldcontain">
    <fieldset data-role="controlgroup">
        <legend>Choose as many snacks as you'd like:</legend>
            <input type="checkbox" name="checkbox-1a" id="checkbox-1a"/>
            <label for="checkbox-1a">Cheetos</label>
    </fieldset>
</div>

in .js file:

$("#status-list").trigger('create');
Jesper Bischoff-Jensen
  • 1,460
  • 2
  • 11
  • 20
1

I needed a way to dynamically refresh a JQM page after it had been initialized. I found that if I removed the data attribute "page" during the "pagehide" event, the next time the JQM page was displayed it was re-initialzed.

$('#testing').live('pagehide', function (e) {
    $.removeData(e.target, 'page');
}); 
Scott Woodall
  • 10,456
  • 6
  • 39
  • 37
  • nice trick. I hope it's irrelevant since the create event exists, but still good to know there's something like 'page' key in data – naugtur Oct 13 '12 at 08:42
1
$('#pageId').page('destroy').page(); 

works for entire control groups that are generated, let alone radio input children.

-Mike

0

I little bit off topic. I wanted to be able to stop jqm from creating first default page div on init as backbone wraps elements in divs anyway. I wanted to dynamically insert pages to the DOM and then call jqm to create its classes and widgets. I finally did this like this:

 <head>
 <script src="jquery-1.8.3.js"></script>
 <script type='javascript'>
 $(document).on("mobileinit", function () {  
 $.mobile.autoInitializePage = false;       
 }
 </script>
 <script src="jquery.mobile-1.3.0-beta.1.min.js"></script>
 </head>
 <body>
 ....... dynamically add your content ..........

 <script type='javascript'>
 $.mobile.initializePage() 
 </script>
 </body>

and my hole jqm config (which you put before jqm.js)

$(document).on("mobileinit", function () {
  $.mobile.ajaxEnabled = false;
  $.mobile.hashListeningEnabled = false;
  $.mobile.pushStateEnabled = false;
  $.mobile.linkBindingEnabled = false; // delegating all the events to chaplin
  $.mobile.changePage.defaults.changeHash = false;

  $.mobile.defaultDialogTransition = "none";
  $.mobile.defaultPageTransition = "slidedown";
  $.mobile.page.prototype.options.degradeInputs.date = true;
  $.mobile.page.prototype.options.domCache = false;
  $.mobile.autoInitializePage = false;

  $.mobile.ignoreContentEnabled=true;
}); 

So far Backbone and JQM been working fine.

zzart
  • 11,207
  • 5
  • 52
  • 47
0

Try use enhanceWithin() method. This should be method of any jQuery object while using jQuery Mobile.

Andree
  • 1,159
  • 2
  • 17
  • 32
0

For me only .page() worked (without the .page('destroy')).

E.g.:

$('my-control-group-id').page();

Amnon

Jérôme Verstrynge
  • 57,710
  • 92
  • 283
  • 453