I have a list of books and I want to store data against each book e.g. Price, Quantity, id, catergory id, size, weight etc.
I was looking at storing all this in the dom by extending the li elements representing each book in the list using data- attributes. This data could then be utilised directly with javascript.
However I have read that accessing data- attributes is slow in a performance sense. In addition I can have multiple instances of the same book so am a little concerened about bloat in the html.
An alternative would be to use a JS object to store data for each book.
So my question is what is the best practice for storing data in the frontend, DOM or Javscript?
Thanks in advance
The data- attributes are generally used more as a way to get data into your JavaScript (i.e. From your server-side template), and less a runtime place to store your data. A better place keep your active data is in a JavaScript object, especially if you will be accessing it or manipulating it frequently during the life of your script.
This is more in keeping with an MVC approach, where the data lives in your Model, but may be represented in your View. For this reason, some of the newer MVC frameworks like AngularJS provide automatic two-way binding between the two.
The choice is really dependant on your application architecture and type of functionality in your application. If you are building a single page app I found that using a well constructed json object in conjunction with a good templating plugin gives you much more flexibility in terms of functionality.
I found that indexing your data on an id in your json and then storing that id in the "data-" element gives you a nice way of reacting to browser events (clicks etc) without having to search through JSON structure. Having a JSON structure also makes it a bit easier to do operations such as sorting lists and other global operations that you might want to do without having to rebuild your data from DOM. This method is also better when you work with MVC like frameworks or implement your own "observable" data structures.
On the other hand if you are working with mostly server side code and have only basic functionality in your page that utilizes your "data-" data (such as display book details on click or something simple like that), it is probably simpler to just use the "data-" attribute to store additional details.
The difference between storing that in the DOM elements and keeping data as JavaScript objects is that in the first case you have the data and the DOM element directly related, while in the second case you need to somehow keep similar data and DOM structures in order to keep the data related to the DOM. The second case is, as it sounds, more error prone, because you have to make sure that every change in the DOM is reflected in the data (adding/removing/modifying elements) and every change in the data is reflected in the DOM (adding/removing/modifying data members).
In the case of data-* attributes data is directly accessed from the DOM so the two are already tied together and is, at least in my opinion, a much better practice. However, as mentioned in comments, there is a DOM retrieval overhead which comes with data-* attributes.
In terms of performance both require the data to be stored in memory, be it as DOM element attributes or as JavaScript objects. Retrieving a DOM element attribute is actually more expensive but it's more convenient. Rendering is not affected by data-* attributes as they do not have any functional meaning.
Related
For the past few years I have always used a client-side hidden <input> field to store a server-side value and use it in Javascript land.
For example, let's say I need an Ajax timeout value from my app configuration.
I'd probably store it like this in my JSP:
<input type="hidden" id="ajaxTimeout" value="${serverValue}" />
and then use it like this where my AJAX call lived in an external file:
$("#ajaxTimeout").val()
I was having a discussion about this today and it was suggested that it is best practice to store values which are only going to be used by Javascript within HTML <meta> tags.
Does this matter? Is there a preferred way to obtain server-side information which is solely to be used in Javascript?
My understanding is that if the hidden input field is not part of a form then it is safe enough to use to store value as it won't be attached to any requests. Having said that, I've always thought this was indeed a bit of a hack.
Thoughts?
::EDIT::
Two fantastic answers:
Use objects literals for general in-page data that is not tied to any particular DOM element.
Use data attributes to store custom data tied to DOM elements: http://www.w3.org/TR/2010/WD-html5-20101019/elements.html#attr-data
In addition to the plain old object literal method given in other answers, if the value you want to pass to the client is about a specific DOM element (or there is a DOM element that represents the logical object that the value is about), you can put the value in a data attribute:
<div id="videoplayer" data-startplayingat="1:02">HTML Content</div>
This is accessible as an entire attribute, data-startplayingat, or in modern browsers there is the dataset attribute. jQuery syntax is $('#videoplayer').data('startplayingat').
The official W3C spec on data attributes explains all this.
Here are a few interesting highlights:
The name must not use upper case letters, and must be XML compatible.
The dataset attribute converts dashes, such that a name like start-playing will become startPlaying.
One potential drawback for the object literal method (which I like and have used myself) is that if you want the object in a .js file, then normally static javascript files have to be run through your dynamic parser--which will cause a potentially small (but still present) performance loss. Putting the object declaration into a <script> tag in an HTML file works around this, but then you can have script load order issues to deal with.
We personally do something like this:
var options = {
selector: '#divId',
serverSideVariableHere: <%=AspNetProperty %>,
anotherServerSideVariableHere: <%=AspNetPropertyTwo %>
}
var viewModel = new KnockoutViewModel(options);
ko.applyBindings(viewModel, $(options.selector)[0]);
This is simply an example using KnockOut JS, but this idea can be expanded to any JavaScript library you choose to use (or not ;))
We then pass these options to whatever use them, such as Knockout ViewModels, or whatever. That way our JavaScript remains testable and we can pass in whatever values we want to our tests.
Using meta tag for something other than browser meta-"instructions" is no less of a hack IMO.
I would consider storing JavaScript data where it belongs - in JavaScript, using JavaScript object literals.
I strongly prefer JSON snippets in data- attributes. This lets you scope them to the related HTML element, and you don't pollute your Javascript global namespace, or have to generate additional code to handle namespacing otherwise. Coupled with a JSON serialiser on the server side this minimises having to manually escape anything in your values.
(Also I have a Thing™ against <script> tags with content in general. View and logic separation and all that.)
I need to keep the state of my Html control (I've a multi select list and I need to keep the info about selected items), for which I'm using a custom attribute like:
// put
$("#element").attr("selectionState", "value");
// get
alert($("#element").attr("selectionState"));
While it works, I wonder if it's a safe approach and if not, how would you solve the problem?
The only risk I can see is - another script creating custom attributes with the same names, which is something I can manage.
I suggest using .data() instead.
$('#element').data('selectionState', 'value');
It's definitely safer, as it keeps the data completely in JavaScript instead of the "attributes" maps in the DOM elements. Sins ".data()" is all JavaScript, you can store anything there, including functions and closures. (I guess you could do that with ".attr()" too but it's pretty risky in IE, which, in old versions at least, had quite different storage management internally for DOM and for JScript.)
The namespace problem you allude to is of course the same, as would be the possible ways of managing it.
I seem to often be making the decision to create objects in javascript that are basically the ModelView or Model objects in an MVC architecture. So when the user changes their properties or whatever via the webpage, the javascript object's properties are changed, and then the javascript object is submitted to the controller. The main reasons I am using this approach are:
Increased flexibility of display.
Alternatively, everything is done
with forms so that I can easily post
them back to the controller. Forms do
not allow various display options
such as wrapping around other
elements and so on.
I am using a lot of javascript
anyway. I have to manipulate the
elements whenever buttons are pressed
(like swapping two list elements
around). I also usually hijack the
buttons and use them with ajax.
The default model binder rarely works
on complex objects so I need to
maintain two sets of objects anyway.
It is easier to perform complex
validation on a javascript object
compared to html.
Are there any libraries or techniques or approach that assist with this approach? Maybe JSON.NET? Do any people try to avoid this approach?
I haven't taken this approach myself but there are some frameworks that sound similar to what you are proposing. The one that looks most interesting is Knockout JS. It provides data binding to your model among other features.
I have a particular scenario where I need a file name, not once but twice, because I pass the variable to an ASP.NET MVC controller. Is it a good idea to either store the file name in a DOM element like a span or div, and getting the value by using jQuery's .text() function? Or would a better approach be to work with JSON-like objects that are initialized and then continuously manipulated?
The question however remains. Is it a good or bad idea to store variables in HTML DOM elements?
As #Atticus said, it's fine to do it either way, and I'll do both depending on what I need the data for: If it's specifically tied to the element, I'll store it on the element; if it's more general to the page, I'll pass back an object using JSON notation.
When storing data on DOM elements, you don't need to store them as text within the element. You can use data-* attributes instead. These are valid as of HTML5 and work in all browsers right now. The only downside is that if you're using validation as part of your workflow, and you're not yet using HTML5 to validate (and that wouldn't be surprising, the validator isn't quite ready, what with the spec still being rather in flux!), they don't validate in HTML 4.01 or below. But browsers are fine with them, this is one of the areas where HTML5 is codifying (and reigning in) current practice, rather than innovating.
Either one works, and it's fine to store data in a DOM. It more so depends on the complexity of the operation you are trying complete, which sounds simple -- storing file names. I think you should be fine doing it this way. Storing in JSON object works too, I would go with whatever fits your structure best and which ever works easier with your client/server handshake.
Is it considered good practice to use DOM Element's getAttribute/setAttribute calls to associate additional information about contents of the element ?
For example I want to call setAttribute("MY_ATTRIBUTE_VALUE", "..."), where MY_ATTRIBUTE_VALUE isn't anything applicable to <div>.
Thanks !
You should definitely go with data attributes. Here's an article on them. HTML5 Custom Data Attributes.
It is very good practise as long as you're setting custom data attributes, whose purpose is holding meta data about those elements. Data attributes take the form data-name where name can be any valid descriptor.
Traditionally people would add classes, and in some cases this is still appropriate (e.g. when a class describes the state of an attribute and also denotes a style class, for which class is primarily used).
If you believe that markup is about presentation, then associating data with HTML elements is inconsistent with that philosophy. If you think that it doesn't matter, then use data- attributes introduced in HTML5. Note however that HTML5 is not a standard and is not yet that widely supported (if the term "supported" has any meaning in the context of a "living specification" that is constantly changing). However data- attributes likely won't upset most browsers but you must use get/setAttribute to access them reliably in a browser independant way.
It is considered good practice to keep data separate from presentation so that you can change the presentation to provide multiple views of the same data. If you bind data to the presentation, you reduce your ability to do that. It also means that changing the data model may well affect presentation unnecessarily.
Storing data in an object and relating it to the element (say by the element's id) will likely provie much faster access to the data (direct property access is much faster than function calls passing strings) and allow for a more flexible UI and data model.