Knockout mapping of complex structure with arrays

瀏覽次數:185 次
跳到第一則未讀訊息

Silan Liu

未讀,
2016年7月24日 清晨7:22:052016/7/24
收件者:KnockoutJS
Suppose an Ajax call gets back a complex structure:

Company
 - CompanyName
 - Address
 - Array of Departments

Each Department has following structure:
- DepartmentName
- Array of Employees

Each Employee has 
 - EmployeeName
 - DOB
 .......

When I do a simply ko.mapping.fromJS:

var viewModel;

 

$.ajax({

    url: '......'

    type: 'GET',

    dataType: 'JSON',

    success: function (company) {

        var data = JSON.parse(company);

        viewModel = ko.mapping.fromJS(data);

        ko.applyBindings(viewModel, $('#company').get(0));

    },

    error: function (result) {

        //handle the error, left for brevity

    }

});

Will all departments and all employees and EmployeeName and DOB become observables and observable arrays? Or only the top-level properties such as CompanyName and Address become observables?

noirabys

未讀,
2016年7月29日 上午9:19:282016/7/29
收件者:KnockoutJS
hi,
i think default with no mapping options is that primitives will become observables and observableArrays and objects will stay objects and its not limited to top level

ko.mapping.fromJSON('{ a: { b: { c:"a"}}}');

a = object
b = object
c is observable

Бобан Стојановски

未讀,
2016年8月28日 清晨7:41:212016/8/28
收件者:KnockoutJS
As noirabys said, all of the properties and arrays will be observable. I think for testing you can go with this simple approach, but if you build serious application you must control this yourself. I don't think that all properties of every type of object should be observable, and there are many reasons that not to be the case. From the objects name in the description i can sense that performance will not be a problem here, but is one of main reasons why you need to limit the number of observables to the minimum. Also working only with observables will increase the complexity in the javascript/typescript unnecessarily.
Check the documentation for ways how to control this. You should first create custom types for all of your entities and create custom mapping configuration for all of them inside of their constructors.
The constructor of Company can look something like this:
export class Company {
public departments: KnockoutObservableArray<Department>;
public name: string;
public address: KnockoutObservable<string>;

constructor(json: any) {
    var self: any = this;
    var mapping: Object = {
        "departments": { "create": (options: KnockoutMappingCreateOptions) => new Department(options.data, self) },
        "copy": ["name"]
    }
    ko.mapping.fromJS(json, mapping, self);
}
}

In the sample that is written in typescript I decided to make the name property static and address as observable. The Department class will be created in the similar fashion. I put the self in the second parameter in the department's constructor in order to be used to set a property like 'parent' if you need to go access Company properties inside of Department. This practice is a common one when creating an objects tree.
回覆所有人
回覆作者
轉寄
0 則新訊息