Best way to link UI elements with backing javascript objects - javascript

This is a rephrase of a post I made last week. I was surprised I didn't get more of a response, thinking maybe I didn't describe/title it very well.
Simplest possible way to describe it:
Is there something like spring:bind for javascript/dhtml?
The high level view of what I want:
In my app, I have a list of "subscriber" objects which I've loaded via ajax. I'd like to dynamically draw UI elements representing these objects, and register event handlers so that the backing objects are updated when the user edits the view.
The more low level thoughts
Dynamically displaying js data in the browser is trivial. It's also not a big problem to write event handlers for every type of data, but it's a bit tedious. I feel like there should be some library out there which will behave as a template system, creating HTML form elements dynamically, populating placeholders with data from my js objects, but go to the additional step of updating the backing objects when the user makes edits to the form elements. The closest example I'm aware of is a back-end technology, the Spring (java framework) binding functionality, where form elements in templates are coded according to a system where they're automatically linked to the model objects on the server.
So, does what I've described exist in the front-end world?

I do not know about libraries of the kind you described, but jQuery offers the very useful data() function which allows you to associate an arbitrary piece of data with a DOM element, using a key. Adding a new element and associating data with it might look like this:
var elem = $('<div class="subscriber">...</div>').appendTo(someContainer);
elem.data('yourKey', backingObject);
Using event delegation (e.g., the live() function), you can add one event handler that is valid for all graphical representations of your subscriber objects, no matter if they already exist or not.
$('.subscriber').live('click', function(e) {
var backingObject = $(this).data('yourKey');
// Now call some methods on the backing object
});
Hope this helps you somehow.

This is not an answer, but a larger comment. It might help to write the API you want to use, such as:
var jsObj = {};
jsObj.bind(document.getElementById("firstName"), "onchange");
//binds the data from the firstName element to the jsObject in property "firstName" during the onchange event.
Is this what you are trying to do?
A quick google search turns up:
http://api.jquery.com/bind/
It might be interesting to make a delegate to jQuery's bind, which doesn't see to hard to do.

Knockout looks like it does the job you are looking for.

Related

How to create knockout data bindings at runtime w/o data attributes

