2015-08-19 3 views
0

Я учусь Marionette.js и есть сценарий, где мое приложение имеет:дисплей длина коллекции в представлении в Marionette.js

app.addRegions({ 
    main: '#omen', 
    newItem: '#addnewitem', 
    counter: '#counter' 
}); 

Эти регионы. У меня есть эти модели/Коллекция:

var Item = Backbone.Model.extend(), 
Items = Backbone.Collection.extend({ 
    model: Item, 
    url: 'api/items' 
}), 

У меня есть вид товара и товары Вид:

ItemView = Mn.ItemView.extend({ 
    tagName: 'tr', 
    template: '#itemView', 
    events: { 
     'click #btnDeleteBook' : 'deleteItem' 
    }, 
    deleteItem: function() { 
     app.trigger('item:delete', this.model); 
    } 
}), 
ItemsView = Mn.CollectionView.extend({ 
    tagName: 'table', 
    childView: ItemView, 
    onShow: function(view) { 
     TweenMax.staggerFrom($(view).find('td'), 1, { 
      x: 100 
     }, 2); 
    } 
}), 

У меня есть функция инициализации, которая прослушивает события выше и делает вещи через app.ItemController. Все работает отлично.

Но теперь я хочу добавить регион (область счетчика), который отображает общее количество элементов в моей коллекции. Мне нужно, чтобы это был отдельный вид в идеале, потому что я буду показывать его в разных местах.

Так я это сделать:

DisplayCounter = Mn.ItemView.extend({ 
    template: _.template('Total: '+ app.Items.length), 
}), 

app.Items является экземпляром Collection, упомянутых выше. Но даже до создания DisplayCounter, я получаю ошибку:

Uncaught TypeError: Невозможно прочитать свойство 'length' of undefined.

Пожалуйста, помогите ... :(

------------------------- EDIT --------- . -------------

я достиг его, но это, кажется, настолько сложны, чтобы сделать такую ​​маленькую вещь

изменил мою коллекцию так:

Items = Backbone.Collection.extend({ 
     model: Item, 
     url: 'api/items', 
     initialize: function() { 
      this.listenTo(this, 'add', function() { 
       app.trigger('collection:updated', this); 
      }); 
     } 
    }), 

и изменил мой DisplayCounter следующим образом:

DisplayCounter = Mn.ItemView.extend({ 
     template: _.template('Total: <%=length%>'), 
     templateHelpers: function() { 
      return { 
       length: this.lengthVariable || 0 
      } 
     }, 
     initialize: function() { 
      app.on('collection:updated', function(params){ 
       this.lengthVariable = params.length; 
       this.render(); 
      }.bind(this)); 
     } 
    }), 

Я не могу поверить, что нет более простого способа сделать это ..:/

ответ

1

кода, который устанавливает DisplayCounter бежится перед кодом, который помещает экземпляр Items в app.Items.

Даже если вы избежать этой проблемы путем назначения app.Items первых, вы все еще есть проблема - template свойство устанавливается только один раз, так что вы бы только когда-либо видеть длину app.Items в то время, когда вы определяете DisplayCounter.

Вместо того, чтобы жестко кодировать значение непосредственно в строке шаблона, вы должны указать значение во время рендеринга. Mn.View.serializeData позволяет настроить данные, передаются в функцию шаблона во время рендеринга:

DisplayCounter = Mn.ItemView.extend({ 
    template: _.template('Total:: <%= itemCount %>), 

    serializeData: function() { 
    return { itemCount: app.Items.length } 
    } 
}), 
+1

о том, что полезно спасибо! однако моя 'app.Items.length' появляется как 0, и я думаю, что это потому, что я использую метод fetch() для получения элементов с сервера. И когда представление визуализируется, оно еще не имеет элементов. Поэтому я должен каким-то образом реализовать что-то вроде события «collection: change», а затем запустить событие, которое скажет «эй, коллекция была обновлена, хотите повторно отобразить?» Такие вещи... ? –

+0

Да, вы должны повторно отобразить в ответ на добавление и удаление событий. – joews

+0

Я обновил код. Это правильный способ сделать это? –

0

app.Items не определяемое.

В Marionette вы можете определить, какие коллекции или модели будут использовать ваши взгляды.

ItemsView = Mn.CollectionView.extend({ 
tagName: 'table', 
childView: ItemView, 
collection: myItems // An instance of your collection 
onShow: function(view) { 
    TweenMax.staggerFrom($(view).find('td'), 1, { 
     x: 100 
    }, 2); 
} 
}), 

Таким образом, марионетка будет отображать один элемент для каждого элемента в вашей коллекции. Затем внутри вашего представления коллекции this.collection будет ссылаться на экземпляр коллекции. Так что this.collection.length будет иметь то, что вам нужно.

И в вашем ItemView вы можете получить соответствующую модель с помощью this.model

+0

CollectionView не является проблемой, поскольку я все равно передаю коллекцию. Моя проблема заключается в представлении DisplayCounter ... –

Смежные вопросы