2014-09-18 3 views
1

У меня есть массив «пользователей» в наблюдаемом массиве KnockoutJS. Я могу добавить пользователей в массив, и он корректно обновляет представление, но редактирование пользователей в настоящее время приводит меня в бешенство, возможно, из-за небольшого отсутствия понимания базовой концепции с моей стороны.Обновить элемент массива в нокауте js

вид Модель

var viewModel = { 
    users: ko.observableArray(), 
    user: ko.observable(), 
    showEditForm: function (model) { 
     if (!$('#users-form').is(':visible')) { 
      $('#mask').show(); 
     } 
     showUsersLoading(); 
     loadUserIntoEditForm(model.Id); 
    }, 
    getUser: function (userId) { 
     for(var i = 0; i < this.users().length; ++i) 
     { 
      if (this.users()[i].Id === userId) 
      { 
       this.user(this.users()[i]); 
       break; 
      } 
     } 
    } 
}; 

пользователя Посмотреть Модель (это в основном используется для функциональных возможностей добавления в данный момент)

var userViewModel = function (id, username, statusDescription, email) { 
     var self = this; 
     self.Id = ko.observable(id), 
     self.Name = ko.observable(username), 
     self.StatusDescription = ko.observable(statusDescription), 
     self.Email = ko.observable(email) 
    }; 

Обновления/редактирование выполняется в частичном виде MVC, который выстреливает ajax-запрос для обновления пользовательского сервера, затем при успешном ответе, выполняется следующий код для обновления пользователя

viewModel.getUser(result.Id); 
viewModel.user().StatusDescription('locked'); 
viewModel.user().Name('testingUpdate'); 

Который дает мне Uncaught TypeError: string is not a function Ошибка

Здесь я понимаю, что не в порядке. Я понимаю, что пользователь, которого я захватил из массива users, не имеет наблюдаемых свойств, поэтому я не могу обновить его с помощью метода функции Knockout, я подтвердил это, вытащив детали массива пользователей в окно консоли браузера.

Я также знаю, что, концептуально, я хочу, чтобы пользовательский наблюдаемый объект был привязан к объекту userViewModel, поэтому свойства становятся видимыми, и я могу их обновить; или я хочу, чтобы пользователи наблюдаемого массива знали, что объекты, которые он содержит, должны иметь тип userViewModel, поэтому свойства объекта наблюдаемы.

Проблема, с которой я сталкиваюсь, хотя я понимаю концепцию, я не могу понять код, чтобы заставить его работать.

ответ

0

Как всегда, легкий ответ: я идиот.

Ключевая часть, которую я отсутствовала, забывает, что я не имею дело с сильно типизированными объектами и полагаю, что они будут работать так, как я ожидаю.

Успех обратного вызова для моего AJAX вызова заселить пользователей() массива в объекте ViewModel имел обыкновение быть

success: function (data) { 
    viewModel.users(data) 
    setupDatatable(); 
} 

Который, оглядываясь на него, проблема очевидна. Я вставляю общие объекты в массив, а не объекты userViewModel.

Так что, когда я изменил его:

success: function (data) { 
    for (var i = 0; i < data.length; ++i) { 
     viewModel.users.push(new userViewModel(data[i].Id, data[i].Name, data[i].StatusDescription, data[i].Email)); 
    } 
    setupDatatable(); 
} 

Внезапно он начал работать.

Надеюсь, моя тупость и дни стоит от головной боли поможет кому-то еще :)

1

Проблема: ключевое слово . В вашем примере это не означает, что вы ожидаете.

Попробуйте использовать RMP (раскрывающий шаблон модуля), чтобы упростить способ написания кода. Это выглядит примерно так:

var viewModel = (function() { 
    var users = ko.observableArray(); 
    var user = ko.observable(); 

    // This one changes: you can use the vars directly 

    var getUser = function (userId) { 
     for(var i = 0; i < users().length; ++i) 
     { 
      if (users()[i].Id === userId) 
      { 
       user(this.users()); 
       break; 
      } 
     } 
    } 

    // Reveal the data 

    return { 
     users: users, 
     user: user, 
     getUser : getUser 
    }; 

})(); // self-executing anonymous function 

Анонимная функция закрывает ваши вары. Вы можете безопасно использовать вары в этом закрытии, и они недоступны за его пределами. Кроме того, вы можете иметь «частные вары», просто не раскрывая их.

Дополнительное примечание: Я рекомендую вам использовать lodash или underscore для упрощения работы с массивом: вы бы избежать написания петель, чтобы найти элемент в массиве. Например, используя lodash find.

+0

Спасибо за ответ, но я все еще получаю ту же ошибку. Одним из небольших изменений, которые мне пришлось внести в ваш код, был пользователь (this.users()); просто заполнил пользовательский объект полным списком пользователей, поэтому я изменил его на пользователя (this.users() [i]); –