1

Iam trying to build a very simple ul where u have a input box and add button , on clicking add button , text from input is appended to ul

this is my code :

HTML :

<body>
<input type="text" id="name">
<button id="add">Add</button>
<ul id="mylist"></ul>

JS :

$(function(){

var myCollection = Backbone.Collection.extend();

var myView = Backbone.View.extend({

    el:$('body'),

    tagName:'li',

    initialize : function(e){
        this.collection.bind("add",this.render,this);
    },

    events:{
        'click #add' : 'addfoo',
        'click .button':'removefoo'
    },

    addfoo:function(){
       var myname= $('#name').val();
       $('#name').val('');
       console.log('name entered: '+myname);
       this.collection.add({name:myname});
    },

    removefoo:function(){
             //need the code here 
    },

    render:function(){

        $('#mylist').empty();
        this.collection.each(function(model){
            $('#mylist').append('<li>'+model.get('name') + "<button class='button'>"+"delete"+"</button></li>");
        });

    }

});
var view = new myView({collection: new myCollection()});
    });

My add funcitonality is working , but when i click the button for delete , which model from collection should be deleted , iam stuck there , please help me out.Just need the code , for what do delete from collection in removefoo function.

In other word how do i get which model to be removed when button is clicked

Thank you

Nishant Jani
  • 1,965
  • 8
  • 30
  • 41

2 Answers2

4

I think you need a more modular approach to Backbone, let me explain.

Backbone is a way to organize your code. Having just one Backbone view do it all, doesn't change a lot.

Instead, try to see what views you actually need:

  • MainView
  • ListView
  • ListItemView

MainView could look like this:

var MainView = Backbone.View.extend({

    el: 'body',

    initialize : function(options) {
       this.collection = new Backbone.Collection.extend({ url: '/items' });
    },

    events:{
    },

    render:function(){
        var listView = new ListView({ el: this.$("#myList") });
        listView.render();

        this.collection.fetch();

        return this;
    }
});

ListView

var ListView = Backbone.View.extend({

    tagName: 'ul',

    initialize : function(options) {
        _.bindAll(this, "render");

        this.collection.on("add", this.appendListItem, this);
    },

    events:{
    },

    render: function() {
        this.collection.each(this.appendListItem, this);

        return this;
    },

    appendListItem: function (model, collection, options) {
        var listItem = new ListItemView({ model: model});
        this.$el.append(listItem.render().el);
    }
});

ListItemView

var ListItemView = Backbone.View.extend({

    tagName: 'li',

    initialize : function(options) {
        _.bindAll(this, "render");

        this.model.on("destroy", this.remove, this);
    },

    events:{
        "click button": "delete"
    },

    render:function(){
        this.$el.text(this.model.get('name'));
        this.$el.append("<button class='button'>Delete</button>");

        return this;
    },

    delete: function (event) {
        this.model.destroy();
    }
});

Kick off the main view: var view = new MainView().render();

MartinHN
  • 19,542
  • 19
  • 89
  • 131
  • thanks for the reply , but iam v v new to backbone , i really could not digest so much of code, no offense , but can you please help out with something more lucid ? – Nishant Jani Nov 23 '12 at 12:14
  • Try to take a look at TodoMVC: http://todomvc.com/, and the Backbone version of it: https://github.com/addyosmani/todomvc/tree/gh-pages/architecture-examples/backbone -- It will take some time to consume and see the big picture, but to write maintainable Backbone apps it is important to get the concept right. The problem with your code is, that it doesn't really utilize all the goodness that Backbone has to offer. – MartinHN Nov 23 '12 at 12:30
  • 1
    `ListView` should `this.collection = options.collection;` automatically and the `render` should probably `this.collection.each(this.appendListItem, this)` for completeness. – mu is too short Nov 23 '12 at 17:05
  • @muistooshort I actually wasn't aware that `View` automatically handles `collection` in the `initialize` method. – MartinHN Nov 23 '12 at 21:47
  • @muistooshort , martinHN i posted a similar question on SO , can u tell me if the answer given , utiliza the goodness of backbone ? http://stackoverflow.com/questions/13507760/backbone-add-remove-from-ul-anomaly , please ? thank you so much – Nishant Jani Nov 24 '12 at 07:55
0

A unique id must be assigned to each li element when you render each model on the UI to know which element gets deleted.

Instead of

$('#mylist').append('<li>'+model.get('name') + "<button class='button'>"+"delete"+"</button></li>");

you're better off using templates. You can use underscore's template which will it easier to assign ids and create lis dynamically.

To delete the model:

removefoo:function(evt){
        var target = evt.target;
        //Parse the target id to get the model id and then delete it.
    }

See https://stackoverflow.com/questions/8782704/backbone-js-tutorial to understand how all the components of backbone fit together.

Community
  • 1
  • 1
Pramod
  • 5,150
  • 3
  • 45
  • 46
  • hmm thanks for the reply , but when i do your approach the event give me : and not model id – Nishant Jani Nov 23 '12 at 11:38
  • Yes, to get the model id, you have to assign incorporate the model id in the li id. It could be something like
  • where 1 is the model_id
  • – Pramod Nov 23 '12 at 11:51
  • but in my case elements are added and removed dynamically how can i assign a static id ? – Nishant Jani Nov 23 '12 at 12:15
  • You have to assign it dynamically using templates. "foo_1" is just an example. It's a general case of "foo_model_id" – Pramod Nov 23 '12 at 17:11
  • I really try to avoid this approach. It's generally a much better idea to maintain a reference to a view or DOM element than to try to cross-reference models and DOM elements with a cludgy in-DOM string. – nrabinowitz Nov 23 '12 at 21:57
  • @nrabinowitz So does the view maintain a mapping between each model and the corresponding dom element? What should the id of the dom elements be? – Pramod Nov 24 '12 at 05:06
  • 1
    The standard way to deal with this is to have 1:1 view:model relationships, with each view managing one DOM element (and its children). That's essentially what @MartinHN's answer does. If you need to maintain an internal model-element mapping, you probably need sub views. – nrabinowitz Nov 24 '12 at 05:11
  • Oh, and I almost never have ids on view-created elements. You shouldn't need them for selection, and you can't use them for CSS unless you know them ahead of time, which if very hard if you want them to be unique. – nrabinowitz Nov 24 '12 at 05:14
  • @nrabinowitz Oh ok Thanks !! But what wouldn't that lead to too many view objects being created? – Pramod Nov 24 '12 at 05:50
  • 1
    Depends on your case - it might be an issue with many, many DOM elements. But under normal circumstances it wouldn't affect memory or performance in any meaningful way. – nrabinowitz Nov 24 '12 at 06:40
  • @nrabinowitz can you please tell me what advantages would i have if i create a dediate/seperate view for each DOM element – Nishant Jani Nov 24 '12 at 10:32
  • 2
    The advantage is in maintaining your associations between model, view, and DOM through references in the view, rather than having to query the DOM to get the elements. It's cleaner, easier to maintain, and faster (because you don't need to query every time). – nrabinowitz Nov 24 '12 at 16:06
  • @nrabinowitz I'm using your method for my new project. Works great :) Thanks! – Pramod Dec 20 '12 at 19:34