базовый javascript и knockout.js в приложении MVC 3: проблема с циклом for в массиве элементов myCustomObject - PullRequest
0 голосов
/ 26 августа 2011

Проблема:

Я пытаюсь использовать knockout.js с шаблонами jquery.Проблема в том, что вызов $ .ajax возвращает значения правильно, но когда я пытаюсь вставить их в соответствующий ko.observableArray, я получаю правильное количество строк, но все значения равны undefined

.проблема, согласно моей отладке, находится в цикле for в успешном обратном вызове для вызова $ .ajax.

Кажется, что если я напишу:

for (item in myArray)
{
    alert(item.myProperty); // shows undefined
}

Что я делаюнеправильно ??!

Подробная настройка приведена ниже.

Настройка:

Мой шаблон:

<fieldset style="padding-top:10px;">
    <legend>Associated Cost Centres</legend>
    <table>
        <thead>
            <tr>
                <th>
                    Cost Centre
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody data-bind="template: {name:'actividadesAsociadas', foreach: viewModel.costCentres}"></tbody>
    </table>
</fieldset>
<script type="text/x-jquery-tmpl" id="actividadesAsociadas">
    <tr>
        <td data-bind="text: NameCC"></td>
        <td data-bind="text: CostCentreId"></td>
        <td><a href="#" data-bind="click: remove">Delete</a></td>
    </tr>
</script>

Мой JavaScript-код:

function costCentre(CostCentreId, IdTransactionType, NameCC, ownerViewModel) {

    this.CostCentreId      = ko.observable(CostCentreId); 
    this.IdTransactionType = ko.observable(IdTransactionType); 
    this.NameCC            = ko.observable(NameCC);
    this.remove            = function() { ownerViewModel.costCentres.destroy(this) }
} 



function costCentreViewModel() { 

   // other methods

   this.costCentres = ko.observableArray([]);

    var self = this;self = this;
    $.ajax({url: "/[...route...]/GetCostCentres/" + @id,
        dataType: 'json',
        data: {},
        type: 'POST',
        success: function (jsonResult) {
            var mappedCostCentres = $.map(jsonResult, function(item) {
            return new costCentre(item.CostCentreId, item.IdTransactionType, item.Name, self)
             });
             for (cc in mappedCostCentres)
             {
                 self.costCentres.push(new costCentre(cc.CostCentreId, cc.IdTransactionType, cc.NameCC, self));
             }
       },
       error: function (result) {
             $('#ErrorDisplay').show().html('<p>' + result.responseText + '</p>');
       }
    });
    // test data
    this.costCentres.push(new costCentre(55, 54, "test", this));

    // other methods
}; 

var viewModel = new costCentreViewModel();
jQuery(document).ready(function () { ko.applyBindings(viewModel); });

Бит, где проблема возникает в коде JavaScript:

for (cc in mappedCostCentres)
{
    self.costCentres.push(new costCentre(cc.CostCentreId, cc.IdTransactionType, cc.NameCC, self));
}

Причина в том, что cc.CostCentreId, cc.IdTransactionType и cc.NameCC оцениваются как undefined.

Я знаю, что это так, потому что тестовые данные правильно отображаются шаблоном jquery.tmpl, тогда как строки, введенные вызовом $ .ajax, просто отображаются как пустые теги.

jsonResult:

jsonResult, возвращаемый вызовом $ .ajax, выглядит следующим образом (это правильно):

    [{"CostCentreId":5,"IdTransactionType":2,"Name":"Impuestos"},
{"CostCentreId":14,"IdTransactionType":3,"Name":"Transferencias Internas"}]

Вопросы:

  1. Настроив цикл for в (for(cc in mappedCostCentres)), почему:

cc.NameCC

оценивается как undefined, несмотря на то, что в firebug можно увидеть, чтоэлементы в mappedCostCentres имеют ожидаемые значения?

  1. Какой лучший, или вернее, рабочий способ заполнить один массив из другого массива?

Редактировать:

Я сейчас пытаюсь следующий код:

в моей ViewModel (costCentreViewModel), я определяю:

this.GetCostCentres = function() {
    $.ajax({url: "/Admin/Accounts/GetCostCentres/" + @id,
            dataType: 'json',
            data: {},
            type: 'POST',
            success: function (jsonResult) {
                var mapped = $.map(jsonResult, function(item) {
                    return new costCentre(item.CostCentreId, item.IdTransactionType, item.Name, self)
                });
                self.costCentres = ko.observableArray(mapped);
                alert(self.costCentres.length);
            },
            error: function (result) {
                $('#ErrorDisplay').show().html('<p>' + result.responseText + '</p>');
        }
    });
};

Затем я вызываю (вне определения Viewmodel модели):

var viewModel = new costCentreViewModel();
viewModel.GetCostCentres();
jQuery(document).ready(function () { ko.applyBindings(viewModel); });

Это все еще не работает.Проблема в моем уме:

Почему эта строка не работает (все остальное работает):

self.costCentres = ko.observableArray(mapped);

Я могу только думать, что я определил свой объект модели представления,используя шаблон конструктора, то есть:

function myViewModel() {
this.costCentres= ko.observableArray([]);

...

this.GetCostCentres = function() {
   $.ajax(....);

}

, но я, честно говоря, понятия не имею.JavaScript побеждает меня прямо сейчас.Может мне вернуться к квантовой космологии?

Ответы [ 2 ]

2 голосов
/ 27 августа 2011

Похоже, основная проблема заключалась в том, что при попытке установить значение observableArray в результате запроса AJAX вы устанавливали его равным новому observableArray, а не устанавливали значение существующего, которое уже было привязано кваш пользовательский интерфейс.

Итак, self.CostCentres = ko.observableArray (mapped) `создаст новый массив observableArray, с которым ваш пользовательский интерфейс в настоящее время не связан.

self.CostCentres(mapped) будет подходящим способомустановить существующий массив observableArray равным совершенно новому массиву.

В предыдущей попытке выглядело, как будто вы дважды создавали CostCentre, чтобы поместить его в свой observableArray.Каждый CostCentre необходимо создать только один раз.

0 голосов
/ 27 августа 2011

Проблема во многом связана с:

  1. мое незнание javascript.

  2. копирование учебника knockoutjs.com для загрузки и сохранения данных с использованием стука и отсутствия понимания того, что в учебной среде отсутствуют строки кода js для вызова объекта viewmodel.

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

Комментарии Нимейера под вопросом помогли мне вернуться на правильный путь. Но для любого, кто имеет такой же уровень незнания JavaScript, как я, вы можете скопировать или адаптировать учебный код на knockoutjs.com, просто не забудьте добавить в нижней части эквивалент (т. Е. В зависимости от того, что делает ваш код):

var viewModel = new costCentreViewModel();
viewModel.GetCostCentres();
jQuery(document).ready(function () { ko.applyBindings(viewModel); });

Это эффективно запускает ваш код, в отличие от странных вещей, которые я не в состоянии описать или проанализировать ...

Примечание

Я добавил этот ответ на случай, если кто-нибудь придет с той же проблемой, что и я, и расскажет о том, что сработало, что последовало советам Р. П. Нимейера и заставило его работать.

Если Р.П. Нимейер добавит ответ, суммируя его предложения, я удалю этот ответ и отмечу его как решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...