The framework merges a component's defaults with the options
specified by the user at runtime. Default options for
a component are registered by the component developer using the fluid.defaults()
function. The framework combines
these values with those supplied by the user to the component creator function.
Left unchecked, this options merging code becomes unruly and verbose. The vast majority of merging can be taken care of
by a simple call to a standard "object merging function" such as jQuery.extend
- however, there are a few cases where
this behaviour is inappropriate, and where manual merging code might still be required.
The Fluid component API therefore contains a specialised merging routine, fluid.merge
, which allows the user to
specify an (optional) more fine-grained merge policy object, which allows detailed behaviour during options merging
to still be specified by a declarative strategy.
Use of fluid.merge
fluid.merge
is invoked automatically by the framework as part of standard component initialisation. However, the
component author does have the capability of directing the operation of fluid.merge
by means of specifying the
policy
object. Every standard Fluid component accepts a top-level option named mergePolicy
which will be supplied
as the policy argument to fluid.merge
. This option itself also undergoes merging, although the user may not specify
policy for the merging of the mergePolicy, and users may contribute material into the mergePolicy from any parent
grades of the component, arguments, etc.
Structure of the Merge Policy Object
The merge policy object is a hash of keys, which represent EL paths into the target object, onto values which represent a policy.
By default if there is no policy specified, a deep merge is done together with
expansion. Firstly, any IoC references and expanders in the source objects will be
expanded. Secondly, everything in the source objects are copied over the target object, in a manner very similar to the
operation of the jQuery API method $.extend(true, ...)
. Anything that existed in the target but was not present in any
of the source objects will continue to be present in the resulting merged object.
The following are the policy types that are supported, determined by the key's value in the policy object. For the
custom policies in the first three rows, combinations may be applied by separating them with commas - e.g. noexpand
,
nomerge
.
Policy Value | Description |
---|---|
"replace" |
If any value is found at the EL path in a source object, the value held at the
target path will be cleared (that is, blasted back to an empty state with no properties)
before the values are copied.
|
"noexpand" |
Apply no expansion to any of the options material in the
tree below this path. Unless you also specify nomerge , although no expansion occurs, the
contents of the source options will be merged together as if they consist of pure JSON material.
|
"nomerge" |
Can be specified together with, or separately from, noexpand . This directs the framework to
perform no merging when multiple values are discovered at the same path - instead, the rightmost value
from any of the sources will be chosen as the final value. The framework will make a good attempt to
preserve the exact object handle present at that path in the final options structure. This is the
appropriate policy when the option value does not consist of pure JSON material but instead contains
some form of exotic material such as a Fluid component or native object (e.g. Date,
Float32Array, Socket, etc.). The framework detects some kinds of native object (e.g. DOM nodes, jQuery
objects) and protects them from merging without the use of this option.
|
Any other String value |
The value will be interpreted as an EL path into a source object. If no user-supplied value is present
at this options path (other than those supplied in defaults), the value will be taken from the final merged value
held at this specified EL path. That is, this style of policy is used to specify that an
options value has a default value which defaults to the value of another supplied option.
|
Function |
This option allows the user to take complete control of the merging process at this path with a custom
policy function. The value holds as a function which accepts two arguments (target, source)
representing the sub-objects which are about to enter merging. The function will be invoked on these
arguments and no further operations will be performed on this subtree. The return value of the function
will become the next **running value** of the target and may be supplied as argument 1 to another
invocation of the same policy function. These semantics are the same as those of the standard functional
algorithm known as reduce (or
fold, accumulate, etc.)
|
fluid.merge signature
fluid.merge
directly is deprecated. The framework user should never
need to invoke fluid.merge
directly - it is invoked automatically by the framework as part of standard
component initialisation.
The signature to fluid.merge
is
/* you can have as many sources as you like, one per argument from the third argument on. */
fluid.merge(policy, target, source1, /* ... */ sourceN);
where policy
is the merge policy object (may be empty), target
is the object to (destructively) be the target of
the merge operation, and source-1
through source-n
are a list of a number of "source" options structure from which
the merge is to be performed.