Video

Want to see the full-length video right now for free?

Sign In with GitHub for Free Access

Notes

Advanced Model and Relationships - Part 2

Rendering todo lists

  • First create a serializer for TodoList

    • Inside the serializer include the id
    • Add has_many todo_items as well

      class TodoListSerializer < ActiveModel::Serializer attributes :id

      has_many :todo_items end

  • Next we're going to create Backbone Collection and Model objects for todo items

    • For now simply create an empty TodoItem model

      class App.Models.TodoItem extends Backbone.Model

    • The TodoItem collection class will only reference the TodoItem model

      class App.Collections.TodoItems extends Backbone.Collection model: App.Models.TodoItem

  • Override our Backbone TodoList model's constructor

    • Create a todoItems attribute and assign an instance of the Backbone TodoItem collection object

      constructor: -> @todoItems = new App.Collections.TodoItems([], todoList: this) super(arguments...)

  • In the parse method reset the todoItems attribute to the values passed in the data argument

    parse: (data) ->
      @todoItems.reset(data.body.todo_list.todo_items, parse: true)
      delete data.body
      data
    
  • Create a toJSON method to translate the data back to the format provided by the server

    toJSON: ->
      {
        title: @get('title')
        body:
          type: 'todo_list'
          todo_list:
            todo_items: @todoItems.toJSON()
      }
    
  • Now we need to create a TodoItemsIndex Backbone view

    • Set the tagName attribute to ul
    • Set the className attribute to todo-items
    • For now we'll leave the render method blank

      class App.Views.TodoItemsIndex extends Backbone.View tagName: 'ul' className: 'todo-items'

      render: => @$el.html('') this

  • Next we create a singular TodoItem Backbone view

    • Set the className attribute to todo-item
    • In the render method display the model's title

      class App.Views.TodoItem extends Backbone.View className: 'todo-item'

      render: => @$el.html(@model.get('title')) this

  • Once we're done with our TodoItem Backbone view we need to add some code to our TodoItemsIndex Backbone view

    • In the render method we want to iterate over our collection of TodoItems and render the TodoItem Backbone view for each item

      render: => @$el.html('') @collection.forEach(@renderItem) this

    • To do this we need to add a method named renderItem that takes a TodoItem model as an argument

    • In the renderItem method we need to instantiate an instance of the TodoItem Backbone view and append the rendered view to the TodoItemIndex's DOM object

      renderItem: (model) =>
        view = new App.Views.TodoItem(model: model, tagName: 'li')
        @$el.append(view.render().el)
      
    • Finally we need to override the TodoItemIndex Backbone view's initialize method to tell the object to rerender when an item is added to the collection, or when the collection is reset

      initialize: -> @listenTo(@collection, 'add', @renderItem) @listenTo(@collection, 'reset', @render)

  • Now we return to our TodoList Backbone view

    • First we override the initializer to instantiate an instance of the TodoItemIndex class
    • We pass the TodoList's model's todo_items as the TodoItemIndex's collection

      initialize: -> @todoItems = new App.Views.TodoItemsIndex(collection: @model.todoItems)

    • Next we modify the render method to render the TodoItemIndex view we instantate in the initalizer

      render: -> @$el.html(@todoItems.render().el) this

    • Finally we have to tell the TodoList Backbone view to remove the newly instantiated TodoItemIndex when anytime it gets removed to avoid a memory leak

      remove: -> @todoItems.remove(arguments...) super(arguments...)

  • Now that we're printing out todo list items let's add some styles

    • Open the note.css.scss file
    • Inside the .body class definition add a definition for the .todo-items class

      .todo-items { padding: 0;

      .todo-item { list-style: none; } }

  • Now we'll make the todo items in the list editable

  • Create a new todo item show template app/assets/templates/todo\_items/show.jst.eco

    • Inside the template add a single text input