-2

I follow the example from this book https://leanpub.com/marionette-gentle-introduction. My problem is that the view does not rerender when i change the model by clicking on the button. As the answer from this question , i don't need to do anything because Backbone/MarionetteJS smart enough to change the view. Here is the code

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Demo marionettejs</title>
        <script src="./vendors/jquery/dist/jquery.js" type="text/javascript"></script> 
        <script src="./vendors/underscore/underscore.js" type="text/javascript"></script>
        <script src="./vendors/backbone/backbone.js" type="text/javascript"></script>
        <script src="./vendors/backbone.marionette/lib/backbone.marionette.js" type="text/javascript"></script>
    </head>
    <body>
        <div id="main-region" class="container">
            <p>Here is static content in the web page. You'll notice that it gets
                replaced by our app as soon as we start it.</p>
        </div>
        <script type="text/template" id="contact-template">
            <p><%- firstName %> <%- lastName %> : <%- time %> </p> <br /> 
            <button>Change model</button>
        </script>
        <script type="text/javascript">
            var ContactManager = new Marionette.Application();
            ContactManager.Contact = Backbone.Model.extend({});
            ContactManager.ContactView = Marionette.ItemView.extend({
                template: "#contact-template",
                initialize: function () {
                    this.currentMeterId = null;
                },
                events: {
                    "click button": "changeModel"
                },
                modelEvents: {
                    "change": "modelChanged"
                },
                changeModel: function() {
                    this.model.set("time", (new Date()).toString());
                },
                modelChanged: function() {
                    console.log("Model changed : " + this.model.get('time'));
                },
                //EDIT
                onRender: function() {
                     //Create jsTree here.
                }
            });
            ContactManager.on("before:start", function () {
                var RegionContainer = Marionette.LayoutView.extend({
                    el: "#app-container",
                    regions: {
                        main: "#main-region"
                    }
                });

                ContactManager.regions = new RegionContainer();
            }); 
            ContactManager.on("start", function () { 
                var alice = new ContactManager.Contact({
                    firstName: "Alice",
                    lastName: "Arten",
                    time: "#"
                }); 
                var aliceView = new ContactManager.ContactView({
                    model: alice
                });
                ContactManager.regions.main.show(aliceView);
            });
            ContactManager.start();
        </script>

    </body>
</html>

@Edit This code is just sample. In my real app, I have an ajax task that changes DOMs in the view. This ajax task creates a tree (jsTree) in onRender event. If i use modelEvents: {"change": "render"}, my jsTree will be reload and lost its state. So I want only update the model values in the view, others DOMs is retain.

Community
  • 1
  • 1
hieund
  • 356
  • 1
  • 6
  • 16
  • 1
    Possible duplicate of [Marionette ItemView how to re-render model on change](http://stackoverflow.com/questions/16876970/marionette-itemview-how-to-re-render-model-on-change) – ivarni Feb 18 '16 at 10:30
  • I edited my question. My problem is not the same. – hieund Feb 19 '16 at 01:53
  • If you don't want a full re-render, you'll have to manually update the changed DOM elements. – ivarni Feb 19 '16 at 07:24

1 Answers1

0

The accepted answer to the question you pointed points to another question which has the following:

modelEvents: {
  'change': "modelChanged"
},
modelChanged: function() {
  console.log(this.model);
  this.render();

}

And the most upvoted answer suggests the same:

modelEvents: {
    'change': 'fieldsChanged'
},

fieldsChanged: function() {
    this.render();
}

a comment to the most upvoted answer suggests

just {'change': 'render'} does the trick too

Which means you can do

modelEvents: {
  'change': 'render'
}

So somehow you need to tell marionette invoke render on model changes.

I don't think backbone and marionette couple is smart enough to know whether you need to render view on model changes or you don't want to unless you tell them ;)

Community
  • 1
  • 1
T J
  • 42,762
  • 13
  • 83
  • 138
  • Add {'change': 'render'} can tell the view to rerender. But in my real app, some ajax tasks has changed some DOMs in the view. When the view rerender (because of the model changing), all the changed DOMs are set to the orignal template. This is not what i want. – hieund Feb 18 '16 at 10:44
  • @hieund your question was *"My problem is that the view does not rerender when i change the model by clicking on the button"* my answer answers the question being asked... If you have a different problem now, you should accept the answer and ask a different question explaining the AJAX calls and stuff... BTW, your ajax calls should be changing the model data, so when the view rerenders, it displays the change. That is how we work with common template engines, we don't do DOM manipulation manually – T J Feb 18 '16 at 10:53