Using Backbone.js with jQuery Mobile

Backbone.js is an architectural framework that helps you write well-structured Web applications. It is not, however, a user interface framework and it therefore doesn’t help you with the way your application looks.

Backbone’s confined scope is a good thing: it’s lightweight, non-intrusive, not coupled to things you don’t need, and it lets you use the UI toolkit of your choice or simply roll your own styles and widgets. In my previous post, I demonstrated how to use Twitter Bootstrap on top of Backbone.

Quest for a Mobile UI Toolkit

After that post, I wanted to create a mobile version of the same application; a version that I could package with PhoneGap and that would look and behave like a native app. Twitter Bootstrap can probably be tweaked for that purpose as well, but I was looking for a UI toolkit dedicated to providing native looking controls and behaviors on mobile devices.

Another Way to Use jQuery Mobile

jQuery Mobile (jQM) is one option that I’ve explored before (here and here), but it fits more in the category of full-stack frameworks that tie together architectural structure and UI controls and behaviors. John Bender, my colleague at Adobe and member of the jQuery Mobile team, recently pointed out to me that you can disable the routing and navigation capabilities of jQM, and essentially use it as a pure UI framework on top of other architectural frameworks like Backbone.js.

Sample Application

I ended up spending a decent amount of time trying different things to get the two frameworks to play well together without stepping on each other. To save you some headaches if you are trying to do the same, I put together a simple application with the basic setup to combine Backbone (for the application structure and “routing”) and jQuery Mobile (for its styles and widgets).

NOTE: Another approach would be to use jQM’s “routing” instead of Backbone’s. Ben Nolan has an example of this approach here. I prefer to use Backbone’s routing because I find it more flexible and less “page-centric”.

Here is the app:

Click here to run the application in a separate window. The source code is available in this GitHub repository.

How it works

The key to this approach is to disable jQuery Mobile’s “routing”: In other words, you need to tell jQuery Mobile not to handle links, hash tag changes, and so on. I isolated that code in jqm-config.js:

$(document).bind("mobileinit", function () {
    $.mobile.ajaxEnabled = false;
    $.mobile.linkBindingEnabled = false;
    $.mobile.hashListeningEnabled = false;
    $.mobile.pushStateEnabled = false;
});

If jQuery Mobile is not in charge of page navigation, you also have to manually remove the pages from the DOM when they are not used anymore. Here is one way to do it:

$('div[data-role="page"]').live('pagehide', function (event, ui) {
    $(event.currentTarget).remove();
});

With this configuration in place, you use Backbone’s routing as usual:

var AppRouter = Backbone.Router.extend({

    routes:{
        "":"home",
        "page1":"page1",
        "page2":"page2"
    },

    home:function () {
        this.changePage(new HomeView());
    },

    page1:function () {
        this.changePage(new Page1View());
    },

    page2:function () {
        this.changePage(new Page2View());
    },

    changePage:function (page) {
        $(page.el).attr('data-role', 'page');
        page.render();
        $('body').append($(page.el));
        $.mobile.changePage($(page.el), {changeHash:false});
    }

});

Is this the right stack?

I like the idea of a lightweight architectural framework combined with a UI toolkit. Backbone + Twitter Bootstrap felt right because the two frameworks have different areas of concern and complement each other very well. I was happy to see you could decouple jQM from its navigation infrastructure. However, that’s probably not the main “design center” at this point. I think it would be interesting for jQM to focus on that utilization scenario as well. At the end of the day, frameworks are often a matter of personal preferences, and not all applications are equal. So try it, see if it works for you, and share your experience. What UI toolkit are you using?

Source Code

The source code is available in this repository on GitHub.

A More Real-Life Application

In my next post, I’ll share a Backbone.js + jQuery Mobile version of the Employee Directory application first explored with Backbone.js + Twitter Bootstrap.

