我的架构中有两个表服务和员工之间的多对多关系(一个服务可以由多个员工执行,一个员工可以执行多个服务的) 。我使用 ServiceEmployee 联结表来创建此关系。
我在客户端使用淘汰赛。淘汰视图模型是通过服务器端viewmodel的knockout.mapping插件创建的。在服务器端,我有3个viewmodel:
EmployeeModel(包含ServiceEmployeeModel 列表)
ServiceModel(包含ServiceEmployeeModel 列表)
ServiceEmployeeModel(包含ServiceId,EmployeeId)[不能包括Employee和 服务对象以避免客户端的自引用循环]
现在在客户端我有3个模块:
员工模块
function Employee(data)
{
var self = this;
ko.mapping.fromJS(data, {
"Services": {
create: function (options) {
return new serviceEmployee(options.data, options.parent);
}
}
}, self);
....
}
服务模块
function Service(data)
{
var self = this;
ko.mapping.fromJS(data, {
"Employees": {
create: function (options) {
return new serviceEmployee(options.data, options.parent);
}
}
}, self);
....
}
ServiceEmployee模块
function (data, parent)
{
var self = this;
ko.mapping.fromJS(data, self);
//If parent object has property EmployeeId it means the parent object is Employee
//object and we will add only related Service (not Employee) in order
//to avoid self reference loop.
if (parent.EmployeeId) {
self.Service = ko.computed(function () {
if (self.ServiceId()) {
var services = require("modules/tenant").services();
if (services) {
var assignedService;
ko.utils.arrayFirst(services(), function (service) {
if (service.ServiceId() === self.ServiceId()) {
assignedService = service;
return true;
}
});
return assignedService;
}
}
});
}
//If parent object has property ServiceId it means the parent object is Service
//object and we will add only related Employee (not Service) in order
//to avoid self reference loop.
if (parent.ServiceId) {
self.Employee = ko.computed(function () {
if (self.EmployeeId()) {
var staff = require("modules/tenant").staff();
if (staff) {
var assignedEmployee;
ko.utils.arrayFirst(staff(), function (employee) {
if (employee.EmployeeId() === self.EmployeeId()) {
assignedEmployee = employee;
return true;
}
});
return assignedEmployee;
}
}
});
}
}
我正在使用的方法正在运行,但我觉得应该有一些其他更好的方法来处理这种情况。因为在这种方法中如果我们将服务分配给员工或员工服务,那么我们必须手动更新Employees和Services数组,我觉得应该有更好的方法,以便淘汰赛将为我更新这些数组。
计算的可观察量可能是解决方案,但我无法得到它。有人可以帮我解决这个问题吗?
答案 0 :(得分:0)
解决方案A:
您可能想尝试使用breeze:http://www.breezejs.com/它们不直接支持多对多关系,但是如果您公开navigaiton对象:
Service.Employees // Array of ServiceEmployee
ServiceEmployee.Employee // Employee
ServiceEmployee.Service // Service
Employee.Services // Array of ServiceEmplyee
Breeze提供了自动跟踪哪些员工和服务相关的机制,允许您这样做:
var myEmployeesServices = ko.computed(function () {
return myEmployee.Services().map(function (a) {
return a.Service;
};
); // an always up to date array of services related to a specific employee
var newService = entityManager.createEntity("Service", {})
//entityManager is a class defined by breeze
//createEntity is a function provided to create new breeze managed objects
var newServiceLink = entityManager.createEntity("ServiceEmployee", {
EmployeeId: myEmployee.Id,
ServiceId: newService.Id
}); // creates a new ServiceEmployee object linking myEmployee and newService
// myEmployeeServices now also contains newService
如果你想使用微风,你必须阅读其他微风功能,例如加载和保存数据等。
解决方案B:
您可能需要查看ko.mapping插件的ignore属性,例如尝试此操作:
function Employee(data)
{
var self = this;
ko.mapping.fromJS(data, {
"Services": {
create: function (options) {
return new serviceEmployee(options.data, options.parent);
}
}
}, self);
self.ServiceObjects = ko.computed(function () {
var staff = require("modules/tenant").services();
return staff().filter(function (a) {
return self.Services.filter(function (b) {
return b.ServiceId() == a.ServiceId();
}).length;
})
});
....
}
function serviceEmployee(data, parent) {
this.EmployeeId = parent.EmployeeId || data.EmployeeId;
this.ServiceId = parent.ServiceId || data.ServiceId;
}
如果我正确地编写了映射部分(不确定我是否这样做,请在此处查看更多详细信息http://knockoutjs.com/documentation/plugins-mapping.html)然后当您取消映射员工模型时,映射插件应忽略您的ServiceObjects计算
您还可以通过添加和删除Services数组中的对象来响应ServiceObjects数组中的更改,添加要添加到数组的写入函数。
解决方案C:
看看这个其他解决方案:Knockout JS ObservableArray with many-to-many relationships