Можно ли передать в Knockout значение по умолчанию для элемента select при привязке опций через AJAX? - PullRequest
1 голос
/ 05 марта 2012

Мне нужно получить как текущее значение, так и доступные параметры <select /> через два разных вызова AJAX (я не могу поставить их в очередь / по нескольким причинам).

Я не знаюЯ не знаю, имеет ли это значение, но вызов, считывающий текущее значение, завершается до того, как вызов прочитает доступные параметры каждый раз.

Использование Knockout 2.0.0 и Knockout Mapping 2.0.3 Я ограничил выбор с помощью data-bind="options: values, value: valueComputed", ноЯ обнаружил, что Knockout удаляет / игнорирует значение, установленное первым вызовом AJAX, до тех пор, пока вызов, извлекающий доступные опции, не завершится, невозможно установить текущее значение.

Это правильно?Можно ли сказать Knockout «это текущее значение, когда станут доступны доступные опции, выберите его»?

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

Я делаю что-то зло?

Пример jsFiddle: http://jsfiddle.net/KeNUU/

Код JavaScript, который я использую:

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

    // The underlying observable where
    // the selected value is stored.
    self.value = ko.observable();

    // The observable bound to
    // the value of the drop down.
    self.values = ko.mapping.fromJS([]);

    // Use a computed observable to intercept the undefined
    // value placed by KnockOut when binding the drop down.
    self.valueComputed = ko.computed({
        "read": function () {
            return ko.utils.unwrapObservable(self.value);
        },
        "write": function (value) {
            // Update the underlying observable only when
            // there is a value, if it's undefined ignore it.
            if (value) {
                self.value(value);
            }
        }
    });

    // Simulate the AJAX request which fetches the actual value,
    // this request must complete before the second one.
    setTimeout(function () {
        self.valueComputed("b");
    }, 1000 * 1);

    // Simulate the AJAX request which fetches the available values,
    // this reqest must complete after the first one.
    setTimeout(function () {
        ko.mapping.fromJS(["a", "b", "c", "d"], {}, self.values);
    }, 1000 * 2);
};

$(document).ready(function () {
    ko.applyBindings(new viewModel());
});

1 Ответ

2 голосов
/ 05 марта 2012

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

Я думаю, что более простой выбор - просто кэшировать начальное значение в ненаблюдаемой области, а затем использовать его для заполнения value при возврате списка.Если бы список был первым, то не было бы начального значения, и оно могло бы работать как обычно.

Что-то вроде:

setTimeout(function () {
    self.initialValue = "b";
    self.value("b");
}, 1000 * 1);

// Simulate the AJAX request which fetches the available values,
// this reqest must complete after the first one.
setTimeout(function () {
    ko.mapping.fromJS(["a", "b", "c", "d"], {}, self.values);
    if (self.initialValue) {
         self.value(self.initialValue);
         self.initialValue = null;
    }    
}, 1000 * 2);

http://jsfiddle.net/rniemeyer/gB3E5/

Теперь выобрабатывать это заранее без (незначительных) накладных расходов на вычисляемый наблюдаемый перехват при каждом изменении раскрывающегося списка.

...