Question

I'm trying to make a quick sample Backbone.js app that has a Post model, a PostList collection, and a PostView + PostListView. Something simple where you can post in a form and it will add your post to the list of posts.

When someone clicks submit on the post form, it triggers an event in "PostListView", the view for the PostList collection. Where do I create a new post model and add it to the collection? Do I write this code in the View itself? Or does the view call a collection method that does this? Can you even write custom collection methods? If so, how do I call them from a view?

Coming from a Rails background, I naturally edge towards putting code in the collections/models rather than views (rails controllers), but I can't figure out how to call custom collection events from views.

Code is as below. Thanks so much for any help!

PostListView.coffee:

class forum.PostListView extends Backbone.View
    tagName: 'section'
    className: 'post-list'

    events:
        'click .post-form button': 'submit'

    initialize: ->
        #causes the view to render whenever the collection's data is loaded
        @collection.bind 'reset', @render
        @collection.bind 'add', @render

    render: =>
        $(@el).html JST['postList']()
        $postList = this.$('.post-list')

        #iterates through posts, renders, appends to <ul>
        @collection.each (post) =>
            view = new forum.PostView
                model: post
                collection: @collection
            $postList.append view.render().el

        return this

    submit: ->
        console.log "submitted!"
        @collection.trigger 'newPost', this.$('.post-form textarea').val()

PostList.coffee:

class forum.PostList extends Backbone.Collection
    model: forum.Post
    url: '/posts'

    initialize: ->
        this.bind 'newPost', newPost

    newPost: (postText) ->
        console.log "Collection method called!!"
        # post = new forum.Post
        #   content: postText

        # @add post
Was it helpful?

Solution

You call a method in PostList, from the PostListView, to add a new model in the collection. Something like this in regular js:

this.collection.add( new forum.Post( this.$( ".post-form textarea").val() ) );

I don't do CoffeeScript so I guess the syntax for above in cs would be like this:

@collection.add new forum.Post
           this.$( ".post-form textarea").val()

If it's more complicated to add a new Post to PostList, you could add a method for it in PostList

this.collection.complexAdd( params... );

You add custom methods to PostList in the place where you create the class.. you have done so with the newPost method already.

This is much simpler than your collection listening to view events because views are initialized last.

Edit: I guess it could also come down to opinion, some people prefer models/collections knowing about which backbone views are using them, but in a situation where there are more than one view for one model (for example, TabContent view and TabSelector view for a single TabModel), it makes stuff more complicated.

OTHER TIPS

The following tips may help you...

  1. It might separate things better if you have a separate view for NewPost, whose single responsibility is to manage the new post form. Your PostListView can create that and append it to itself.

  2. Normally, you do not want to add a new model to a collection until after it is saved. So what you may do is give your NewPostForm a reference to the collection and have it add it once it is saved.

  3. You may also want the PostList to dump and recreate the NewPost view after that, and get it ready to add a subsequent post.

Backbone "views" are sometimes more like controller actions in Rails. So creating models, moving them around, saving them, etc. are all perfectly ok to do in view code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top