2

jsfiddle

I'm trying to create a message client using this tutorial at this point, the view is supposed to be updated when a new message is typed into the field and the add button is clicked. For some reason the "addMessage" Event is failing to add a new model to the collection.

var messagesjson = [
  { 
    id: 3,
    message: "This is the message",
    sender: "gabriel",
    receiver: "gabriel",
    has_been_read: false,
    has_been_reported: false,
    created_at: "2014-10-23T19:55:20+0200",
    is_friend: false
  },
  {
    id: 5,
    message: "I'm loving this ",
    sender: "gabriel",
    receiver: "gabriel",
    has_been_read: true,
    has_been_reported: false,
    created_at: "2014-10-23T20:02:34+0200",
    is_friend: false
  }];

var MessageModel = Backbone.Model.extend({
  defaults:
  {
    id: 3,
    message: "This is the message",
    sender: "gabriel",
    receiver: "gabriel",
    has_been_read: false,
    has_been_reported: false,
    created_at: "2014-10-23T19:55:20+0200",
    is_friend: false
  }
});

var MessageView = Backbone.View.extend({
  tagName: "div",
  className: "listview",
  template: $('#messageTemplate').html(),
  render: function()
  {
    var tmpl = _.template(this.template);
    console.log(this.model);
    this.$el.html(tmpl(this.model.toJSON()));
    return this;
  }
});

var MessageCollection = Backbone.Collection.extend({
  model: MessageModel
});

var MessageCollectionView = Backbone.View.extend({
  el: $('#messages'),
  initialize: function()
  {
    this.collection = new MessageCollection(messagesjson);
    this.render();
    this.collection.on("add", this.renderMessage, this);
  },
  render: function()
  {
    var that = this;
    _.each(this.collection.models, function(item){
      that.renderMessage(item);
    },this);
  },
  events:{
    "click #add":"addMessage"
  },
  renderMessage: function(item)
  {
    var messageview = new MessageView({
      model: item
    });

    this.$el.append(messageview.render().el);
  },
  addMessage: function(e)
  {
    e.preventDefault();
    var formData = {};

    $("#addMessage").children("input").each(function (i, el) {
      formData[el.id] = $(el).val();
    });

    messagesjson.push(formData);
    this.collection.add(new MessageModel(formData));

    console.log(messagesjson);
  }
});

var messagecollectionview = new MessageCollectionView();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<div id="messages">  
  <form id="addMessage" action="#">
    <div>
      <label for="messageText">Message: </label>
      <input id="messageText" type="text" />
      <button id="add">Add</button>
    </div>
  </form>
</div>

<script type="text/template" id="messageTemplate">
  <a href="#" class="list autoWidth <% if(has_been_read) { %> selected <% } %>">
    <div class="list-content">
      <img src="//www.polyvore.com/cgi/img-thing?.out=jpg&size=l&tid=20774792" class="icon">
      <div class="data">
      <span class="item-title-secondary fg-gray"><b><%= sender %></b></span>
    </div>
    <span class="tertiary-text">
      <%= message %>
    </span>
    </div>
  </a>
</script>
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
user3531149
  • 1,519
  • 3
  • 30
  • 48

1 Answers1

1

You are setting the id as 3 for all new models as your defaults hash contains id: 3. The collection thinks it is the same model as it already has a model with that id.

So first you need to change your defaults with id:null:

var MessageModel = Backbone.Model.extend({
    defaults:{
        id: null,
        message: "This is the message",
        sender: "gabriel",
        receiver: "gabriel",
        has_been_read: false,
        has_been_reported: false,
        created_at: "2014-10-23T19:55:20+0200",
        is_friend: false
    }
});

Then you need to fix the code getting the formData. First of all you are using jQuery children() method which only looks at immediate childrens. That means you will never get the inputs inside the form as there is an intermediate div. You could use find.

Secondly, you need to make sure that formData has a property named message so it can override the default message: "This is the message". I would add a name attribute message to the input element and use it like formData[el.name] = $(el).val();. (You could later use one of the jquery serializeObject plugins to automatically serialize all input elements this way).

So the addMessage would look like this:

addMessage: function(e){
    e.preventDefault();
    var formData = {};

    $("#addMessage").find("input").each(function (i, el) {
        formData[el.name] = $(el).val();
    });                

    messagesjson.push(formData);
    this.collection.add(new MessageModel(formData));
}

You can try it in this fiddle

Daniel J.G.
  • 34,266
  • 9
  • 112
  • 112