knockout.js - How to handle many to many relationship in knockout viewmodels -
i have many many relation in schema between 2 tables service , employee (a service can performed multiple employees , employee can perform multiple services) . used serviceemployee junction table creating relationship.
i using knockout @ client side. knockout viewmodels create through knockout.mapping plugin server side viewmodel. @ server side have 3 viewmodel are:
employeemodel (contain list of serviceemployeemodel)
servicemodel (contains list of serviceemployeemodel)
serviceemployeemodel (contains serviceid, employeeid) [cant include employee , service object in order avoid self reference loop @ client side]
now @ client side have 3 modules:
employee module
function employee(data) { var self = this; ko.mapping.fromjs(data, { "services": { create: function (options) { return new serviceemployee(options.data, options.parent); } } }, self); .... }
service module
function service(data) { var self = this; ko.mapping.fromjs(data, { "employees": { create: function (options) { return new serviceemployee(options.data, options.parent); } } }, self); .... }
serviceemployee module
function (data, parent) { var self = this; ko.mapping.fromjs(data, self); //if parent object has property employeeid means parent object employee //object , add 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 means parent object service //object , add 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; } } }); } }
the approach using working feel there should other better way of handling kind of scenario. because in approach if assign services employee or employees service have manually update employees , services array , feel there should better way knockout update these array me.
computed observable may solution can't how. can please me solve issue ?
solution a:
you might want try breeze: http://www.breezejs.com/ don't support many many relationships directly, if expose navigaiton object this:
service.employees // array of serviceemployee serviceemployee.employee // employee serviceemployee.service // service employee.services // array of serviceemplyee
breeze provides mechanisms automaticly keeping track of employees , services related, allowing this:
var myemployeesservices = ko.computed(function () { return myemployee.services().map(function (a) { return a.service; }; ); // date array of services related specific employee var newservice = entitymanager.createentity("service", {}) //entitymanager class defined breeze //createentity function provided create new breeze managed objects var newservicelink = entitymanager.createentity("serviceemployee", { employeeid: myemployee.id, serviceid: newservice.id }); // creates new serviceemployee object linking myemployee , newservice // myemployeeservices contains newservice
if want use breeze you'll have read on other breeze functions, such loading , saving data, etc.
solution b:
you may want take @ ignore property of ko.mapping plugin, try example:
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; }
if wrote mapping part correctly (not sure if did, check here more details http://knockoutjs.com/documentation/plugins-mapping.html) when unmap employee model mapping plugin should ignore serviceobjects computed
you add write function add array adding , removing objects services array in response changes in serviceobjects array.
solution c:
take @ other solution: knockout js observablearray many-to-many relationships
Comments
Post a Comment