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

Я застрял в проблеме привязки JS. У меня есть основная модель представления, привязанная к странице оболочки моего одностраничного приложения. Эта masterviewmodel контролирует, какой вид в данный момент виден (с помощью Sammy JS). Он также содержит ссылки на подмодели представлений, которые привязаны к представлениям.

var app = function () {
    var self = this;

    self.State = ko.observable('home');

    self.Home = ko.observable(new homepageVm());
    self.User = ko.observable(new userInfoVm());
    self.Request = ko.observable(new requestVm());
};

Модель просмотра User имеет одно представление, к которому можно привязать следующее:

<div data-bind="with: User, visible: State() === 'user'">
    .. snip ..
</div>

Привязка with: гарантирует, что к представлению привязана правильная подвидовая модель. Этот подход отлично работает как для домашнего просмотра, так и для просмотра информации пользователя.

RequestVm использует пользовательский интерфейс в стиле мастера и требует привязки к нескольким представлениям. Вот где я застрял.

<div data-bind="with: Request, visible: State() === 'request-step-1'">
    .. snip ..
</div>

<div data-bind="with: Request, visible: State() === 'request-step-2'">
    .. snip ..
</div>

<div data-bind="with: Request, visible: State() === 'request-step-3'">
    .. snip ..
</div>

Привязки работают нормально, когда я запускаю сайт (Knockout не вызывает ошибок привязки). Но когда я начинаю передавать данные через виртуальные машины, они больше не обновляют пользовательский интерфейс, как будто все привязки нарушены (даже те, которые имеют одно представление, привязанное к ним, например пользовательская ВМ).

Если я включу только представление первого шага мастера, в результате чего у меня останется только одна привязка к виртуальной машине запроса вместо трех, все привязки в приложении снова начнут работать!

Я не понимаю, что вызывает это. Может ли нокаут привязать только одно наблюдаемое к одному элементу? Или я пробую что-то неподдерживаемое?

Обновление. Похоже, что-то происходит с observableArrays в моей виртуальной машине. Привязки к простым наблюдаемым работают нормально.

Вот одна из виртуальных машин:

    function userInfoVm() {
    var self = this;

    self.UserName = ko.observable();

    self.Beun = ko.observable();

    self.LoadingUser = ko.observable(false);
    self.LoadingObjects = ko.observable(false);

    self.UserData = ko.observableArray([]);
    self.UserObjects = ko.observableArray([]);

    self.LoadUser = function (userName) {

        self.LoadingUser(true);

        $.get('UserData/UserDetail', { username: userName }, function (details) {
            self.UserData(details);
            self.Beun(JSON.stringify(details));

            self.LoadingUser(false);
        });
    };

    self.LoadObjects = function (userName) {

        self.LoadingObjects(true);

        $.get('UserData/UserObjects', { username: userName }, function (objects) {
            alert(JSON.stringify(objects));
            self.UserObjects([objects]);
            self.LoadingObjects(false);
        });
    };

    self.Load = function (userName) {
        self.UserName(userName);

        self.UserData(null);
        self.UserObjects(null);

        self.LoadUser(userName);
        self.LoadObjects(userName);
    };
};

И представление, которое потребляет данные из указанной виртуальной машины:

<div data-bind="with: User, visible: State() === 'user'">
    <h1>
        <button class="backbutton" onclick="history.back();">
        </button>
        Details for user <span data-bind="text: UserName"></span>
    </h1>
    <div class="display detail">
        <table>
            <tbody data-bind="foreach: UserData">
                <tr>
                    <td class="property" data-bind="text: Key">
                    </td>
                    <td class="value" data-bind="text: Value">
                    </td>
                </tr>
            </tbody>
        </table>
        <div class="loader" data-bind="visible: LoadingUser">
            Please wait while we process your request...
        </div>
    </div>
    <div class="display detail">
        <h1>
            Objects and services for user <span data-bind="text: UserName"></span>
        </h1>
        <table class="detailtable">
            <tbody data-bind="foreach: UserObjects">
                <tr>
                    <td class="value">
                        <a class="service" data-bind="text: Value, attr: { href: '#/service/' + Key }" href="#">
                        </a>
                    </td>
                </tr>
            </tbody>
        </table>
        <div class="loader" data-bind="visible: LoadingObjects">
            Please wait while we process your request...
        </div>
    </div>
    Details for user <span data-bind="text: Beun"></span>
</div>

Массивы не уведомляют пользовательский интерфейс о данных, которые им передаются. Другие наблюдаемые объекты, включая объект .Beun, который содержит строковые данные из вызова AJAX, обновляются, как и ожидалось.


person Sander Harrewijnen    schedule 07.08.2012    source источник


Ответы (1)


Какой контент вы получаете с сервера?

Вы можете попытаться преобразовать данные (строку) в объекты с помощью eval (объекты) и преобразовать их в наблюдаемый массив с помощью подключаемого модуля сопоставления (knockout.mapping.js) внутри цикла foreach, если вы хотите сделать это вручную.

var data = '[{ "Id": 1, "Titel": "Title1", "Description": "Description 1" }, { "Id": 2, "Titel": "Title 2", "Description": "Description 2" }, { "Id": 3, "Titel": "Title 3", "Description": "Description 3"}]';
//fist convert your string to JS-objects using eval() ; then to observableArray using mapping pluging
self.UserObjects = ko.mapping.fromJS(eval(data));
person DiederikTiemstra    schedule 10.08.2012
comment
Данные поступают с сервера в формате JSON. Я пробовал несколько вещей, в том числе вручную обрабатывать элементы с сервера. К сожалению, из-за нехватки времени мне пришлось отказаться от всей системы вложенных моделей представления. Я не отказался полностью, хотя в (гораздо) меньшем доказательстве концепций он действительно работал, как ожидалось. - person Sander Harrewijnen; 10.08.2012