将 KnockoutJS 与 jQuery UI Spinner一起使用



我现在正在使用jQuery UI的微调器与KnockoutJS和Durandal一起使用。我遵循了答案/示例在此处创建一个自定义绑定,该绑定负责初始化微调器和观察对微调器所做的更改。

现在,我已将其保存为要加载到 lib 文件夹中的通用模块,由将来需要使用微调器的模块调用。我的问题是,我想在这个特定的页面上检索微调器/每次微调器时进行ajax调用,从而更新数量。我知道我不可能将我的自定义 ajax 代码放在公共模块中,但我不知道把它放在哪里。

下面是执行数据绑定的 HTML:

<p class="qty">
    <input class="spinner" data-bind="spinner: quantity, spinnerOptions: { min: 1, numberFormat: 'n' }" />
    <a class="remove" href="#">Remove</a>
</p>

这是与 HTML 对应的代码:

function Item(data) {
    (...)
    self.updateQuantity = function(){
    $.ajax(apiUrl + self.id, {
        data: self.quantity,
        type: 'patch',
        contentType: 'application/json',
        success: function(result) {
            alert(result);
        }
        });
    };
}
(...)
     return {
    checkedOutItems: checkedOutItems, //checkedoutItems is an array of Item that's passed to the HTML, which can call Item's updateQuantity method
(...)
}

这是我基于上面的链接构建的通用模块:

define(function(require) {
    var system = require('durandal/system'),
    app = require('durandal/app'),
    ko = require('knockout');
    ko.bindingHandlers.spinner = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        //initialize datepicker with some optional options
            var options = allBindingsAccessor().spinnerOptions || {};
            $(element).spinner(options);
            //handle the field changing
            ko.utils.registerEventHandler(element, 'spinchange', function () {
        var observable = valueAccessor();
        observable($(element).spinner('value'));
            });
            //handle disposal (if KO removes by the template binding)
            ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
        $(element).spinner('destroy');
            });
    },
    update: function(element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor()),
        current = $(element).spinner('value'),
        msg = 'You have entered an Invalid Quantity. n Please enter at least 1 or remove this item if you do not want to include it in the shopping cart.';
        system.log(value);
        if(isNaN(parseInt(value))) {
        alert(msg);
        }
            if (value !== current && !isNaN(parseInt(value))) {
        $(element).spinner("value", value);
            }
    }
    };
});

据我所知,一旦可观察数量发生变化,我应该有类似data-bind="value: quantity, click: updateQuantity"调用 updateQuantity 函数的东西。但是,现在我正在使用微调器自定义绑定,我不再确定如何调用 updateQuantity 函数。每个更改都将由公共模块中的代码捕获(如 Chrome 检查器中显示的系统.log),但在我的页面.js中,我不知道在哪里以及如何调用捕获要在 ajax 调用中使用的新数量的函数。

我意识到我对 KnockoutJS 和数据绑定的理解仍然模糊(几周前才开始),所以如果有人能启发我应该从这里开始,我会很高兴。提前谢谢你。

进行 AJAX 调用和微调器彼此无关。 下面,我将向您展示我们如何做到这一点,但是使用SpinJS。 尽管库不同,但主体是相同的。

下面是微调器的自定义绑定:

ko.bindingHandlers.spinner = {
            init: function(element, valueAccessor) {
                var options = ko.unwrap(valueAccessor());
                var opts = {
                    lines: options .lines || 8,
                    length: options .length || 3,
                    width: options .width || 4,
                    radius: options .radius || 6,
                    color: options .color || '#FFF',
                    speed: options .speed || 1,
                    trail: options .trail || 100,
                    shadow: options .shadow == undefined ? false : value.shadow,
                    zIndex: options .zIndex || 2000
                };
                var spinner = new Spinner(opts).stop();
                $(element).data(element.id, spinner);
            },
            update: function(element, valueAccessor) {
                var options = ko.unwrap(valueAccessor()),
                    isSpinning = options .isSpinning,
                    positioning = options .positioning || 'manual',
                    spinner = $(element).data(element.id);
                if (isSpinning) {
                    if (positioning == 'manual') {
                        spinner.spin();
                        $(element)[0].appendChild(spinner.el);
                    } else if (positioning == 'auto') {
                        spinner.spin(element);
                    }
                } else {
                    spinner.stop();
                }
            }

下面是使用自定义绑定的视图:

<div data-bind="visible: isFetchingOpportunities()">
    <div id="activitySpinner" class="ts-ajax-spinner" data-bind="spinner: { isSpinning: isFetchingOpportunities() }">
    </div>
</div>

下面是支持上述视图的相应视图模型:

this.isFetchingOpportunities(true);
var that = this;
$.when(dataservice.getData(options, getFunction, modelmapper.opportunity))
     .then(function() {
         that.isFetchingOpportunities(false);
     });

现在,我们已经将 AJAX 调用打包到一个数据服务中,而数据服务又利用了 AmplifyJS。 但是,同样,校长是一样的。 您可以同样轻松地直接进行 AJAX 调用。

这有意义吗?

如果我理解正确,我认为您需要做的就是订阅可观察的数量并在该函数中进行 ajax 调用。 像这样的东西:-

注意:我将ko.utils.registerEventHandlerspinchange更改为spinstop

ko.bindingHandlers.spinner = {
  init: function(element, valueAccessor, allBindingsAccessor) {
    //initialize datepicker with some optional options
    var options = allBindingsAccessor().spinnerOptions || {};
    $(element).spinner(options);
    //handle the field changing
    ko.utils.registerEventHandler(element, 'spinstop', function() {
      var observable = valueAccessor();
      observable($(element).spinner('value'));
    });
    //handle disposal (if KO removes by the template binding)
    ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
      $(element).spinner('destroy');
    });
  },
  update: function(element, valueAccessor) {
    var value = ko.utils.unwrapObservable(valueAccessor()),
      current = $(element).spinner('value'),
      msg = 'You have entered an Invalid Quantity. n Please enter at least 1 or remove this item if you do not want to include it in the shopping cart.';
    if (isNaN(parseInt(value))) {
      alert(msg);
    }
    if (value !== current && !isNaN(parseInt(value))) {
      $(element).spinner("value", value);
    }
  }
};
var Vm = function() {
  var self = this;
  self.quantity = ko.observable(0);
  self.quantity.subscribe(updateData);
  function updateData(newValue) {
    //do ajax call here
    alert(newValue);
  }
  return self;
};
ko.applyBindings(new Vm());
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<p class="qty">
  <input class="spinner" data-bind="spinner: quantity, spinnerOptions: { min: 1, numberFormat: 'n' }" />
  <a class="remove" href="#">Remove</a>
</p>

最新更新