Is it possible to create knockout bindings from javascript alone, i.e. without writing custom html attributes?
I'm very much stuck with our existing markup and can't add data-bind etc. that knockout.js relies on (html is generated programmatically and there is no access to the rendering pipeline, please assume I've exhausted my options in trying :)
One idea that I'm tentatively pursuing is adding data-bind attributes at runtime prior to calling ko.applyBindings. Is there a preferred approach? I'll also accept an alternative, sufficiently documented/popular/stable framework if it also implements bindings similar to knockout.js if/visible.
Knockout 3.0 (which just around the corner and is in release candidate now) opens up a lot more ways to interact with the binding process, such as the ability to preprocess nodes and dynamically generate bindings. Take a look at Knockout.Punches to see some examples of what is possible. Between that and the things already mentioned like the unobtrusive and class binding providers, you should have no trouble working with whatever markup you're stuck with.
It may also be worth pointing out knockout has an applyBindingsToNode function which takes in a JSON object of the bindings if you want full control, though that does not apply bindings to descendant elements.
Knockout allow us to create custom binding provider, I find out there is several libs that help you to do it
You can find them here:
One that don't use DOM at all:
https://github.com/tobio/knockout.unobtrusivebindingprovider
One that use another approach :
https://github.com/rniemeyer/knockout-classBindingProvider
At last resort if none of them suit your needs, you can with jQuery modify the DOM then call the binding on it...
Look at the "Unobtrusive event handling" section in the Knockout documentation under "Further techniques".

Javascript UI library with easy bind to JSON

I'm looking for a free Javascript UI library which might allow for the following behaviour:
create forms from JSON objects and bind changes to fields.
Creating forms from JSON isn't necessary, but library which supports binding well would be very useful here. By binding I mean:
when object is created initial values there are interpolated to controls
when control values change the properties change as well
(optional) when values in the object change, values in controls change as well.
I only know jquery, but I don't think this library is particularly well-suited for it.
Perhaps this one can help you:
knockoutjs

Is it possible to serialize/deserialize dojo widget objects?

Does anybody know if it is possible to serialize/deserialize dojo widget (dijit) objects to a string or some representation that can be persisted across browser sessions?
My scenario:
I have a webpage with various dijits that I would like to be able to take a "snapshot" of and restore in a new browser session so that everything is brought back up in the exact same state.
In order to do this I believe I need to serialize/restore the DOM tree of the page as well as the dijit objects. I've been able to serialize the DOM tree and am currently restoring it by replacing the contents of the HTML node of the page. When the page's DOM is restored, none of the dijits work - they are rendered correctly but you can't click any of them. I believe this is because the dojo parser has already run through the DOM when the page first loaded, and replacing the entire HTML DOM element destroys all the dijits in the dijit registry for that page.. which means the dijit classes have to be re-instantiated.
Ideally what I would like to be able to do is when I take a "snapshot", to serialize every dijit object that is contained in the dijit.registry for the page to a file, and when the session is restored, to re-construct those dijit objects and add them back to the dijit registry.
Something like:
dijit.registry.forEach(function(widget){
// Save the widget object so that it can be restored in a new browser instance?
});
Has anybody tried this or know if it's possible without writing a custom serializer?
I am not sure that I agree with the technique you are using. A better scenario would be to simply serialize the state of the data for each dijit. I know that this would be more work but you are trying to preserve the state of the data, bringing the UI along for the ride seems to be preserving unnecessary information.
That being said, the dojo parser can be called independently of page load. What you are looking for is
dojo.parser.parse();
Running that after you repopulate the innerHTML should re-parse and recreate the dijits
See this page for the full reference: http://docs.dojocampus.org/dojo/parser
Any javascript object (including dojo widgets) can be serialised into JSON using dojo.toJson(), e.g:
var deserialisedValue = dojo.toJson(myObject);
My guess is that, we can serialize and deserialize dojo widgets, but the stores (and also the type of store) on which these widgets were built, should also be serialized and deserialized.
This may involve usage of eval statements, which is considered evil. Also i think the event handlers, topics to which these widgets subscribed may not be serialized and deserialized.
If the recipient page (where the dijits will be deserialized) has the same number of widgets, the simplest solution would be to wrap everything up inside a dijit/form/Form and call valueJSON = form.get('value') to serialise and form.set('value', valueJSON) to deserialise.
For widgets inside of forms like dgrid and charts, it gets trickier. You would have to take a widget specific approach. Eg: you can easily serialise a dgrid whose values have changed, by calling a grid.save() and then a JSON.stringify (grid.get('store')).
Incase the deserialisation page can have arbitrary number of widgets, I agree with #treaint You could go about getting the type of widget via widget.get('declaredClass') \\Returns TextBox etc.
We had a similar problem, but we solved it quite easily with the form's get/set value! Its quite ingenious, it iterates over all its children, calling child.get('value') on every one of them and mixining it with it's own value.

Most useful techniques for two way data binding with js

With abundance of web services and client side templating features of jQuery and likes, creating mashups or sites consuming a multitude of web services and posting data back to these services is becoming exceedingly popular. For a page of decent size with this kind of architecture, say a dashboard. What are the useful techniques of maintaining this client side state. In other words whats are some of the ways to do two way databinding?
Sample scenario:
Get Data From Service as JSON/XML
Display/Bind on UI
Capture User Input
Recreate request from the UI controls/html
Post Data To Service
Get Response and Rebind
In jQuery you can easily do AJAX request of page load that calls the service, returns an object, and bind that object to the form using jQuery Templates plugin. When the form needs to be submitted, you can use jQuery Form plugin to send to the service via AJAX and return the JSON object, bind it to the jQuery Templates plugin container (the form).
jQuery AJAX API
http://api.jquery.com/jQuery.ajax/
jQuery Templates Plugin
http://plugins.jquery.com/project/jquerytemplate
http://api.jquery.com/category/plugins/templates/
jQuery Form Plugin
http://jquery.malsup.com/form/
also, You may combine the use of jQuery "Form" plugin to send the form, and the KnockOut JavaScript library, which is all about the kind of binding you want to do.
See knockout JS library details on http://knockoutjs.com/
The first two features as listed there are:
Declerative Bindings
Automatic UI Refresh
See this live example for very small introduction http://knockoutjs.com/examples/helloWorld.html
Update:
Since this answer got a recent upvote, it's also important to mention the relatively-new kid in the town, angularJS, it's a bit of a bigger framework that can do so many things, but doing two-way data-binding is the easiest thing ever.
Official URL: http://angularjs.org
Example: http://docs.angularjs.org/guide/forms
http://gurustop.net
Angular is the most impressive player I've seen for two-way databinding. You can use plain old JavaScript objects, attach them to an Angular scope object, and then bind the scope to a section of the DOM. Here's an example for Angular 0.9. (Angular 1.0 uses a very different API to achieve the same thing.)
// angular.compile() returns a databinding function
var databind = angular.compile(document.documentElement);
var model = angular.scope();
// add data to the scope object
model.greeting = "Hello, World!";
model.colors = ["red", "green", "blue"];
// hook 'em up
databind(model);
You can use angular expressions in the HTML for databinding, including form controls.
<!DOCTYPE html>
<input name="greeting" />
<span ng:repeat="color in colors" style="color: {{color}}">
{{color}}
</span>
In this case, the greeting property of the scope objects gets updated with every keystroke in the textbox.
Or if you don't want to use databinding expressions in your HTML, you can do everything manually.
model.$watch("greeting", function (value) {
// when the greeting changes, update the DOM
$("input[name=greeting]").val(value);
});
Then every time you update the scope object and call $eval(), if anything has changed, listeners will be notified.
model.greeting = "Hi.";
model.$eval();
And the best part is that you can make changes to anything attached to the scope, call its $eval() method, and the HTML automatically updates.
model.colors.append("yellow");
model.colors.sort();
model.$eval(); // notifies listeners, including bound HTML
Knockout JS is inferior because instead of working with plain JavaScript objects, arrays, strings, and numbers, you must create instances of its Observable and ObservableArray classes to do databinding.
Enjoy!
I would take a look at Lava JS (http://lava.codeplex.com). It has very nice databinding and it is very unobtrusive to use. It also supports fetching/posting data to the server.

Connecting a form to a Javascript Object (and other best practice advice)

I've been using javascript to do lightweight functionality on sites for years - DOM manipulation etc - but just now im beginning to investigate using it to do a lot more of the heavy lifting (in combo with PHP). I've only just started getting into OO JS, and im still trying to get my head around the best-practices and design patterns that work well with it.
To be more specific - my question is, can anyone here suggest techniques for connecting a form to a javascript object?
In my current implementation I have an JS object that can be edited by a (fairly large) form. When I instantiate the object I attach an onchange observer to the form, whose callback syncs the form fields with the object parameters. I'm handling the form submitting through AJAX - there is also a periodic request that saves a temporary version of the form info to a mySQL DB. One thing I wonder is whether it is possible to easily handle syncing in the other direction - onchange of the object the form fields update (on form reset for instance).
I am interested to know if this approach is a correct/sensible one, and more generally I would be very interested to hear advice with regard to OOJS form handling.
Cheers in advance :)
(Im using Prototype btw)
You can use $("form").serialize(true);
http://www.prototypejs.org/api/form/serialize
You dont need the onchange event, you can just call the serialize() method every time you need to get the form data.
Why not create a method in you object that resyncs the object with the form? And call that on every change of the object? You could create a special change function to assure that it gets called on every change.
It's a perfectly reasonable approach. JS doesn't entirely encourage this sort of thing due to its curious object system and in particular the way bound methods are not first-class objects, but with a bit of suitable metaclass and callback glue it's eminently possible.
You might also want to look at a widget library if you'd like to get more of this kind of low-level form handling stuff for free. Haven't tried the ones built on top of Prototype; other possibilities include YUI's one.
Updating the model from the server can be pretty simple. Generally you'd poll an AJAX request and have the server pass back either diffs, if it knows them, or else just timestamp each object update, send the new object details to the client side on each update, and have the client decide how to merge that with any changes the user has made in the meantime.

Categories

Resources