theironcook / Backbone.ModelBinder

Simple, flexible and powerful Model-View binding for Backbone.
1.42k stars 159 forks source link

Jquery Mobile UI is not refreshed when the model changes #86

Open charliebecker opened 11 years ago

charliebecker commented 11 years ago

I really want to use ModelBinder as I find it incredibly useful for my application, however I'm having difficulty using it with JQuery mobile and maybe this is a defect... I have searched and tested for hours, and nothing I have found works short of binding to changes on the model (within the view) and calling: $("#bindtest").selectmenu('refresh', true);

I have created a JSFiddle to explain the issue here.

JSFiddle with code: http://jsfiddle.net/charliebecker/hbxFc/

JSFiddle so you can use "Developer Tools" to modify the model and see the issue: http://jsfiddle.net/charliebecker/hbxFc/show/light

Javascript code (sorry, not sure why it's not formatting correctly on github):

$(document).ready(function () { model = new Backbone.Model({ test: 1 }); model.bind('change', function() { $('#modelData').html(JSON.stringify(model.toJSON())); }); model.trigger('change'); // just to show the #modelData values initially, not needed for the ModelBinder ViewClass = Backbone.View.extend({ _modelBinder: undefined, initialize: function() { this._modelBinder = new Backbone.ModelBinder(); }, render: function() { var html = ''; this.$el.html(html); var bindings = { test: '[name=test]', }; this._modelBinder.bind(this.model, this.el, bindings); return this; } });

view = new ViewClass({
    model: model
});
$('#viewContent').append(view.render().el).trigger('create');

});

HTML Code:

<div data-role="page" id="pageHome" class="page-map">
    <div data-role="header" data-position="inline" data-theme="a">
        <h1>ModelBinder JQM</h1>
    </div>
    <div data-role="content">
        Model data:
        <div id="modelData"></div>
        View:
        <div id="viewContent"></div>
        <br><br>Notice that if you run the following command (using Chrome dev console or similar), model binder does does not refresh the jquery mobile ui:<br><br>
        model.set({test: "2"});<br>
        <br>
        Now if you manually refresh the select box, you can refresh the ui:<br><br>
        $('#bindTest').selectmenu('refresh',true);
        <br><br>
        Now if you remove Jquery Mobile UI references, refreshes to view occur as expected.
    </div>
</div>

Any help would be greatly appreciated!

Thanks,

Charlie

charliebecker commented 11 years ago

So no one needs to debug my code, I created a couple other JSFiddles to demonstrate the problem using Example 2 from here: https://github.com/theironcook/Backbone.ModelBinder/blob/master/examples/Example2.html

Non JQM version (working) JSFiddle: http://jsfiddle.net/charliebecker/JdXfk JSFiddle w/console: http://jsfiddle.net/charliebecker/JdXfk/show/light

JQM version (broken): JSFiddle: http://jsfiddle.net/charliebecker/zXaCq/ JSFiddle w/console: http://jsfiddle.net/charliebecker/zXaCq/show/light

On either (console version), just select the dog Biff and then run the following from the chrome (or similar) dev console: model.set({dog:{"id":1,"name":"Andy","collar":"yellow"}})

Notice how the non-JQM version updates the UI to Andy, whereas the JQM version does not.

Thanks!

Charlie

alebedev commented 11 years ago

jQuery.Mobile widgets usually require 'refresh' call to update UI when underlying element is changed programmatically. To address this, call button('refresh'), selectmenu('refresh'), etc when model is updated. IMO, custom converter is the best way to do this.

squio commented 9 years ago

What @alebedev says but... it doesn't work when the actual DOM is rendered from a template. I had to wrap the refresh call in a timeout

this.$el.find("select").selectmenu('refresh',true); // doesn't work, DOM not ready yet?

A delay of just 100 ms is enough in Chrome on OSX:

setTimeout(function() {
    // initialize pulldown elements
    self.$el.find("select").selectmenu('refresh',true);
}, 100);

Maybe a note specific for jQm / templates in the documentation would be helpful .