发布与淘汰赛订阅
问题描述:
地狱所有,发布与淘汰赛订阅
我有一点与儿童模型复杂的淘汰赛视图模型。以下是视图模型的定义:
var DailyItems = function (data) {
var p = this;
this.Date = ko.observable(data.Date);
this.Required = ko.observable(data.Required);
this.SetupTime = ko.observable(data.SetupTime);
this.CloseTime = ko.observable(data.CloseTime);
this.MinHrsPerDay = ko.observable(data.MinHrsPerDay);
this.MaxHrsPerDay = ko.observable(data.MaxHrsPerDay);
this.WorkSegments = ko.observableArray([]);
var records = $.map(data.WorkSegments, function (x) { return new WorkShift(p, x) });
this.WorkSegments(records);
this.EnableAdd = ko.computed(function() {
return this.WorkSegments().length < 8;
}, this);
this.Add = function() {
var data = {
Parent: p,
ID: "",
Date: this.Date,
Location: UNIT_ID,
Role: "",
EmployeeRoles: this.WorkSegments()[0].EmployeeRoles(),//add the roles of the first work segment
ShiftStart: "",
ShiftEnd: ""
};
var child = new WorkShift(p, data);
this.WorkSegments.push(child);
}
this.Delete = function (item) {
this.WorkSegments.remove(item);
}
};
var WorkShift = function (parent, data) {
var self = this;
this.Parent = ko.observable(parent);
this.ID = ko.observable(data.ID);
this.Day = ko.observable(data.Day);
this.Location = ko.observable(data.Location);
this.ShiftStart = ko.observable(data.ShiftStart);
this.ShiftEnd = ko.observable(data.ShiftEnd);
this.EmployeeRoles = ko.observableArray(data.EmployeeRoles);
this.Location.subscribe(function (branchId) {
$.ajax({
type: "POST",
url: SERVER_PATH + '/WebServices/AttributeService.asmx/GetDataOnLocationChange',
data: "{" + "clientId: '" + CLIENT_ID
+ "', unitId: '" + branchId
+ "', effectiveDate:'" + EFFECTIVE_DATE
+ "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (res) {
var d = JSON.parse(res.d);
self.EmployeeRoles(d.Roles);
var tasks = self.Parent().WorkSegments();
//Requirement: for any day of the week, if there is more than one work segment
//at different branches the required type should be set to 'On' and made disable
if (tasks.length > 1) {
for (var i = 0; i < tasks.length; i++) {
if ((d.IsSection == false && tasks[i].Location() != self.Location()) || (d.IsSection == true && self.ParentBranch() != tasks[i].ParentBranch())) {
self.Parent().Required('O');
}
else {
self.Parent().Required('E');
}
}
}
},
error: HandleLocationChangeError
});
}.bind(this));
this.Role = ko.observable(data.Role);
}
这里会发生什么事是,位置()在DailyItems(观察到的)是从下拉列表,它是通过主视图模型填充的值。当位置改变时,它应该根据所选位置更改EmployeeRoles()observablearray,因此是Location.Subscribe方法。
我的问题是,即使在初始数据加载期间,该订阅方法也会被调用。所以在开始时就有一个对服务器不必要的调用。我只希望在用户实际更改下拉选择时调用它。
我有什么方法可以实现这个目标?
问候, Chathu
答
以下是我的UI结合:
<tbody data-bind="foreach: WorkSegments">
<tr>
<td class="formFields">
ct class="combobox" data-bind="options:$root.WorkLocations, value:Location, optionsText: 'Name', optionsValue: 'ID', enable: LocationActive"
style="font-size: x-small; font-style: normal; font-family: Tahoma; width: 80px">
</select>
</td>
</tr>
</tbody>
这里的下拉选项从主视图模型设置。之后,所选元素被绑定。之后,当我在初始加载时调试代码时,Location订阅方法被调用。
答
将数据传递到WorkShift构造函数是触发位置observable上的change事件的原因。一种方法是在构建子代后将.subscribe调用移动到父对象,并且可观察值具有其初始值。
你的附加功能会再看看这样的事情:
this.Add = function() {
var data = {
// SNIP
};
var child = new WorkShift(p, data);
child.subscribe(function (branchId) {
$.ajax({
// SNIP
});
}.bind(child)); // <--- important to use child and not 'this'!!!
this.WorkSegments.push(child);
};
你会那么也必须使用的“本”,而不是“自我” Ajax调用里面,因为你已经绑定的这方面孩子。
答
如果它是第一次更改,它可以像运行AJAX调用一样简单吗?它并不漂亮,但很简单:
var locationInitialized = false;
this.Location.subscribe(function (branchId) {
if (!locationInitialized) {
locationInitialized = true;
return;
}
$.ajax({
...
当然,您可以在初始人口成功函数中设置locationInitialized。
另外,设置功能,但不订阅它,直到完成初始人口。 @explunit显示了一种方法来做到这一点。
我没有看到它在初始加载时被调用。我是否缺少一些代码?这里是我从你提供的东西创建的小提琴。 http://jsfiddle.net/sujesharukil/ywEP2/ – 2013-03-18 15:14:57