Interface DataPath
NOTE: the dataPath feature is intended to help certain legacy architectures, such as systems that work in terms of exchanging large messages with several different entity types in one message, and are incapable of providing separate access to each entity type. Don't use dataPath if this is not your situation.
If you are not forced by legacy issues to use hierarchical data structures,
we recommend:
For example, when representing a sales order with a "deliveryAddress" (consisting of
multiple fields), you'd typically want an "orders" dataSource to define the fields
for the order as a whole, and an "address" dataSource to define the structure of the
deliveryAddress object.
It may seem like a good idea to work with a single hierarchical order object, where
the "deliveryAddress" attribute is set to a sub-object that matches the structure
defined in the "address" dataSource. DataPaths could be used to extract individual
address fields for editing in a form alongside other fields from the order, and
edits would be saved via a simple "add" or "update" operation, passing in the
modified nested data object.
In fact, this has a number of disadvantages. Since there is no call to the
"update" operation on the "address" subobject, the address will be modified without
the normal features of a dataSource update. You can't specify
Loading and saving nested data objects as a single hierarchical block also offers
no advantages in terms of performance or simplicity.
Loading arrays of related objects (such as all LineItems in an Order) as a
hierarchical object has the further drawback that paging cannot be used for the
list of related objects, and all such objects will not participate in
In short, we do not recommend structuring your data as a hierarchy of nested data objects
and using dataPath to navigate these structures unless you are forced to by a legacy system
that doesn't allow separate operations on each entity type.
DataSourceField.valueXPath
.security rules
,
DMI
logic, request modifiers
,
and no logging or auditing
will run.
The same "bypassing" problem occurs, in perhaps worse form, if a subobject does not yet
exist and the framework creates it automatically, skipping a DataSource "add"
operation that may have established defaults, not been allowed for the user, etc.
The queuing
system makes it extremely easy to load and save
multiple types of
entities in a single HTTP request, and takes far less code to implement properly as
multiple DataSource operations, with equivalent or better performance.
automatic cache synchronization
.
How to use dataPaths
Each dataPath string is a slash-delimited set of field identifiers, for example
"id1/id2/id3"
. DataPaths may be applied directly to a
component
, and/or to a databound component field specification.
A datapath denotes a path to a nested field value in a hierarchical structure, giving
developers the opportunity to easily view or edit nested data structures.
Specifically:
- if the component is viewing or editing a record, the value for fields will be derived from a nested structure of records
- if the component is bound to a dataSource, field attributes may be picked up by following the dataPath to a field definition on another dataSource
If a dynamicForm is defined with the following fields:
[ { name:"name" }, { name:"street", dataPath:"address/street" } ]If the
"name"
field is set to "Joe Smith" and the "street"
field
is set to "1221 High Street", when the values for this form are retrieved via a
getValues()
call they will return an object in the following format:
{name:"Joe Smith", address:{street:"1221 High Street"}}
For databound components, dataPath also provides a way to pick up field attributes from nested dataSources. Given the following dataSource definitions:
DataSource addressDS = new DataSource(); DataSourceField street = new DataSourceField(); street.setName("street"); DataSourceField city = new DataSourceField(); city.setName("city"); DataSourceField state = new DataSourceField(); state.setName("state"); DataSourceField zip = new DataSourceField(); zip.setName("zip"); addressDS.setFields(street, city, state, zip); DataSource contactsDS = new DataSource(); DataSourceField name = new DataSourceField(); name.setName("name"); DataSourceField email = new DataSourceField(); email.setName("email"); DataSourceField organization = new DataSourceField(); organization.setName("organization"); DataSourceField phone = new DataSourceField(); phone.setName("phone"); DataSourceField address = new DataSourceField(); address.setName("address"); address.setType(addressDS); contactsDS.setFields(name, email, organization, phone, address);and a databound component bound to the 'contacts' dataSource, specifying a field with a dataPath of
"address/street"
would ensure the field attributes were derived from the
"street" field of the 'Address' dataSource.
dataPaths are also cumulative. In other words if a component has a specified dataPath, the dataPath of any fields it contains will be appended to that component level path when accessing data. For example the following form:
DynamicForm form = new DynamicForm(); form.setDataPath("contact"); TextItem field1 = new TextItem(); field1.setDataPath("address/email"); form.setFields(field1);Might be used to edit a data structure similar to this:
{contact:{name:'Ed Jones', address:{state:"CA", email:"ed@ed.jones.com"}}}Nested canvases can also have dataPaths specified, which will similarly be combined. See the
Canvas.dataPath
attribute for more information and examples
of this.