-
Notifications
You must be signed in to change notification settings - Fork 2
Layout Filtering
While Synchro applications strive to run well with a single view on all platforms, there are cases where it is appropriate, even necessary, to customize the view based on device metrics (including the mobile OS, the device type, and the device class, the screen size, the orientation, etc). Layout filtering is the mechanism that provides this support.
Layout filtering pre-processes the view for a given application page or screen, filtering the elements that apply based on the current device metrics, and then passes the resulting view to the mobile client.
Any view element may contain a filter specifying criteria for inclusion of that element in the final rendered view. If the filter criteria is met, the element is included, and if not, it is excluded. In either case, the filter specification itself is removed from the element when the final view is rendered.
A filter consists of a value specification and a qualifier. The value specification may use one of the following value domains as its attribute:
deviceMetric
viewMetric
viewModel
The qualifier may use one of the following relationship specification values as its attribute:
-
is
- equals value, or if value is array, is present in array -
isnot
- not equals value, or if value is array, is not present in array -
lt
- less than -
lte
- less than or equal to -
gt
- greater than -
gte
- greater than or equal to
One of each of these two attribute types are combined to form an object that is the contents of a filter
attribute on the element to be filtered. For example:
{ control: "text", filter: { deviceMetric: "deviceType", is: "Tablet" }, value: "Tablets Rule!" },
{ control: "text", filter: { viewMetric: "widthInches", gt: 6.0 }, value: "Wide Screen" },
More than one value may be provided when using the is
(or isnot
) relationship attribute, in which case the filter checks to see if the value matches (or does not match) any value in the attribute array, for example:
{ control: "text", filter: { deviceMetric: "os", is: ["Windows", "WinPhone"] }, value: "Microsoft Rules!" },
More than one filter can be specified on an element by using an array of filter objects, such as:
{ control: "text", filter: [{ deviceMetric: "deviceType", is: "Tablet" }, { viewMetric: "widthInches", gt: 6.0 }], value: "Wide screen tablet" },
In this case, the filters are treated as an and (all filters must pass in order for the element to be included in the rendered view).
=========
Any view element may contain filter criteria (one or more filter criteria attributes). The filter criteria attributes are as follows:
-
filterOS
- values: Windows, WinPhone, Android, iOS -
filterDeviceType
- values: Phone, Tablet -
filterDeviceClass
- values: Phone, Phablet, MiniTablet, Tablet
If the filter criteria attribute contains a single value, then that value will be compared to the appropriate device metrics value. If the filter criteria attribute contains a list of values, then each value in the list will be compared to the appropriate device metrics value to see if any of them match.
If any filter criteria attribute is not a match, then the element is excluded from the view layout.
For example:
{ control: "text", filterDeviceType: "Tablet", value: "Tablets Rule!" },
{ control: "text", filterOS: ["Windows", "WinPhone"], value: "Microsoft OS" },
It is possible to have a set of elements with mutually exclusive filters to guarantee that a single element is present in the final layout, such as:
{ control: "text", filterDeviceType: "Phone", value: "Primary orientation is Portrait (phone)" },
{ control: "text", filterDeviceType: "Tablet", value: "Primary orientation is Landscape (tablet)" },
In addition, there are "selector" container elements that can assist in scenarios where more complex filtering logic is required.
-
select: "First"
- This will select the first child element to replace this element (after removing any non-qualifying child elements based on filter criteria). -
select: "All"
- This will select all child elements to replace this element (typically used to group like elements)
Note: select:First and element disqualification via filter criteria are performed first, for the entire layout, followed by select:All. This allows select:All elements to be contained in a select:First element (a common scenario).
Examples:
{ select: "First", contents: [
{ control: "text", filterOS: "iOS", value: "iOS rules!" },
{ control: "text", filterOS: "Android", value: "Android rules!" },
{ control: "text", value: "Some kind of Windows platform rules!" },
]},
{ select: "First", contents: [
{ control: "text", filterOS: ["Windows", "WinPhone"], value: "Microsoft OS", },
{ control: "text", value: "Non-Microsoft OS" },
]},
Here is a real-word example to include specific auxiliary control elements based on the OS (platform), using select:All child elements for grouping:
{ select: "First", contents: [
{ select: "All", filterOS: "Windows", contents: [
{ control: "commandBar.button", text: "Add", icon: "Add", commandBar: "Bottom", commandType: "Secondary", binding: "increment" },
{ control: "commandBar.button", text: "Subtract", icon: "Remove", commandBar: "Bottom", commandType: "Secondary", binding: "decrement"},
{ control: "commandBar.button", text: "Reset", icon: "Stop", commandBar: "Bottom", binding: "reset" },
]},
{ select: "All", filterOS: "WinPhone", contents: [
{ control: "appBar.button", text: "Add", icon: "add", binding: "increment" },
{ control: "appBar.button", text: "Subtract", icon: "minus", binding: "decrement"},
{ control: "appBar.button", text: "Reset", icon: "refresh", binding: "reset" },
]},
{ select: "All", filterOS: "Android", contents: [
{ control: "actionBar.item", text: "Add", binding: "increment" },
{ control: "actionBar.item", text: "Subtract", binding: "decrement", enabled: "{count}" },
{ control: "actionBar.item", text: "Reset", icon: "ic_action_refresh", showAsAction: "IfRoom", binding: "reset" },
]},
{ select: "All", filterOS: "iOS", contents: [
{ control: "navBar.button", systemItem: "Trash", binding: "reset", enabled: "{count}" },
{ control: "toolBar.button", text: "Add", icon: "plus-symbol-mini", binding: "increment" },
{ control: "toolBar.button", text: "Subtract", icon: "minus-symbol-mini", binding: "decrement" },
]},
]},