Data Binding in Extension¶
All controls in Mobile Development Kit support data binding. It is recommended that your extension also allows apps to pass values to your extension via ExtensionProperties
as binding.
For example:
{
"Extension": {
"Module": "MyExtensionFolder",
"Control": "MyExtensionFileName",
"Class": "MyExtensionClass",
"ExtensionProperties": {
"Title": "{FirstName} {LastName}"
}
}
}
Data Binding¶
When the app that use or consume your extension specified binding via one of the key inside the ExtensionProperties
that your extension supports, Mobile Development Kit does not automatically resolve the bindings, the extension itself is responsible to handle the bindings and resolve them at the appropriate time with the appropriate binding context.
You can make use of valueResolver()
function which return a valueResolver
instance, it has a resolveValue(value, context)
function that can be used by your extension to resolve binding value that's passed to the extension from the app. The ValueResolver
class spec can be found here.
Note
In regards to ValueResolver.resolveValue
parameters:
-
value
parameter: It can be a single object or an array of values. If an array is passed to the function, the result in the promise resolve function will be an array of resolved value with the same order. -
context
parameter: You can pass the base classcontext
member variable to as the context for resolving the values.IView
/IControl
/BaseControl
base class has acontext
member variable that you can access e.g.this.context
. Or you can create a newContext
object with new binding data as the binding context for the value resolver.Context
class can be imported from"mdk-core/context/Context"
Example of resolving binding using valueResolver().resolveValue()
:
var value = this.definition().data.ExtensionProperties.Value;
this.valueResolver().resolveValue(value, this.context).then((resolvedValue)=> {
this._label.text = resolvedValue;
});
Target Binding¶
All extensions types support a Target
property that allows app that use your extension to bind data to your extension.
{
"Extension": {
"Module": "MyExtensionFolder",
"Control": "MyExtensionFileName",
"Class": "MyExtensionClass",
"ExtensionProperties": {
"Title": "{ProductName}"
},
"Target": {
"EntitySet": "Products",
"Service": "/MyApp/Services/MyODataService.service"
}
}
}
In your extension class, the data retrieved by the Target
binding can be accessed in the context.binding
property.
The binding
property will be an ObservableArray
if there's data bound to it. If no Target
binding is specified by the app, binding
will be undefined
.
The following example show you how to consume the Target
data binding in your extension and also making use of the value resolver to resolve binding for each individual data entry.
// Import the Context class so that you can create a new context for each item in the data list
// Import the isAndroid, iOS to check your current platform
import { Context } from 'mdk-core/context/Context';
import { isAndroid, isIOS } from "tns-core-modules/platform";
// You should call this function in your extension's initialize function and save the returned layout
private createView() {
var bindingArray = this.context.binding;
var layout = null;
if (isIOS) {
layout = UIStackView.new();
//Configuring the paddings around the stack view
layout.autoresizingMask = UIViewAutoresizing.FlexibleWidth;
layout.layoutMarginsRelativeArrangement = true;
let inset = new NSDirectionalEdgeInsets();
inset.top = 8; inset.leading = 16; inset.bottom = 8; inset.trailing = 16;
layout.directionalLayoutMargins = inset;
// Set the layout stacking to be vertical
layout.axis = UILayoutConstraintAxis.Vertical;
}
else if (isAndroid) {
layout = new android.widget.LinearLayout(this.androidContext());
layout.setOrientation(android.widget.LinearLayout.VERTICAL);
layout.setLayoutParams(new android.view.ViewGroup.LayoutParams(-1,-1));
}
if (bindingArray && bindingArray.length > 0) {
var title = this.definition().data.ExtensionProperties.Title; // Get the properties passed from the app that consume your extension
var len = bindingArray.length;
for (var i = 0; i < len; i++){
var context = new Context(bindingArray.getItem(i)); // Create a new context with data from item(i)
this.valueResolver().resolveValue(title, context).then((resolvedTitle) => {
var label = null; //Each entry is represented by a label in this example
if (isIOS) {
label = UILabel.new();
label.text = resolvedTitle;
layout.addArrangedSubview(label);
} else if (isAndroid) {
label = new android.widget.TextView(this.androidContext());
label.setText(resolvedTitle);
layout.addView(label);
}
}); // Resolve the binding
}
}
return layout;
}