Обновление родительского представления в backbone.js

Цель: использовать Backbone для создания таблицы пользователей, иметь возможность редактировать этих пользователей в процессе работы и при сохранении повторно отображать строку с обновленными данными.

  • Я создаю таблицу контейнеров для пользователей с основным UsersView.
  • Затем я перебираю коллекцию пользователей и использую UserView для создания одной строки таблицы для каждого пользователя.
  • Щелчок по редактированию любой строки должен заменить строку формой редактирования. (С пользователем связано больше полей, чем отображается в таблице.)
  • При нажатии кнопки «Сохранить» форма редактирования должна быть заменена обновленной строкой таблицы.

Все работает, кроме повторного рендеринга строки таблицы. (Если я перезагружу страницу, обновленные пользовательские данные отображаются правильно, поэтому я знаю, что они сохраняются.) Что я пытаюсь сделать (я думаю), так это заставить родительское представление (UsersView) прослушивать изменения и повторно отображать Пользовательское представление. После десятков поисков и разных попыток, я здесь прошу помощи, что я делаю не так. Заранее спасибо.

// Просмотр основных пользователей

var UsersView = Backbone.View.extend( {
  el: '#content',

  template: _.template( usersTemplate ),

  initialize: function( ) {
    var that = this;
    this.listenTo( Users, 'change', this.updateOne );
    Users.fetch( );
    that.render( );
  },

  render: function( ) {
    this.$el.html( this.template );
  },

  // Add a single user to the table
  addOne: function( user ) {
    var userView = new UserView( { model: user } );
    userView.render( ).el;
  },

  // Add all items in the Users collection
  addAll: function( ) {
    Users.each( this.addOne, this );
  }
});

// Просмотр отдельного пользователя

var UserView = Backbone.View.extend({
  el: '#usersTableBody',

  tagName:  'tr',

  attributes : function( ) {
    return {
      'data-user' : this.model.get( 'display_name' )
    };
  },

  template: _.template( userTemplate ),

  events: {
    'click .editUser': 'editUser'
  },

  initialize: function( ){ },

  render: function( ) {
    var html = this.template( this.model.attributes );
    this.$el.html( html );
  },

  // Switch user row into edit mode
  editUser: function( e ) {
    e.preventDefault( );

    var userAddEditView = new UserAddEditView( { model: this.model } );
    userAddEditView.render( );
  }
});

// Представление для редактирования пользователем

var UserAddEditView = Backbone.View.extend({
  el: $( '#content' ),

  template: _.template( userEditTemplate ),

  events: {
    'click .saveUser': 'saveUser'
  },

  initialize: function( options ) { },

  render: function( ) {
    element = '[data-user="' + this.model.get( 'display_name' ) + '"]'
    this.$el.find( element ).hide( ).after( this.template( this.model.attributes ) );
  }, 

  saveUser: function( ) {
    var display_name = this.$( '#display_name' ).val( ).trim( );
    var email_address = this.$( '#email_address' ).val( ).trim( );
    var key_email_address = this.$( '#key_email_address' ).val( ).trim( );
    var password = this.$( '#password' ).val( ).trim( );
    var partner_name = this.$( '#partner_name' ).val( ).trim( );
    var hash = this.$( '#hash' ).val( ).trim( );
    var salt = this.$( '#salt' ).val( ).trim( );

    Users.create( { display_name: display_name, key_email_address: key_email_address, email_address: email_address, password: password, partner_name: partner_name, hash: hash, salt: salt } );
  }
});

// Модель пользователя

var UserModel = Backbone.Model.extend( {
  idAttribute: 'key_email_address'
});

// Коллекция пользователей

var UsersCollection = Backbone.Collection.extend( {
  model: User,

  url: 'users',

  initialize : function( models, options ) { },

  parse: function( data ) {
    this.result = data.result;
    return data.users;
  }
});

person James B    schedule 20.03.2013    source источник


Ответы (1)


Событие change не запускается, когда в элементах коллекции происходят какие-либо изменения.

Итак, ваша следующая строка не должна ничего делать:

this.listenTo( Users, 'change', this.updateOne );

вам нужно включить в свой метод UserView initialize следующее:

this.listenTo( this.model, 'change', this.render );

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

person neebz    schedule 21.03.2013
comment
Это не было полным решением, но оно указало мне правильное направление. В дополнение к событию listenTo на модели мне пришлось использовать this.model.save вместо Users.create в функции saveUsers. Спасибо за помощь. - person James B; 21.03.2013
comment
Ага ; Метод create — это скорее ярлык для создания + добавления в коллекцию. в вашем случае, когда вы редактируете существующую модель... вы должны использовать save - person neebz; 21.03.2013