将 KnockoutJS 与 jQuery UI 微调器一起使用
Using KnockoutJS with jQuery UI Spinner
我现在正在使用 jQuery UI 的微调器与 KnockoutJS 和 Durandal。我关注了 answer/example
here 创建一个自定义绑定,负责初始化微调器并观察对微调器所做的更改。
现在,我已将其保存为要加载到 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
(...)
}
这是我根据上面的 link 构建的通用模块:
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 函数。但是,现在我正在使用 spinner 自定义绑定,我不再确定如何调用 updateQuantity 函数了。每个更改都将被公共模块中的代码捕获(如 Chrome 检查器中的 system.log 所示),但在我的 page.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.registerEventHandler
从 spinchange
更改为 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>
我现在正在使用 jQuery UI 的微调器与 KnockoutJS 和 Durandal。我关注了 answer/example here 创建一个自定义绑定,负责初始化微调器并观察对微调器所做的更改。
现在,我已将其保存为要加载到 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
(...)
}
这是我根据上面的 link 构建的通用模块:
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 函数。但是,现在我正在使用 spinner 自定义绑定,我不再确定如何调用 updateQuantity 函数了。每个更改都将被公共模块中的代码捕获(如 Chrome 检查器中的 system.log 所示),但在我的 page.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.registerEventHandler
从 spinchange
更改为 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>