2010-12-13 4 views
5

Я создаю приложение, используя очень гладкую библиотеку KnockoutJS, но я столкнулся с проблемой. На странице html у меня есть простой элемент управления <select>, который я хочу загрузить с данными JSON, возвращаемыми из веб-службы.ObservableArray не отражает обновление данных

Я определяю наблюдаемый массив следующим образом:

var laborRow = function() { 
    this.positions = ko.observableArray([]); 
}; 

При загрузке страницы, вызов Ajax производится и данные возвращаются. В функции обратного вызова, я делаю следующее:

success: function (msg) { 
     laborRow.positions = msg; 
    } 

на основе документации KO, я бы ожидать, что я хотел бы установить результат, как этот:

laborRow.positions(msg); 

Однако, это просто выдает ошибку о том, что "laborRow.positions в не функции"

шаблон в HTML выглядит следующим образом:

<tbody data-bind='template: {name: "laborRowTemplate", foreach: laborLine}'> </tbody> 
</div> 
    <script type="text/html" id="laborRowTemplate"> 
     <tr> 

      <td><select data-bind='options: positions, optionsText: "Title", optionsCaption: "select", value: selectedPosition '></select></td> 

     </tr> 
    </script> 

Объект laborRow - свойство на ViewModel, которое привязано к странице. По какой-то причине это не работает. Чтобы добавить еще одну морщину, если я добавлю код, чтобы заглянуть в наблюдаемый массив и распечатать часть данных, данные там. Таким образом, он загружается успешно.

Любые мысли были бы весьма благодарны.

Полный код для моего примера случай:

var laborRow = function() { 
    this.positions = ko.observableArray([]);  
}; 

var projectEstimate = function() { 
    this.laborLine = ko.observableArray([new laborRow()]); 

}; 

var projectViewModel = new projectEstimate(); 
ko.applyBindings(projectViewModel); 

//and the code in the callback function on ajax success 

success: function (msg) { 
       laborRow.positions = msg; 
       //laborRow.positions(msg); **this does not work - error is laborRow.positions is not a function** 
      }, 

И в HTML:

<tbody data-bind='template: {name: "laborRowTemplate", foreach: 
laborLine}'> </tbody> 

    <script type="text/html" id="laborRowTemplate"> 
     <tr> 
      <td><select data-bind='options: positions, optionsText: 
"Title", optionsCaption: "select", value: selectedPosition '></ 
select></td> 

     </tr> 
    </script> 

Наконец, благодаря комментариям Шона ниже, я был в состоянии заставить его работать путем изменения кода в обратный вызов следующим образом:

success: function (msg) { 
    projectViewModel.laborLine()[(projectViewModel.laborLine().length-1)].positionList(msg); 
} 

ответ

5

Проблема в том, что вы на самом деле не создали свою модель:

var laborRow = function() { 
    this.positions = ko.observableArray([]); 
    // will only be called if you call var some_var = new laborRow() 
}; 

Измените функцию голого объекта (как показано на Knockout docs):

var laborRow = { 
    positions: ko.observableArray([]) 
}; 

И вы будете в состоянии назвать laborRow.positions(msg); и его работу.


EDIT

на основе нового кода, laborRow еще не экземпляр - если вы устанавливаете var laborRow где-нибудь еще в вашем коде (вокруг запроса Ajax, может быть), то вы будете хотеть чтобы убедиться, что ваш стек вызовов выглядит следующим образом:

projectViewModel.laborLine()[0].positions() 
// This will return the array you're looking for. 
// The key is that laborLine is a `getter` not an attribute 

Я укушенный «переменные kò являются getters не attributes» ошибка в ряде случаев ... может быть, это происходит с вашим кодом?

+0

Спасибо за ответ Шон. Я создал модель. В фактической viewModel у меня есть наблюдаемый массив, который при его создании начинает жизнь с нового объекта laborRow как такового: this.laborLine = ko.observableArray ([new laborRow()]); – Alex

+0

@Alex - отлично ... можете ли вы опубликовать немного больше своего кода? Как вы сейчас описываете, все * должно * работать. –

+0

@Alex - обновленный ответ, чтобы сделать еще один удар. –

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