0

I want to know how to add data to mode, from my input. Here is my code:

Main file

var Bintime = new Marionette.Application();

Bintime.on("before:start", function(){
    var RegionContainer = Marionette.LayoutView.extend({
        el: "#app",
        regions: {
            contacts: "#contacts",
            name: "#name",
            messages: "#messages",
            input: "#input"
        }
    });

    Bintime.regions = new RegionContainer();
});

Bintime.on("start", function(){
    Bintime.Contacts.List.Controller.listContacts();
});

Model

Bintime.module("Contacts", function(Contacts, Bintime, Backbone, Marionette, $, _){
    Contacts.Contacts = Backbone.Model.extend({});

    Contacts.ContactsCollection = Backbone.Collection.extend({
        model: Contacts.Contacts,
        comparator: "firstName"
    });

    var contacts;

    var initializeContacts = function(){
        contacts = new Contacts.ContactsCollection([
            {
                id: 1,
                firstName: "Alice",
                lastName: "Arten",
                messages: [
                    {
                        from: "1",
                        message: "Hello"
                    },
                    {
                        from: "1",
                        message: "How r u?"
                    },
                    {
                        to: "1",
                        message: "Hey!"
                    },
                    {
                        to: "1",
                        message: "Great!"
                    }
                ]
            },
            {
                id: 2,
                firstName: "Bob",
                lastName: "Brigham"
            },
            {
                id: 3,
                firstName: "Charlie",
                lastName: "Campbell"
            }
        ]);
    };

    var API = {
        getContactContact: function(){
            if(contacts === undefined){
                initializeContacts();
            }
            return contacts;
        }
    };

    Bintime.reqres.setHandler("contacts:contacts", function(){
        return API.getContactContact();
    });
});

Main Controller

Bintime.module("Contacts.List", function(List, Bintime, Backbone, Marionette, $, _) {
    List.Controller = {
        listContacts: function() {
            var contacts = Bintime.request("contacts:contacts");

            var contactsView = new List.Contacts({
                collection: contacts
            });

            contactsView.on("childview:contact:contacts", function(childView, model) {
                Bintime.Contact.Name.Controller.nameContact(model);
            });

            contactsView.on("childview:chat:contacts", function(childView, model) {
                Bintime.Contacts.Messages.Controller.chatMessages(model);
            });

            contactsView.on("childview:message:contacts", function(childView, model) {
                Bintime.Message.Input.Controller.messageField(model);
            });

            Bintime.regions.contacts.show(contactsView);
        }
    }
});

Controller for module, which add message from input

Bintime.module("Message.Input", function(Input, Bintime, Backbone, Marionette, $, _) {
    Input.Controller = {
        messageField: function(model){
            var contacts = new Input.Contacts({
                model: model
            });

            Bintime.regions.input.show(contacts);
        }
    }
});

View for module, which add message from input

Bintime.module("Message.Input", function(Input, Bintime, Backbone, Marionette, $, _) {
    Input.Contacts = Marionette.ItemView.extend ({
        template: "#new",
        events: {
            "change input#message-input": "sendInput"
        },
        sendInput: function(e){
            e.preventDefault();
            var message = this.$("input#message-input").val();
            console.log(message);
        }
    });

    $('#new').append(v.el);
});

index.html

<div id="app" class="full-width full-height">
      <div class="full-width full-height">
        <div class="large-3 column contacts nopadding full-height">
          <div id="contacts">
          </div>
        </div>
        <div class="large-9 column full-height nopadding">
          <div id="name" class="user full-width">
            <div>

            </div>
          </div>
          <div id="messages">
          </div>
          <div id="input">
          </div>
        </div>
      </div>
    </div>
    <script type="text/template" id="contacts-list">
      <div class="contact">
        <div class="center text-center">
          <a href="#"><span class="text-center"><%= firstName%> <%= lastName%></span></a>
        </div>
      </div>
    </script>
    <script type="text/template" id="user">
        <h5 class="text-center"><%= firstName%> <%= lastName%></h5>
    </script>
    <script type="text/template" id="message">
      <% _.each(messages, function (item) { %>
        <div class="message">
          <div>
            <% if (item.from) { %>
              <div class="in">
                <%= item.message %>
              </div>
            <% } else if (item.to) { %>
              <div class="out">
                <%= item.message %>
              </div>
            <% } %>
          </div>
        </div>
      <% }); %>
    </script>
    <script type="text/template" id="new">
      <div class="enter full-width">
        <input id="message-input" type="text" placeholder="Enter your message..">
      </div>
      <a href="#" id="send" class="button">
        <span>Send</span>
      </a>
    </script>

As you can see, I already get my data from input field, here:

sendInput: function(e){
   e.preventDefault();
   var message = this.$("input#message-input").val();
   console.log(message);
}

But I can't add my data to model. I tried do it with .set(), but it override all my messages array. Something like that, but not exactly same:

sendInput: function(e){
    e.preventDefault();
    var field = $(e.currentTarget);
    var message = this.$("input#message-input").val();
    var data = {};
    data[field.attr("messages")] = message;
    this.model.set(data);
}

The result of adding "111" string to model, with previous example:

enter image description here

So, basically I need add new message to my model. Like this:

    id: 1,
    firstName: "Alice",
    lastName: "Arten",
    messages: [
        {
            from: "1",
            message: "Hello"
        },
        {
            from: "1",
            message: "How r u?"
        },
        {
            to: "1",
            message: "Hey!"
        },
        {
            to: "1",
            message: "Great!"
        },
        {
            to: "1",
            message: "HERE SHOULD BE NEW MESSAGE"
        }
   ]
AleshaOleg
  • 2,171
  • 1
  • 15
  • 29

1 Answers1

1

Assuming you have access to the model via this.model whose attribute hash looks like this:

{
   id: 1,
   firstName: "Alice",
   lastName: "Arten",
   messages: [{
        from: "1",
        message: "Hello"
      },
      {
        from: "1",
         message: "How r u?"
      },
      {
         to: "1",
         message: "Hey!"
      },
      {
         to: "1",
         message: "Great!"
      }]
}

as shown in question, you can add a new message to it like this:

this.model.get("messages").push({
    to: "1", // fill this as per your logic
    message: message 
});

This works because objects are passed by reference in JavaScript, and arrays are special objects.

T J
  • 42,762
  • 13
  • 83
  • 138
  • thanks! exactly what I want. I have one more question, how to immediately update my view? Should I use render()? Tried this.render(); Didn't work – AleshaOleg Nov 30 '15 at 14:14
  • @AleshaOleg normally, yes you have to re-render the view by calling it's `render`. I use [rivets.js](http://rivetsjs.com/) when I work with Backbone. It does two way binding, when you change the model, it'll automatically re render the parts that changed. In the case of views with huge template, it's much better than re-rendering the entire view – T J Nov 30 '15 at 14:16
  • sorry for this, but i changed my comment. I sad that in my this.render() don't work. I know, it's not a topic of this question, but may be you know what's the problem? – AleshaOleg Nov 30 '15 at 14:22
  • @AleshaOleg I'm not familiar with Marionette, but looking at `Input.Contacts` view, it doesn't have a `render` method. Usually people define a `render` method that attaches the html to view based on the model data (usually using templating libraries like underscore, handlebars etc). And when they need to redraw the view based on updated model data, people call `render`. But your view doesn't seems to have a render method..? – T J Nov 30 '15 at 14:26
  • OK, Now I know what to look for, Thanks, again! – AleshaOleg Nov 30 '15 at 14:28