Is it possible to serialize/deserialize dojo widget objects? - javascript

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.

Related

How can you get Angular to regenerate parts of page after data is changed?

Simply put:
My Angular app parses through a JSON object of objects of objects using ng-repeat and some ng-shows, etc. It makes a nice layout on the page with all the data. In my page, the JSON objects (at any level) can be updated by the user.
The problem is, that after the data is updated, the layout doesn't regenerate itself. Instead, it just places in the new data in an ugly unformatted way.
How do you get the view to update as if you just loaded the page fresh with all this data there?
This sounds like a $scope.apply issue.
You can manually apply changes to your scope via $scope.apply() which will re-render the changes to the page (not in a page-blink manner, but a typical Angular manner).
Often, this needs to be done when a change occurs via non-Angular JavaScript manipulating the data or the DOM itself, so check for areas in your script where that may be occurring as your culprit.

How can you get an ADO DataTable in code behind (available on pageload) back to the javascript?

On page load, I have my DataTable results available which I need to pass back to the javascript for processing.
What are my options?
Use a hidden field to pass the data back up. not sure how exactly, by maybe convert it to xml/json and then access it from javascript that way. Seems like a pain. No extra round trips for this approach.
Use webmethod/webservice to issue a call directly from the javascipt and then get back the DataTable, however this requires an extra round trip since I already have the DataTable available on pageload.
It is also possible to access objects in code behind using ASP.NET inline expressions (i.e. <% syntax) usable from the .aspx page. No extra round trips for this approach.
Convert DataTable to json/xml and then use ASP's ClientScript.RegisterStartupScript to make it available in there as a string returned from a function or something. Sounds hacky though.
Bind the DataTable/DataSet (or any object that implements the IEnumerable interface) to an ASP data control such as a DataGrid, DataList, Repeater, etc... and then just hide the control via some CSS: #datacontrol {display: none;}
How can I do this?
If it is just array, refer this.
If it is custom object, IMO it is better to call server method via. ajax requests and load them into javascript objects and work on data.
There are a number of ways you could do it as you have already reasoned through. Any time I have had a need to do this I have written my data out to a javascript variable using the clientscript.registerclientscriptblock method and then used javascript in the page to access the variable and do the rest of the parsing.
See this for example
You would just use the string builder or whatever you chose to dim a javascript array containing your table values and pass that to the page.
I had this same requirement in one of my asp.net application. What I did was, I created a string variable from the DataTable on Page_Load() by using custom separators like :: ; etc for row-separator and column separator. And then set the string to a hidden field or textbox text with CSS {display: none;}
After that, you can get the value of the hidden-field or TextBox in javascript $(document).ready() block or javascript pageLoad function() if you want it to be executed on every full/partial postback.
Get the value and decode it as you had coded the DataTable into the string in code-behind, and process it as u need.
Hope it helps :)
After trying several of the above options, I've found #3 (ASP.NET inline expressions) to be the best choice for accessing an ADO query result such as a DataTable or DataSet since it was the quickest to implement and had no additonal round trips due to the fact the inline expressions are resolved during the page construction.
I tried #5 (bind data to data control, then hide it), but it was noticeably slower and I had problems finding a control that would expose all the features of a DataTable/DataSet. There are a handful of data controls that you can bind records to, but what I found was that much of the "nice-ities" that come with a DataSet/DataTable are lost when converting to a repeater control or such. If you use one of the more full featured ASP controls available to get more of those features back, you lose on performance since those controls are meant for read/write and to render the content for display. And it wasn't as simple as I expected to access the data as it is in the code behind.
I thought about #4 (passing data thru ASP's ClientScript.RegisterStartupScript), but didn't feel like serializing/deserializing every object I need to expose and working though any hiccups that come with it. It just didn't seem like the right way. I suppose it would be fine for simpler objects though.
And #1 (serialize data to a hidden field) is pretty much the same concept as the above #4 (passing data thru ASP's ClientScript.RegisterStartupScript so I didn't bother with that one either.
The other (2nd best) possibility is to do #2 (using webmethod/webservice) as #Sundeep and #ron_tornambe have pointed out. However, this option adds an extra round trip to the page request and since the above scenario has the DataTable/DataSet ready for consumption on page load it is not optimal for me. If it wasn't for that I'd say it was equal to my first choice of #3 (ASP.NET inline expressions) since you'll get the full featured object to work with.