60 Responses to Using Backbone.js with jQuery Mobile

  1. andy matthews March 5, 2012 at 8:47 pm #

    I’m working with other members of the jQuery Mobile community on the jQuery Mobile Cookbook (to be released by O’Reilly). There’s going to be an entire chapter on utilizing jQM for large scale applications. Connecting with Backbone and Knockout will be two the recipes.

    • Joshua Smith March 28, 2013 at 3:57 am #

      Andy~

      Has this book been published… I have been working on a jquery mobile project trying to plug it into mvc… but am having problems,

  2. John Fawcett March 8, 2012 at 4:50 am #

    Would just like to point out that this posting has been immensely helpful in starting my project a couple of days ago. I had little experience in backbone and none in jQuery Mobile so knowing that the routing systems clashed was awesome.

    I initially did things your way, but I’d like to share my method. I couldn’t get configuration on “mobileinit” to work consistently for some reason, so I listened to the “pagebeforechange” event.
    // Prevent jqm from handling routes
    $(document).on(‘pagebeforechange’, function(e, data){
    // Only on url updates, non-jquery elements
    if (typeof data.toPage === “string”) {
    e.preventDefault();
    var url = $(‘‘).attr(‘href’,data.toPage)[0].pathname; // Get our path
    app.router.navigate(url, {trigger: true});
    }
    })
    In my Route:
    var page = new app.Views.TestPage();
    page.render();
    $.mobile.changePage($(page.el), {changeHash: false});

    In addition, I put the jquery page enhancement stuff inside the views render method:
    render: function(){
    $(this.el).html(app.templates.test());
    $(‘body’).append($(this.el));
    $(this.el).page();
    return this;
    }

    The main thing that bugged me about your solution is the use of the deprecated ‘live’ function. Why not just use ‘on’? Furthermore, we can put that event directly on the view:
    views.TestPage = Backbone.View.extend({
    events: {
    ‘pagehide': ‘onPageHide’
    },

    onPageHide: function(){ $(this.el).remove(); }
    });

    Either way, thanks a lot!

    • John Fawcett March 8, 2012 at 4:54 am #

      Yeah, that’s all sorts of horrid formatting. Should be:
      var url = $(‘<a />‘).attr(‘href’,data.toPage)[0].pathname; // Get our path

      • David A. May 21, 2012 at 12:25 pm #

        Hi John Fawcett,
        thanks for your enhancement.
        Do you have an full example somewhere public?

  3. M van Dillen March 14, 2012 at 2:20 pm #

    Thanks, dropping the jqm-config.js in my project fixed the navigation for me.

  4. John Paul Narowski March 26, 2012 at 6:05 pm #

    I feel your pain about the mobile UI toolkit. I have been on the quest to find the “right” mobile framework for some time now. My biggest issue is that I have a large web app who’s features keep growing, but to have this codebase also work for mobile has been a huge headache.

    I started with Titanium, then moved to Sencha touch, which is where my mobile app resides. The problem is that the code is completely separate from my app so nothing is shared. I want to move to a Backbone.js powered UI that I could then “share” with my mobile apps. This solution comes close so I’m happy to see you struggling with the same issues. What I’d really love is to use Sencha Touch’s animations and UI components with Backbone but so far haven’t had any luck.

    Do you do any freelancing work, I’d love to chat with you more about these experiences as I think we’re on the same page in terms of the mobile UI framework struggle.

    Anyways awesome posts, I am going to read through the others and appreciate you taking the time to pave the path.

  5. Ronald March 26, 2012 at 8:22 pm #

    Thanks a lot for you ideas, I got my own backbonejs jquery mobile sample working :) if you want to you can check it out at https://github.com/ronaldpatino/backbone-namespace/tree/jqm. I think I can move to the next step now.

  6. Presley April 4, 2012 at 5:47 pm #

    Thank you for the article, you saved the day. I have experimented a lot with this and also the other alternative (not using the backbone.js routing) and I like your approach.

    I just want to add you don’t have to remove the pages from the DOM. They can still be there after you have changed the page. You will need to remove them only if you are afraid that the DOM will get too big, otherwise, you don’t need to. Correct me if I’m wrong.

    One more thing, do you know a convenient way of how to set the transition, I mean every change page needs to have its own transition and the only way I figured how to do this is to pass the transition it in the url (which is ungly) or use global variable (which is still not very beautiful approach).

    Thank you again!

    • Seth Howard September 26, 2012 at 9:29 pm #

      Just to follow up above, to prevent the DOM from removing the elements, remove or comment this line from jqm-config.js

      // $(‘div[data-role=”page”]’).live(‘pagehide’, function (event, ui) {
      // $(event.currentTarget).remove();
      // });

      In this case, you will have to rearrange the router works so that views aren’t instantiated every time you switch pages, instead just load them up all at once. If they’re dependent on a model then trigger the model to re-render on change or reset.

  7. Harley April 10, 2012 at 12:14 pm #

    you can use this.$el instead of $(this.el). fuckyeah backbone <3

  8. Dipin Kumar Krishnan April 20, 2012 at 1:44 am #

    This post helped me to solve a blocker in my project. But, my doubt now is, can we have the mobile gestures like, swipe, tap, swipe left etc as events in the view?
    For example
    Events:{
    “tap #btnSignIn”:”doSignIn”
    }
    Does backbone support these mobile gestures?

  9. Ruben Müller May 10, 2012 at 12:30 pm #

    Thank you for your post, it helped me alot to get started! :)

  10. Mike May 17, 2012 at 12:40 pm #

    Thanks for the providing this.

    I’m trying to figure out how to include a fixed footer navbar within this framework that navigates between the pages without reproducing it within each of the pages. Any hints as to how this would be done?

  11. dunhakdis May 28, 2012 at 1:57 am #

    This is not working anymore with jquery.mobile-1.1.0.min.js

    • DavidAm May 28, 2012 at 7:15 pm #

      For me, it is working with 1.1.0 -

  12. Jared June 20, 2012 at 9:45 pm #

    This was very helpful, thanks! Just curious if anyone else is having trouble with routes containing slashes when using this method. In my routes table I have an entry like “:page/:query” and it’s only getting hit after a second click. The first click seems to change the page’s url. Btw, it works if I change the slashes to some other character.

  13. Rafael June 22, 2012 at 12:40 am #

    Thank you for your post, it was very helpful in getting backbone and jquery mobile working together.
    Has anybody experienced problems with certain jquery mobile form controls such as the collapsible lists? In my case, when I let the router (with the changes you suggested) change me to a page that contains theses types of controls they don’t come out right. When I reload the page manually the page is rendered correctly. Any clues as to what might be causing this? (Other controls don’t have these problems)

  14. TheMCME June 25, 2012 at 2:56 am #

    Thanks for the tutorial. There is problem with footers/navbars though, it doesn’t show the active item in the bar unless you click 2 times in a row on the item, I think it’s because the way the changePage method in the router creates a new page and removes the old one… Don’t know yet how to fix that and some help would be appreciated! Thanks.

  15. Garris June 27, 2012 at 6:46 am #

    I appreciate this post. Earlier this year I built http://icon.spigit.com/. I used knockout.js with jQuery mobile and a CSS framework for responsive apps. I am pretty happy with this stack — it was very quick to get a clean integration going and my team was able to deliver the first release in a little over 3 months. For the first iteration I went with a stock implementation of jQM using the built-in link binding and hashchange mgmt. I was surprised with how far it got me. I added some state keeping params in the URL with BBQ also. Eventually, I want to clean up the URL window with more of a hash bang format and I am looking at pathjs for that. Thanks for this post — it is a great starting point for me to add in the new router.

  16. Mark August 2, 2012 at 12:48 am #

    FYI, the Backbone book, http://addyosmani.github.com/backbone-fundamentals/, talks about how to get Backbone and JQM to cooperate, by disabling JQM’s router. Search for “Backbone & jQuery Mobile”.

    • Andrea Rota October 31, 2012 at 1:54 pm #

      Actually the approach suggested in the Backbone book is not working. The minimun configuration I found working is: $.mobile.linkBindingEnabled = false; $.mobile.hashListeningEnabled = false;

  17. Wayne August 16, 2012 at 12:09 pm #

    Just discovered that the ‘pagehide’ event monitor needs to watch for dialogs as well:

    $(‘div[data-role=”page”],div[data-role=”dialog”]’).live(‘pagehide’, function (event, ui) {
    $(event.currentTarget).remove();
    });
    gist here: https://gist.github.com/3369688

  18. Adrian September 3, 2012 at 12:27 pm #

    Thanks for the post! It is truly useful. Any news regarding the second part?

  19. fangzx October 13, 2012 at 2:41 am #

    Use this routing method, it is difficult to show popup in new jquery mobile 1.2. Anyone can help?

  20. Jose Carrillo October 16, 2012 at 9:50 pm #

    How would you apply this technique on a website built on php?

    Thanks

  21. Leandro Costa November 9, 2012 at 10:31 am #

    There’s a problem with jqm-config.js + with many options.
    JQM renders in different ways depending on their sizes [see http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.js line 8553] . If the widget is too big JQM creates a new page and changes to it. When the execution gets line 3928 JQM tries to call active.url.indexOf( dialogHashKey ) , but active.url is undefined. Does anybody know how to solve this problem?

    • Josh Schneider November 26, 2012 at 11:51 pm #

      Using jQM with Knockout and Sammy, and using all the usual jQM config settings to allow Sammy to control routing (including $.mobile.linkBindingEnabled=false), but now older Android, particularly, has issues with link event handling. Not only are jQM link event styles unhooked (buttons and listview items don’t change color on touch), but the entire event goes unhandled. Touch events work reasonably well in most other phones. Anyone else experienced this and have a workaround they’ve used to fix the issue? I wish there were a config to just get jQM to handle touch abstraction and event UI, but leave routing to another framework.

    • Seth December 29, 2012 at 8:08 am #

      Leandro,

      Getting the same issue. Were you able to come up with a resolution?

  22. dan December 13, 2012 at 5:48 am #

    Hi there.. love this but is can you suggest why this doesnt work on a windows phone 7? and what the possible solution may be? (apart from to get a better phone..)

  23. Sunny December 31, 2012 at 5:31 am #

    Hi

    I wanted to append the html in a div instead of body. But i am getting error.
    I want to create 3 regions header, content and footer and only want to change the content area.

    Thanks,
    Sunny

  24. Luis February 14, 2013 at 3:52 pm #

    Hey, this code saved me from a lot of headaches.

    Thanks a lot!

    If you are interested i’ve ported the javascript version of the code to coffeescript in https://gist.github.com/luiscronicl/4953670

  25. ryo February 20, 2013 at 10:04 pm #

    two hours pulling my hair to trigger jqmobile restyle my page.
    that’s the cure!
    $.mobile.changePage($(page.el), {changeHash:false});

  26. Chris Lee March 13, 2013 at 6:39 am #

    When pages scroll back, the direction is wrong!

  27. fake louis vuitton coin pouch March 17, 2013 at 4:56 am #

    Besides, I can still get the scent from fabric softener and dryer sheets.Tagged with cleaning productsI use Tide Simple Pleasures for all of my laundry. Simple fake louis vuitton coin pouch http://fakelouisvuittonspeedy.blogspot.com/

  28. John Kevin M. Basco March 24, 2013 at 12:59 pm #

    Hi, thanks for this post. It helped me a lot! Anyway if we are navigating from 1 page to another, do we still need to unbind the events attached to the previous page to avoid ghost views? Since I can see you only remove the page when rendering a new page like this:

    // Remove page from DOM when it’s being replaced
    $(‘div[data-role=”page”]’).live(‘pagehide’, function (event, ui) {
    $(event.currentTarget).remove();
    });

    Should we do something like:

    // Remove page from DOM when it’s being replaced
    $(‘div[data-role=”page”]’).live(‘pagehide’, function (event, ui) {
    $(event.currentTarget).remove();
    $(event.currentTarget).close();
    });

  29. Mike April 10, 2013 at 6:47 pm #

    You’re a saint. Worked for me with jQM & angular.

    • Edgardo March 1, 2014 at 1:02 pm #

      Hi Mike,

      Can you send sample of code on how you have done jQM with Angular please.
      Thanks.

  30. ANDROID 4.1 TABLET online June 10, 2013 at 10:16 am #

    Thanks for any other informative site. The place else
    may I get that kind of info written in such an ideal manner?
    I have a venture that I’m just now running on, and I’ve been on the look
    out for such information.

  31. Anna June 24, 2013 at 7:10 am #

    I was really searching for such a nice post…Thanks for sharing such a nice information, its beneficial for me…Keep sharing more.
    Mobile Apps Development USA

  32. Andi August 1, 2013 at 8:29 am #

    Hey Christopher,

    thanks for this nice article. Although it’s from 2012, this topic is still up-to-date. I’m using DurandalJs (http://durandaljs.com/), another cool modularization framework, to organize my webapps. I also want to combining it with jQuery Mobile and your configuration points me to the right direction :-)

    Go on with this sort of articles.
    Best regards,
    Andi

  33. Tommy August 8, 2013 at 4:39 am #

    Hi guys,

    have you try to run this app in android emulator or maybe in IBBDemo2 – iPhone and iPad simulator, because this don’t work in them. I tried to run on android 2.3 device and it worked.
    So I am confused a bit , does this combination of backbone + jqm work well on most platforms or this is just bug in simulators.
    Do you have similar experience ??

    Regards,
    tommy

  34. Mission Mobile September 3, 2013 at 5:53 am #

    Hello,

    thank you for this realy helpful information. We also develope Mobile Apps, and Backbone.js is also an option for us. But it sounds very interesting….

  35. Nicholas Cole March 12, 2014 at 8:15 am #

    Nice post Christophe, I am using Kendo UI for current projects which is working well – great widgets and nice ‘native’ feel. Thanks again for the post.

  36. Monster Warlord Hack May 17, 2014 at 10:15 am #

    I truly love your site.. Great colors & theme. Did you create this site yourself?
    Please reply back as I’m planning to create my very own blog
    and would love to find out where you got this from or exactly what the theme is called.

    Kudos!

  37. clash of clans hack android June 13, 2014 at 10:31 pm #

    I know thiss if off topic but I’m looking into starting my own blog annd was wondering what alll iis needed to get seet up?

    I’m assuming having a blog like yours would cost a pretty penny?
    I’m not very web savvy sso I’m not 100% sure.
    Any suggestions or advice would be greatly appreciated.
    Cheers

  38. ask fm Hack June 26, 2014 at 4:10 am #

    Having read this I thought it was very enlightening.
    I appreciate you finding the time and energy to put this information together.
    I once again find myself spending way too much time both reading and posting comments.
    But so what, it was still worthwhile!

  39. robert December 4, 2014 at 7:01 am #

    Organic SEM is more extended phrase for efficient SEO solutions which includes marketing of email, on the internet marketing, outcomes of company, support of google and classified ads. here are the findings

Trackbacks/Pingbacks

  1. Employee Directory Sample App with Backbone.js and jQuery Mobile - March 8, 2012

    […] described in my previous post, jQuery Mobile was (at least initially) intended as a full-stack framework as opposed to a pure UI […]

  2. Employee Directory Sample App with Backbone.js and jQuery Mobile - March 8, 2012

    […] described in my previous post, jQuery Mobile was (at least initially) intended as a full-stack framework as opposed to a pure UI […]

  3. developpement mobile | Pearltrees - March 8, 2012

    […] Using Backbone.js with jQuery Mobile Quest for a Mobile UI Toolkit After that post, I wanted to create a mobile version of the same application; a version that I could package with PhoneGap and that would look and behave like a native app. Twitter Bootstrap can probably be tweaked for that purpose as well, but I was looking for a UI toolkit dedicated to providing native looking controls and behaviors on mobile devices. Backbone’s confined scope is a good thing: it’s lightweight, non-intrusive, not coupled to things you don’t need, and it lets you use the UI toolkit of your choice or simply roll your own styles and widgets. In my previous post , I demonstrated how to use Twitter Bootstrap on top of Backbone. […]

  4. Using Backbone.js with jQuery Mobile | designoMatt - March 29, 2012

    […] christophe coenraets […]

  5. 使用JQuery Mobile + RequireJS + BackboneJS模块化开发移动应用 | RIA分享|这里是RIA的时刻 - April 27, 2012

    […] 可以看到,在jqm.config.js中,我们在document上绑定了mobileinit事件的侦听器,在侦听器方法中执行了对JQuery Mobile的设置。mobileinit事件是JQuery Mobile的初始化事件。由此,该绑定必须发生在应用加载执行JQuery Mobile类库(jquery.mobile-1.1.0.js)之前。这也是为什么我们在app.js中通过require加载jqm的原因。 关于”backbone和JQuery Mobile的适配”的问题,可以进一步参考CHRISTOPHE COENRAETS的blog:“Using Backbone.js with jQuery Mobile” […]

  6. Getting started with HTML mobile application development using jQuery mobile, RequireJS and BackboneJS | Appliness - June 14, 2012

    […] to workaround it. I like the magic from Christophe Coenraets (Using Backbone.js with jQuery Mobile: http://coenraets.org/blog/2012/03/using-backbone-js-with-jQuery-mobile/) […]

  7. Getting started with HTML mobile application development using jQuery Mobile, RequireJS and BackboneJS | TechnoVeille - September 3, 2012

    […] to workaround it. I like the magic from Christophe Coenraets (Using Backbone.js with jQuery Mobile: http://coenraets.org/blog/2012/03/using-backbone-js-with-jQuery-mobile/) […]

  8. [Javascript] Un nuovo modo di scrivere il front-end con Backbone.js + CoffeeScript - October 28, 2012

    […] realizzazione di Single-Page Application e di web app per il mobile (Using backbone.js with jQuery Mobile) […]

  9. Using Backbone.JS with jQuery Mobile | Appliness - December 5, 2012

    […] This article was written by Christophe Coenraets and appeared in the June issue of Appliness. The article originally published on his blog at http://coenraets.org/. […]

  10. Building radvisor.net ✩ Mozilla Hacks – the Web developer blog - January 30, 2013

    […] It also includes HTML5 history support via Backbone.Router which makes it easy to translate a UX flow to a set of routes and views.[^footnote] (jQuery Mobile also has its own router – which you must disable if you want to use Backbone’s) […]

  11. 开发Web App的一些工具和经验总结 | qhm123(鸣)'s blog - March 9, 2013

    […] Backbone.js 提供了Model,Collection,Router,View等实现了Web App的MVC模式。MVC可以很好的降低Rich Client App的复杂度。基于Backbone.js的Mobile Web App有一个比较不错的案例是LinkedIn Mobile。Backbone.js代码基于Underscore.js等。Backbone.js和jQueryMobile的组合有一定的价值,前文介绍过jQueryMobile,但是Backbone.js和jQueryMobile的组合会存在冲突问题,可以参考这里的一种解决方案进行处理。 […]

Leave a Reply

css.php