map-deep-merge
Perform a smart merge of deeply nested maps and lists.
mapDeepMerge( instance, data )
The can-connect/helpers/map-deep-merge
module exports a function that
merges nested can-define/map/map or can-define/list/list instances.
var mapDeepMerge = require('can-connect/helpers/map-deep-merge');
var type = new Type({ ... });
mapDeepMerge(type, { ... });
var list = new Type.List([ ... ]);
mapDeepMerge(list, [ ... ]);
To properly know how to merge can-define instances of a can-define/list/list,
mapDeepMerge
needs to know how to:
- uniquely identify the instances
- create instances from raw data (hydration)
mapDeepMerge
solves this by first identifying the [can-define.types.TypeConstructor]
of the # (index) property definition.
With the Type
known of each item in the list, mapDeepMerge
looks for for a Type.algebra
to
specify the unique [can-set.props.id] of Type
instances. If Type.algebra
does
not exist, it looks for an id
and then _id
property.
With the Type
known of each item in the list, mapDeepMerge
looks for a Type.connection.hydrateInstance(props)
method. If one does not exist, new Type(props)
is used instead.
Parameters
- instance
{can-define/map/map|can-define/map/list}
:An instance to apply a merge to.
- data
{Object|Array}
:An object or array with the updated data.
Use
This method is often used by mixing in the can/merge behavior into a connection.
It can be used directly to update a can-define/map/map instance or can-define/list/list instance with nested data as follows:
var mapDeepMerge = require("can-connect/helpers/map-deep-merge");
var myMonth = new ContributionMonth({
id: 1,
month: "Feb",
osProjects: [ { id: 1, title: "canjs" }, {id: 2, title: "jQuery++"} ],
author: {id: 5, name: "ilya"}
});
mapDeepMerge( myMonth, {
id: 1,
month: "February",
osProjects: [ { id: 1, title: "CanJS" }, {id: 3, title: "StealJS"}, {id: 2, title: "jQuery++"} ],
author: {id: 6, name: "ilya"}
});
This will create the following changes:
// 1 - a property update
contributionMonth.name = "February";
// 2 - a property update on an item of a list
contributionMonth.osProjects[0].name = "CanJS";
// 3 - item insertion
contributionMonth.osProjects.splice(1,0, hydrateInstance({id: 3, name: "StealJS"}) )
// 4 - a map replacement (`id` is different)
contributionMonth.author = hydrateInstance( {id: 6, name: "ilya"} )