Dec
12
Written by:
Michael Washington
12/12/2012 7:02 AM
LightSwitch JavaScript Data Binding
In the LightSwitch HTML Client Preview 2, the binding pattern has several advantages in that it allows you to create large robust and well structured applications. You may have heard about the binding pattern in Silverlight and WPF (known as MVVM). The key component is the INotifyPropertyChanged interface that raises an event when anything changes a property that implements the interface.
The ability to simply bind to a property (this can be a single scalar value or an entity composed of several properties) allows you to simply subscribe to changes in say the First Name property, and in one place, validate, update, or persist the value in one or more centralized methods. Without binding, you would need to implement if… then code in a multitude of places potentially creating spaghetti code (the larger you application gets).
Binding in JavaScript
You can find a good overview of frameworks that allow binding in JavaScript at this link. What the link does not cover is all the work that you must do to implement the frameworks. Knockout is a popular JavaScript binding framework, and its Hello World requires 10 lines of code, consisting of a integrated View and a View Model that you must carefully craft (without making any typos). I created an implementation for the article A Full CRUD DataJs and KnockoutJs LightSwitch Example Using Only An .Html Page. What I learned from that experience was a deeper appreciation for the C# code behind experience . When you don’t have a compiler, every line of code you write comes at a price that grows exponentially the larger your application gets. The key is to write as little JavaScript as possible (and to also use tools such as TypeScript (see: Creating JavaScript Using TypeScript in Visual Studio LightSwitch)).
Also, see Stephen Provine’s comments at this link as to reasons why LightSwitch does not use Knockout (but you still can implement Knockout yourself manually).
Binding In The LightSwitch HTML Client
To see a detailed example of JavaScript binding in the Visual Studio LightSwitch HTML Client, see: Implementing The Wijmo Radial Gauge In The LightSwitch HTML Client. The binding part comes down to only three lines:
contentItem.dataBind("value", function (newValue) {
UpdateRadialContrl(radialContrl, newValue);
});
The remaining binding code is automatically done for you by the Visual Studio code designer and the Visual Studio LightSwitch runtime. LightSwitch is a productive liberating tool. LightSwitch is the easy to use tool to create great modern software.
To illustrate how data binding works in LightSwitch, we will start with the example program created in: Using Toastr with Visual Studio LightSwitch HTML Client (Preview).
Two Methods To Bind Them All
Two methods to bind to data will be explored, dataBind and addChangeListener. dataBind is a function that actually implements addChangeListener. dataBind provides the advantage in that it parses the input binding path that you specify, and creates change notifications (using addChangeListener). Each change notification will raise the callback function that you specify in the dataBind constructor. addChangeListener on the other hand, will just bind to the element that you specify. addChangeListener has the advantage, that unlike dataBind, does not require a contentItem (so it can be used in entity code that does not have a contentItem).
dataBind
A nice feature about LightSwitch is that it allows you to easily see what you are binding to. To bind to data, you click on the element you want to bind to in the screen designer.
In the Properties for the element, you can click Edit postRender Code.
This will take you to a JavaScript method that is wired-up and ready for your custom code.
We will start off by just displaying the initial values, using the Toastr JavaScript plug-in, by adding the following code to the method:
// Display Initial Values
var FirstName = contentItem.value.FirstName;
var LastName = contentItem.value.LastName;
var InitialValues = 'Initial Values:'
+ ' FirstName = '
+ FirstName
+ ' LastName = '
+ LastName;
toastr.info(InitialValues);
When we run the application the initial values are displayed.
However, when we change the values, to see the new values, we have to save the record and re-open it.
To resolve this, and provide the INotifyPropertyChanged like binding notifications, we use the following code:
// Binding to only the FirstName property
contentItem.dataBind("value.FirstName", function (newValue) {
var newFirstName = newValue;
var updatedFirstNameOnly = 'Updated FirstNameOnly: '
+ newFirstName;
toastr.info(updatedFirstNameOnly);
});
The diagram above shows how the data flows.
You will also notice that code was added around the binding, because in this example the binding is in a Dialog popup box. The View Model (that is automatically created for you by LightSwitch) is re-used each time the Dialog box is opened. Without some sort of flag like hookedEvents we would have multiple bindings attached each time the Dialog is opened.
Note, the flag code would not be needed if you had a separate page for editing that was completely closed and re-opened each time (see: Implementing The Wijmo Radial Gauge In The LightSwitch HTML Client for an example).
Also, note that the initial scope is the entire People entity (that consists of FirstName and LastName), but in this case we are only binding to the FirstName property (because we set dataBind binding to “value.FirstName”).
When we run the application, the Toastr notification will show the latest value each time we change it (and tab out of the box).
The following code shows how to bind to the property that indicates if a property is “dirty” (has been changed):
// Binding to LastName isChanged property
contentItem.dataBind("value.details.properties.LastName.isChanged", function (newValue) {
var isChangedLastName = 'LastName.isChanged: '
+ newValue;
toastr.info(isChangedLastName);
});
When we run the application, we can see the value change.
When and Where to use it
Use it within a render or postRender function, this allows you to easily get notified when some property (that is reachable from the contentItem) has changed, regardless of how deeply nested the data is.
Limitations
dataBind requires a contentItem and you don’t have that in a Screen or Entity method (however, in a Screen method, you can use code like: contentItem = screen.findContentItem("OrderDate") to get a specific content item).
addChangeListener
We can open a table (entity).
When we select the Client tab, the Write Code menu will allow access to the created method.
Unlike the render methods, we only have access to entity, therefore we must use addChangeListener.
Add the following code:
entity.addChangeListener("LastName", function (e) {
toastr.info("(from entity level) LastName value changed to: " + entity.LastName);
});
When we run the application, we have to create a new entity to invoke the addChangeListner.
The notification will fire without the need to save the record first.
When and Where to use it
Use it from within Entity and Screen functions. This code would work anywhere you show the data (avoiding the need to duplicate the logic on each screen the data objects appears on).
Limitations
It does not have the ability to specify a binding path to listen to nested data.
LightSwitch Help Website Articles
Implementing The Wijmo Radial Gauge In The LightSwitch HTML Client
Writing JavaScript In LightSwitch HTML Client Preview
Creating JavaScript Using TypeScript in Visual Studio LightSwitch
Theming Your LightSwitch Website Using JQuery ThemeRoller
Using Toastr with Visual Studio LightSwitch HTML Client (Preview)
LightSwitch Team HTML and JavaScript Articles
Custom Controls and Data Binding in the LightSwitch HTML Client (Joe Binder)
Creating Screens with the LightSwitch HTML Client (Joe Binder)
The LightSwitch HTML Client: An Architectural Overview (Stephen Provine)
Writing JavaScript Code in LightSwitch (Joe Binder)
New LightSwitch HTML Client APIs (Stephen Provine)
A New API for LightSwitch Server Interaction: The ServerApplicationContext
Building a LightSwitch HTML Client: eBay Daily Deals (Andy Kung)
Special Thanks
A special thanks to LightSwitch team member Stephen Provine for his valuable assistance.
Download Code
The LightSwitch project is available at http://lightswitchhelpwebsite.com/Downloads.aspx
(you must have HTML Client Preview 2 or higher installed to run the code)
2 comment(s) so far...
Nice article, but how does one know that "value.details.properties.LastName.isChanged" even exists? I.e. how does one explore or know about this hierarchy? Thanks.
By dan houck on
2/22/2014 5:43 AM
|
If you search the Microsoft site there is documentation.
By Michael Washington on
2/22/2014 5:44 AM
|