Как я могу правильно отобразить базовую коллекцию в представлении?

#javascript #jquery #html #css #backbone.js

#javascript #jquery #HTML #css #backbone.js

Вопрос:

Я пытаюсь научиться Backbone.js и теперь я использовал пример на этой странице, чтобы создать представление из коллекции. Для этого я использую коллекцию:

 var ContactEventCollection = Backbone.Collection.extend({
    initialize: function(models, options) {
        this.id = options.id;
        this.lastContactEventId = options.lastContactEventId;
    },
    url: function() {
        return 'ticket/'   this.id   '/contact-events/'   this.lastContactEventId;
    }
});
  

одно представление для диалога и одно для события контакта (событие контакта — это в основном сообщение):

 var ConversationView = Backbone.View.extend({
    render: function(){
        this.collection.each(function(contactEvent){
            var contactEventView = new ContactEventView({model: contactEvent});
            this.$el.append(contactEventView.render().el);
        }, this);
        return this;
    }
});

var ContactEventView = Backbone.View.extend({
    template: _.template($('#contact-event-template').html()),
    render: function() {
        this.$el.html(this.template(this.model.toJSON()));
        return this;
    }
});
  

ссылка #contact-event-template выглядит следующим образом:

 <script type="text/template" id="contact-event-template">
    <div class="user-message"><%= text %></div>
</script>
  

Затем я пытаюсь добавить ее к этому div ( <div id="put-conversation-here">put the conversation here!</div> ):

 var contactEventCollection = new ContactEventCollection([], {id: 1, lastContactEventId: 0});
contactEventCollection.fetch();
console.log(contactEventCollection);
var conversationView = new ConversationView({collection: contactEventCollection});
console.log(conversationView);
$('#put-conversation-here').append(conversationView.render().el);
  

В консоли я вижу, что conversationView выглядит как изображение ниже. Странно то, что у меня есть коллекция, и у меня есть представление, которое включает в себя все эти модели, но то, что добавляется, — это просто пустое: <div></div> (даже не с class="user-message" ).

Я также пытался this.model.toJSON() заменить простым объектом: {text: "some text"} , но безрезультатно. К настоящему времени я полностью потерян и нуждаюсь в любой помощи, которую я могу получить. Если бы я мог, я бы немедленно назначил награду за это, но, к сожалению, мне приходится ждать два дня, прежде чем делать это.

Кто-нибудь знает, где я здесь ошибаюсь? Любая помощь, советы или рекомендации приветствуются!

введите описание изображения здесь

Комментарии:

1. Может быть contactEventCollection.fetch(); , это называется асинхронным, и перед выборкой данных ваш html отображается? Возможно, вы захотите использовать $.when(contactEventCollection.fetch()).done(function(){html population}); , но не уверены в этом.

2. @Pushkar — Вы, сэр, просто потрясающие. Вот и все, спасибо!

3. Я не мастер, только начал его использовать. Мы используем handlebar.js . Пожалуйста, отметьте сообщение как ответ.

Ответ №1:

Это contactEventCollection.fetch(); называется асинхронным, и перед извлечением данных ваш HTML-код отображается.

Возможно, вы захотите использовать

$.when(contactEventCollection.fetch()).done(function(){html population});

Ответ №2:

Collection.fetch вызывается асинхронно, поэтому ваш результат еще не существует, когда вы пытаетесь получить к нему доступ.

«Основной способ» сделать это — прослушать событие и убедиться, что ваше представление будет работать правильно, независимо от того, в каком состоянии находится коллекция.

В идеале ваше представление охватывает полный жизненный цикл вашей коллекции, поэтому оно всегда представляет текущее состояние:

 var ConversationView = Backbone.View.extend({
  initialize: function () {
    // add a view when a model is added to the collection.
    this.listenTo(this.collection, 'add', this.addContactEventView);
  },
  render: function () {
    // create views for all existing models
    this.collection.each(addContactEventView, this);
    return this;
  },
  addContactEventView: function (model) {
    var contactEventView = new ContactEventView({model: contactEvent});
    this.$el.append(contactEventView.render().el);
    // remove the view when model destroys.
    contactEventView.listenTo(model, 'remove', contactEventView.remove);
  }
});
  

Ответ №3:

В этом случае у вас может быть такой код. (код в coffeescript)

// Внутри вашего представления.

  template ://receive the template html in you case ('#contact-event-template')

initialize:->
    @listOfContact = ''
    @collection = new ContactEventCollection()
    @collection.on 'triggeredEvent', @render, @
    @collcetion.getConversations()


render:->
    @collection.each (model) =>
          @listOfContact  = @template(item.toJSON())
    @$el.html(@listOfContact)
  

Таким образом, у вас есть только один доступ к DOM, избегая перехода туда для каждого элемента вашей коллекции, это более эффективно 🙂