How to pass a javascript object back to the server?

What is the best way to pass server-side variables to client-side JavaScript?

  • Our application uses a lot of configuration options. Those options need to be reflected on the client side in the form of User preferences, site wide preferences, etc. Currently, we pass server side settings down to the client side in the form of JSON that is stored in custom attributes in the markup for a specific element (and no, our application currently doesn't worry about W3C validation). We then retrieve the data from the custom attribute, and parse it into a JSON object for use in script using jQuery. One drawback to this is referencing attributes on elements from within event handlers. I know this is frowned upon, as it can create circular references, and subsequently memory leaks. I would much prefer to use jQuery's data function, but you can't invoke this from the server side at page render time. What does everyone else do in this type of scenario?

  • Answer:

    One suggestion I've had is to use HTML5's data attributes. So, prefixing the custom attribute with data-. i.e. <div id="someId" data-config='{"userId": 1234}'></div> This would then allow this to be used like: var userId = $('#someId').data('config').userId; // assigns 1234 This to me seems like a great marriage of server side and client side.

Stephen Calvert at Quora Visit the source

Was this solution helpful to you?

Other answers

I've done what Stephen Calvert suggests, and I've also just set a bunch of variables in a script tag (the script is generated server side, of course). It all depends on whether or not the config is something you need to access globally in the page or if it is relevant to only a few of the HTML elements. Something like this works (I'm assuming that this is wrapped in a script tag, but I won't put it in here, as it would probably get stripped out): config = { userName: 'Scott Patten', userLogin: 'spatten', hasBoughtCurrentBook: true, followers: ['peterarmstrong', 'rolandtanglao'] }; config is a global variable, so you can then access it from any other script. You can, of course, take this a bit further and create a Config model with defaults and such, but this should be a good start.

Scott Patten

I would avoid coupling JavaScript config settings with HTML markup. I think there are better ways of passing data from server to client. The most direct way would be to plug the data directly into the JS. In this example, Zend is assumed to be the server-side framework. YOUR_APP.settings = <?= json_encode($this->settings) ?>; The disadvantages of this method are that the server blocks the JS execution and that the settings may only be set once. The advantage is that the settings are baked directly into the JS and there is no overhead of extra HTTP requests. Alternatively you could use AJAX to request the settings, and invoke a callback function when ready. function getSettings(context, fn) { $.get('/api/getsettings.php', function (data, status) { if (status === 'success') { fn.call(context, data); } }); } getSettings(this, function (settings) { YOUR_APP.settings = settings; // do more stuff... }); The disadvantage of this method is an extra HTTP request, but it allows the client-side to request the settings whenever and however many times it wants. Another disadvantage is that the settings-dependent code must wait for the JSON response, as in the // do more stuff... section.

Rick Viscomi

I would say three come to mind. using html5 data attributes on html elements: <div data-username="foobar" /> setting a global variable inside script tags: <script> var data = {}; </script> Or asyncrhonously loading with ajax requests that return json.

Anthony Ettinger

As always, asking for the best solution is problematic without giving very specific parameters for what you are trying to achieve, because for the general problem you describe there are many solutions. Some are already listed, and I include them in this list. The server generates the JavaScript for rendering in the HTML (as Loki and Henrik suggest). This is a nice, low bandwidth solution as all the data you need is automatically in your document in the original HTTP request from the client.  However, this is not optimal if you have a heavily interactive web page because it requires that the server generate the entire document again if there is any state change in your data. Use additional HTTP requests (as Rick suggests) to obtain the data from the server after the document has been rendered by the browser.  This, obviously, is using XHR to make 1 to n requests to different services to get appropriate data. This has the rather obvious side effect of requiring more connections from your web server to your application server, which can cripple a poorly designed infrastructure if the usage is heavy and there are many XHR connections. Use Web Sockets to have the server directly inject data into client DOM or JavaScript objects.  This is relatively cutting edge, even though the capability has been around for some time, but the browsers are only now getting around to fully supporting it.  A good example of this is http://meteor.com/, but some quick Googling will find support for more servers and other frameworks. My personal opinion, which may or may not be applicable for your use case, would be to avoid injecting JSON in your HTML elements and using jQuery to then extract it, because of two reasons: It's unnecessary processing required on the client side when the server can perform the same task.  This is only a valid concern of mine if you have a non-interactive document. It is generally(1) not scalable. As an application continues to mature and the amount, and complexity, of data required by it grows, decoding and parsing large JSON documents stored inside HTML attributes can quickly cause noticeable and unfortunate performance problems for the client. I have found, in my own experiences, that using XHR to request data from the server after the HTML document has been rendered provides the best combination of flexibility, and scalability as an application matures.  This way, your HTML, styling and interactive elements are all decoupled from each other and far more easy to maintain as time goes by. (1) This is an admittedly vague assertion because I don't know the parameters of your specific case.

Steve Brownlee

You could still print the data as an attribute on the elements, and then move it into jQuerys data at client initialization.

Mattias Petter Johansson

Don't fear the script tags for this. You want behavior separated from structure/content, and presentation. Raw data dropped in on the initial page load doesn't really violate that. When you're going through trouble to do it right, something is wrong. Most client-side best practices are all about reducing work not adding to it.

Erik Reppen

If you want to bootstrap it with the page load, I'd use your server-side template to output the JSON inside a function that gets called. Oversimplified example: <script> $(document).ready(function () { handleData(" HAVE YOUR SERVER SIDE TEMPLATE OUTPUT JSON HERE "); }); </script>

Henrik Joreteg

jQuery has a data() function to tie data to a Dom element, its siilar to the one on the HTML5 API, but its usefull in way more browsers. Also if you use a data name that starts with a dot(.) it tirggers a event that you can listen every change and do something like change the value display. PHP example <script> $(document).ready(function(){ $('#something').data('.mydata',<?php echo json_encode($somearray)?>); }); </script> http://api.jquery.com/jQuery.data/

Loki Zavala

Just Added Q & A:

Find solution

For every problem there is a solution! Proved by Solucija.

  • Got an issue and looking for advice?

  • Ask Solucija to search every corner of the Web for help.

  • Get workable solutions and helpful tips in a moment.

Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.