Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access Backbone.Model methods from Marionette.js ItemView template?

I'm trying to access a model's method from within an .eco template using backbone/marionette.js. I have an Expense model with a day() method which, using moment.js, returns '13th'; for example:

class Expense extends Backbone.Model
  day: ->
    moment.get('date').format('Do')

I can create a new Expense as follows, and call the day() method:

coffee = new Expense({name: "Coffee", amount: 2.50, date: "2014-01-13T13:50:00Z"})
coffee.day() # 13th

However, trying to access day() from within the following view and template is causing me some problems:

class ExpenseView extends Marionette.ItemView
  template: "views/_expense"
# views/_expense.jst.eco
<h3 class="expense__name"><%= @name %></h3>
<p class="expense__day"><%= @day() %></p>

I understand why it isn't working...the ItemView calls serializeData which returns @model.toJSON()... therefore, the Expense's day() method isn't accessible. Is there an established pattern in the backbone/marionette community that makes model methods available to templates?

So far, I've done the following to make it work:

class ExpenseView extends Marionette.ItemView
  template: "views/_expense"

  serializeData: ->
    _.extend(@model.toJSON(), model: @model)

  templateHelpers:
    day: ->
      @model.day()

But I'm unsure whether this is the best way to go about the problem? Thanks!

like image 811
danscotton Avatar asked Jan 13 '14 14:01

danscotton


1 Answers

You can always add it to templateHelpers or serializeData - but what you're really asking about is a virtual attribute - one that can be part of every template, an attribute that is used solely as part of a ViewModel. In this way we can also disable it from syncing to the server on sync events such as save()

There are several plugins out there that do this, my personal favorite to use is Backbone Mutators - https://github.com/asciidisco/Backbone.Mutators

Others like Backbone Computed Fields - https://github.com/alexanderbeletsky/backbone-computedfields give you Ember like computed properties.

With Backbone Mutators you would write your mutators in the Backbone Model.

class Model extends Backbone.Model
  mutators:
    day: ->
      moment.get('date').format('Do')

Alternatively to prevent the 'day' attribute from syncing to the backend...

class Model extends Backbone.Model
  mutators:
    day:
      get: -> moment.get('date').format('Do')
      transient: true

The day attribute will be present in all toJSON() calls now.

like image 195
Brian Mann Avatar answered Oct 19 '22 05:10

Brian Mann