Динамические свойства для модели CanJS?

Я хотел бы добавить в свою модель динамические свойства, которых нет в результатах службы REST. Эти динамические свойства будут сокращать имена, форматировать даты и т. д. Например, моя модель CanJS выглядит так:

var MyModel = can.Model({
    findAll: 'GET /Services/all'),
    findOne: 'GET /Services/{id}'),
    create:  'POST /Services/all'),
    update:  'PUT /Services/{id}'),
    destroy: 'DELETE /Services/{id}')
}, {});

Затем я получаю данные следующим образом:

MyModel.findAll({}, function(data) {
    $('#main').html(can.view('templates/List.ejs'), data));
});

А вот так выглядит мой шаблон List.ejs:

<% for(var i = 0; i < this.length; i++) { %>
    <div class="thumb"><img src="http://cdn.somewhere.com/images/logo.<%= this[i].BaseName %>.png" /></div>
    <div class="title"><%= this[i].Name %></div>
    <div class="date"><%= moment(this[i].StartDate).format('MMM DD, YYYY') %> - <%= moment(this[i].EndDate).format('MMM DD, YYYY') %></div>
    <div class="location"><%= this[i].LocationFriendly %></div>
    <div class="description"><%= this[i].Description %></div>
<% } %>

Обратите внимание на логику, которую я использую в шаблоне для источника изображения и даты начала/окончания. Я хотел бы поместить эту логику в модель, поэтому все, что мне нужно сделать в шаблоне, это:

<% for(var i = 0; i < this.length; i++) { %>
    <div class="thumb"><img src="<%= this[i].ImageURL %>" /></div>
    <div class="title"><%= this[i].Name %></div>
    <div class="date"><%= this[i].StartDateFriendly %> - <%= this[i].EndDateFriendly %></div>
    <div class="location"><%= this[i].LocationFriendly %></div>
    <div class="description"><%= this[i].Description %></div>
<% } %>

Как переместить эту логику на уровень модели или в любое другое место, которое лучше, чем шаблон? Спасибо за любую помощь или совет.


person Basem    schedule 16.09.2012    source источник


Ответы (1)


Самый простой способ - просто создать функции для вашей модели:

var MyModel = can.Model({
    findAll: 'GET /Services/all',
    findOne: 'GET /Services/{id}',
    create:  'POST /Services/all',
    update:  'PUT /Services/{id}',
    destroy: 'DELETE /Services/{id}'
}, {
    imageUrl : function(){
        return "http://cdn.location.com/" + this.BaseName + ".png"
    },
    startDateFriendly : function(){
        return moment(this.StartDate).format('MMM DD, YYYY')
    },
    endDateFriendly : function(){
        return moment(this.StartDate).format('MMM DD, YYYY')
    },
    locationFriendly: function() {
        // ...
    }
});

Затем вы можете просто вызвать эти функции из представления:

<% for(var i = 0; i < this.length; i++) { %>
    <div class="thumb"><img src="<%= this[i].imageUrl() %>" /></div>
    <div class="title"><%= this[i].Name %></div>
    <div class="date"><%= this[i].startDateFriendly() %> - <%= this[i].endDateFriendly() %></div>
    <div class="location"><%= this[i].locationFriendly %></div>
    <div class="description"><%= this[i].Description %></div>
<% } %>
person retro    schedule 17.09.2012
comment
Я только что попробовал это, но шаблон выдает ошибку: Uncaught TypeError: Object #‹Object› не имеет метода 'imageUrl'. Я также пробовал без круглых скобок, но в шаблоне отображается пустое. Знаете ли вы, есть ли что-то особенное в шаблонах EJS для вспомогательных методов Properties? - person Basem; 18.09.2012
comment
Это заработало после перехода на реальные REST-сервисы вместо симулированных. Спасибо! - person Basem; 20.09.2012