Как обновить пользовательскую привязку по нажатию кнопки?

Одним нажатием кнопки я хочу обновить график d3js на основе значений двух выбранных элементов. Если я правильно понимаю, просто позвонив valueAccessor должен запустить функцию обновления, которая не происходит в моем коде.

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

ko.bindingHandlers.plotSvg = {
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        valueAccessor();
        console.log("Update d3js plot");
    }
};

И мнение:

    <div class="panel-body">
        <div class="row">
            <div class="col-xs-2">
                <select class="form-control"
                        data-bind="options: $root.options,
                                           optionsText: 'name',
                                           value: firstSelectedOption">
                </select>
            </div>
            <div class="col-xs-2">
                <select class="form-control"
                        data-bind="options: $root.options,
                                           optionsText: 'name',
                                           value: secondSelectedOption">
                </select>
            </div>
            <div class="col-xs-2 col-xs-offset-5">
                <button class="btn btn-primary" data-bind="click: updatePlot">
                    Visualise
                </button>
            </div>
        </div>
        <div data-bind="plotSvg: updatePlot"></div>
    </div>

updatePlot является функцией в модели представления, и все, что она делает, это печатает значение в данный момент.

редактировать JavaScript: http://pastebin.com/2qKLf6yf вид: http://pastebin.com/TPvmKgxL

2 ответа

Решение

<div data-bind="plotSvg: updatePlot"></div> должен ссылаться на вычисленное, иначе нокаут не будет знать, когда значение чего-либо изменилось, и, следовательно, никогда не будет запускать метод обновления пользовательской привязки.

Я бы порекомендовал что-то вроде:

<div data-bind="plotSvg: selectedValue"></div>

а также

ko.bindingHandlers.plotSvg = {
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        viewModel.redrawPlot();
        console.log("Update d3js plot");
    }
};

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

Поскольку вы используете два значения, вы можете сделать что-то подобное в viewModel, чтобы вызвать наблюдаемое изменение:

this.selectedValue = ko.observable(null);
this.updatePlot = function(){
    this.selectedValue(this.firstSelectedOption()+""+this.secondSelectedOption()+"")
}

Делая это таким образом, вы получите уникальную строку каждый раз, когда изменяется один из параметров. Если ни то, ни другое не меняется, то наблюдаемое не изменится, и график не должен перерисовываться. Это грубая сила, но она должна работать с тем, что у вас есть.

Когда вы звоните valueAccessor() Вы просто получаете значение аксессора, поэтому для вызова функции попробуйте это: valueAccessor()(),

  • valueAccessor - функция JavaScript, которую можно вызвать, чтобы получить свойство текущей модели, участвующее в этой привязке. Вызывайте это без передачи каких-либо параметров (например, вызывайте valueAccessor()), чтобы получить значение свойства текущей модели. Чтобы легко принимать как наблюдаемые, так и простые значения, вызовите ko.unwrap для возвращаемого значения.

Ссылка http://knockoutjs.com/documentation/custom-bindings.html

Другие вопросы по тегам