0

私は Knockout モデルを使用しており、jQuery UI の範囲スライダーを使用してこのモデルの値を更新したいと考えています。次の例を検討してください。

モデル:

var ViewModel = function () {
    var self = this;
    self.MinTerm = ko.observable();
    self.MaxTerm = ko.observable();
}

ko.applyBindings(new ViewModel());

これで、jQuery UI の範囲スライダーがこれら 2 つの値を更新するはずです。この (非常に醜い) ソリューションに近づき、ViewModel の値が更新されていますが、どういうわけか、これらの値にバインドされたコントロールには反映されません。

HTML

<div id="sliderTerms"></div>
<span data-bind="text: MinTerm"></span>
<span data-bind="text: MaxTerm"></span>

脚本:

    $("#sliderTerms").slider({
        range: true,
        min: 6,
        max: 120,
        values: [6, 120],
        step: 1,
        slide: function (event, ui) {
            ViewModel.MinTerm = ui.values[0];
            ViewModel.MaxTerm = ui.values[1];
        }
    });

ここで、次のようなカスタム bindingHandler にバインドできれば非常に便利です。これは、私の KO モデルでスライダーを特異値にバインドするのに最適です。

ko.bindingHandlers.slider = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var options = allBindingsAccessor().sliderOptions || {};
        $(element).slider(options);
        ko.utils.registerEventHandler(element, "slidechange", function (event, ui) {
            var observable = valueAccessor();
            observable(ui.value);
        });
        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).slider("destroy");
        });
        ko.utils.registerEventHandler(element, "slide", function (event, ui) {
            var observable = valueAccessor();
            observable(ui.value);
        });
    },
    update: function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        if (isNaN(value)) value = 0;
        $(element).slider("value", value);

    }
};

これは私が立ち往生するところです。たとえば、valueAccessors の配列を割り当てることができるので、次のようなことを実行できます。

<div id="sliderTerms" data-bind="rangeSlider: [MinTerm, MaxTerm], sliderOptions: {min: 6, max: 120, range: true, step: 1}"></div>

ありがとう!

4

3 に答える 3

1

私はあなたのものに基づいて自分自身を書きました。それはバグがある可能性があるための簡単なモックアップです

http://jsfiddle.net/N9uwx/

ko.bindingHandlers.slider = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var options = allBindingsAccessor().sliderOptions || {};
        var observable = valueAccessor();

        if(observable().splice) {
            options.range = true;        
        }        

        options.slide = function(e, ui) {
            observable(ui.values ? ui.values : ui.value);
        };

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).slider("destroy");
        });

        $(element).slider(options);
    },
    update: function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        $(element).slider(value.slice ? "values" : "value", value);

    }
};
于 2012-11-30T15:50:54.370 に答える
0

ありがとう!あなたのコードは、この bindingHandler を書くきっかけになりました:

ko.bindingHandlers.rangeSlider = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var options = allBindingsAccessor().sliderOptions || {};
        var observable = valueAccessor();

        ko.utils.registerEventHandler(element, "slidechange", function (event, ui) {
            observable[0](ui.values[0]);
            observable[1](ui.values[1]);
        });
        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).slider("destroy");
        });
        ko.utils.registerEventHandler(element, "slide", function (event, ui) {
            observable[0](ui.values[0]);
            observable[1](ui.values[1]);
        });

        $(element).slider(options);
    },
    update: function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
         if(value instanceof Array)
        {
            var value1= ko.utils.unwrapObservable(value[0]);
            var value2= ko.utils.unwrapObservable(value[1]);
            if(value1)
            {
                value = [value1, value2];
            }
            else value = 0;
        }
        else if (isNaN(value)) value = 0;
        $(element).slider(value.slice ? "values" : "value", value);
    }
}; 

これで、次のように rangeSlider を Knockout モデルにバインドできます。

<div id="sliderTerms" data-bind="rangeSlider: [MinTerm, MaxTerm], sliderOptions: {min: 6, max: 120, range: true, step: 1, values: [6,120]}"></div>

values[i] は valueAccessor[i] にバインドする必要があると想定しているため、少し臭いですが、これで十分です。

于 2012-12-03T10:57:39.087 に答える
0

@Nico Beemster が彼自身のコードで見つけたバグについては、更新を「更新」する必要があります: 次のような部分:

 update: function (element, valueAccessor, allBindingsAccessor) {
            console.log("update fired");
            var value = ko.utils.unwrapObservable(valueAccessor());
              if(value instanceof Array)
        {
            var value1= ko.utils.unwrapObservable(value[0]);
            var value2= ko.utils.unwrapObservable(value[1]);
            if(value1)
            {
                value = [value1, value2];
            }
            else value = 0;
        }
        else if (isNaN(value)) value = 0;
            $(element).slider(value.slice ? "values" : "value", value);
             $(element).slider("option", allBindingsAccessor().sliderOptions);
        }

これが更新されたフィドルです。観測可能な要素である場合に、最大範囲要素と最小範囲要素を更新する場合。

于 2014-12-22T18:01:58.080 に答える