Is it okay to use data-attributes to store Javascript 'state'

I often use data-attributes to store configuration that I can't semantically markup so that the JS will behave in a certain way for those elements. Now this is fine for pages where the server renders them (dutifully filling out the data-attributes).
However, I've seen examples where the javascript writes data-attributes to save bits of data it may need later. For example, posting some data to the server. If it fails to send then storing the data in a data-attribute and providing a retry button. When the retry button is clicked it finds the appropriate data-attribute and tries again.
To me this feels dirty and expensive as I have to delve into the DOM to then dig this bit of data out, but it's also very easy for me to do.
I can see 2 alternative approaches:
One would be to either take advantage of the scoping of an anonymous Javascript function to keep a handle on the original bit of data, although this may not be possible and could perhaps lead to too much "magic".
Two, keep an object lying around that keeps a track of these things. Instead of asking the DOM for the contents of a certain data-attribute I just query my object.
I guess my assumptions are that the DOM should not be used to store arbitrary bits of state, and instead we should use simpler objects that have a single purpose. On top of that I assume that accessing the DOM is more expensive than a simpler, but specific object to keep track of things.
What do other people think with regards to, performance, clarity and ease of execution?
Your assumptions are very good! Although it's allowed and perfectly valid, it's not a good practice to store data in the DOM. Sure, it's fine if you only have one input field, but, but as the application grows, you end up with a jumbled mess of data everywhere...and as you mentioned, the DOM is SLOW.
The bigger the app, the more essential it is to separate your interests:
DOM Events -> trigger JS functions -> access Data (JS object, JS API, or AJAX API) -> process results (API call or DOM Change)
I'm a big fan of creating an API to access JS data, so you can also trigger new events upon add, delete, get, change.

How to use JavaScript MVVM/MVC with pre-loaded data

I want to load an HTML page with existing data (a list of comments or widgets or whatever), then use Javascript to render additional data in the same format as it is input by users interacting with the page.
I'd like to use a model stored in a JavaScript object that represents both existing data on the page as well as new data from user input, then observe to the model to update the DOM when it changes.
I'd like to render JS templates to display data entered by users quickly, without hitting the server again.
I would like to avoid writing server-side and JavaScript templates that render the same data.
To solve the first problem of building the initial model it seems like the options are, in order of preference:
Use JavaScript to pull the data rendered in HTML to build the initial model, or
Render JSON directly to the DOM and build the JS object from that, or
Hit the server again after the page is loaded as an ajax call to get the data as JSON
To avoid having server-side and client-side templates to display the same thing:
Use use something like Pure to build templates from the DOM, or
Only use JS templates and use one of the second options above to initially render the page (populate them from JSON rendered to the DOM or make an ajax call to get JSON to populate them).
Use a templating system that works on both the server and client.
I feel like none of these solutions are particularly elegant, and I'm curious as to what other patterns I may not have thought of or if there is a common solution.
My environment is Rails 3, but the problems are applicable to any server -> HTML/JS setup. I can see how some of this might be easier with something like Node.js but I'm principally interested in solutions that would apply to Rails.
There's so many ways to accomplish this. I have been struggling with this same issue. I think that once the complexity of your web app reaches a certain threshold you have to resort to javascript to keep the state correct. Jquery (among other dom manipulation frameworks) really help but at a certain point it can become spaghetti code.
I just touched this binding javascript library called Knockout. It's pretty elegant and simple to use it tries to follow the MVVM pattern by allowing you to create a ViewModel with observables that you can bind html elements so that their values and attributes change based on your ViewModel values.
If you're creating dynamic html you can always embed the initial values of the javascript ViewModel along with the html of the page so that you can avoid that initial ajax call.
Out of the box it is compatible with jquery templates which just makes dom manipulation a breeze. I've just started using it and I'm loving it so far.
Hope that helps.

Best way to link UI elements with backing javascript objects

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.

Categories

Resources