danscotton
danscotton

Reputation: 53

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!

Upvotes: 5

Views: 2324

Answers (2)

Brian Mann
Brian Mann

Reputation: 211

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.

Upvotes: 8

David Sulc
David Sulc

Reputation: 25994

Why don't you just add it to serializeData ? (Can't remember Coffee syntax...)

serializeData: function(){
    var data = _.clone(this.model.attributes);
    data.day = this.model.day();
    return data;
}

Upvotes: 0

Related Questions