13

I've tried 2 ways that both work but neither feel very clean.

The first is to have some inline javascript that accepts the variable from the view template like:

var x = {{ myServersideVariable }}; 

(In my case I'm using Jinja2 but same thing would apply to Django templates, Razor in .NET MVC3, Twig in PHP or any number of view templating engines).

Obviously the unclean part about this that there's javascript in the html page rather than in a separate file.

The other option I've used is to have a hidden field populated server side and then consumed on the Javascript end. That feels slightly more clean, but not completely and it's also a bit cumbersome to write.

Is there a better solution or are those pretty much my only options?

P.S.
I'm aware of JSON and in fact I do sometimes have to resort to the first solution if I need to pass something other than primitives. So bonus points for a solution that supports passing JSON objects without having javascript on the page.

Davy8
  • 30,868
  • 25
  • 115
  • 173
  • did you heard about **node.js**?? i think that may help you... – xkeshav May 08 '11 at 14:04
  • 7
    @diEcho: how would Node.js possibly help here? – Matt Ball May 08 '11 at 14:08
  • @Matt ball i only heard about node.js that it is server side javascript...thats why i write the word 'I THINK'....please correct me if i am wrong..Thanks – xkeshav May 08 '11 at 14:16
  • 3
    @diEcho: yes, Node.js _is_ "server-side JavaScript." That means it's a framework which lets you write server code in JavaScript, as compared to, say, PHP, Java, C#, or Python. No, Node.js would not be helpful here. – Matt Ball May 08 '11 at 14:20
  • @Matt Ball...Thanks for the updating my knowledge...is there any link where i can learn node.js in simple terms..bcoz i found it very tough when reading its own website – xkeshav May 08 '11 at 14:24
  • 3
    @diEcho: Stack Overflow, of course! http://stackoverflow.com/tags/node.js/info – Matt Ball May 08 '11 at 14:29
  • if its PHP then, `var data = ; //Don't forget the extra semicolon! ` from this answer right here :http://stackoverflow.com/questions/23740548/how-to-pass-variables-and-data-from-php-to-javascript – nicholaswmin Nov 30 '14 at 20:33

4 Answers4

6

There are only two correct ways to inject data from the server into javascript.

You either expose the data as a service. You can have a REST service or whatever you like and then query it with ajax to extract data from it.

The other option is to inject the data into the HTML. You want to use JavaScript to progressively enhance your page. So that data already needs to exist in the HTML, and your JavaScript will extract it from the HTML.

Now if your going for a JavaScript heavy application which can't be supported without JavaScript then you want your data to be a REST service.

You do not want to inject it into a serialized hidden field because then your html markup does not have the semantics of the data. You do not want inject it directly into a var x = ... statement because then your compiling your JavaScript on the fly. This breaks the seperation of concerns.

Raynos
  • 166,823
  • 56
  • 351
  • 396
  • I agree with most of your answer, but I don't see how "compiling your JavaScript on the fly" breaks separation of concern? – Davy8 May 08 '11 at 15:05
  • Also one of the usage I currently have is actually figuring out the url of the AJAX call (it could just as easily be a post/get parameter but I'm using url routes to provide parameters server side). For sake of example, let's say it's a chess game, and a player can participate in multiple games at once in separate tabs, each with their own url. On each page, I need to know which game I want to make an AJAX request concerning. How do I retrieve that information? – Davy8 May 08 '11 at 15:11
  • @Davy8 sure it does. Your javascript is hard coupled to your server side code. You should avoid injecting data into your javascript. As for the URL. Inject the url into a ``. That data goes into your html. Then you can have javascript pick up your link and turn it into an ajax link. – Raynos May 08 '11 at 15:16
  • the AJAX call is actually for polling (yes I know, at some point I'm going to need to switch to some form of Comet but there's other priorities at the moment) so the link shouldn't be visible. Is a hidden hyperlink better than a hidden field? Also it's not always part of a url, another case is that it's the timestamp of the last update from the server so they server can return from the Ajax call saying nothing has been updated since the last check. How should that case be handled? – Davy8 May 08 '11 at 15:34
  • @Davy8 there should be a static url you can poll for data with information. The Ajax call should return enough data for you to make the next poll. If you take a look at REST API design, you will find that REST APIs generally have a single static entry point and the data they return tells you where to go next. elegant solutions are a pain in the ass though if it wasn't well designed from the ground up. You would need to present more specifics of your problem to solve it in an optimum way. Maybe a new question – Raynos May 08 '11 at 15:51
  • Just to clarify the *"html markup does not have the semantics of the data"* part - this means that your html contains an element which is meaningless as a markup language, it there just to store data (which isn't the semantic of HTML). – BornToCode Oct 15 '17 at 18:13
4

If the data you want to make accessible to the client-side JavaScript is known at the time the HTML page is requested/generated and will not change until the next time the page is requested then I would not use AJAX because obviously that results in an extra request: one to get the main page, and then another immediately on load to make the AJAX call for the data. That's going to reduce performance and pointlessly complicate both the client and server code.

There's nothing wrong with creating one or more hidden inputs with the data and accessing from your JavaScript code. Depending on the values you want to pass it may be easier to inject the values directly into JS variables in a <script> section on your page, similar to the example you give, and personally I find that easier to read than hidden inputs because the <script> section will be prominant at the top of the page rather than having inputs buried somewhere amongst the HTML, and it makes it obvious that the values are intended to be consumed by your code on the client-side and not just submitted back with other form data. But either way is not "unclean".

If you need to get the server-side data into your JavaScript as a response to something the user did on the page after it loaded (clicking a button or something), or if you want to poll the server at regular intervals to check if the values have changed, then you want to use AJAX.

EDIT: note that although you can dynamically generate JS script files on the server and thus keep your dynamic values out of the HTML page entirely sometimes this doesn't work very well because certain browsers can get confused and keep using an earlier cached version of the JS. I've had this happen with older versions of IE.

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
2

Use JSON to pass variables from the server to the client as it's a very popular and well supported format. PHP, Python, Java and - what's most important - JavaScript handle it really well. You don't have to care about character escaping etc.

// PHP Example

$vars = array(
    'a' => 'def',
    'c' => 'xyz',
    'e' => array(1, 34, 766, 844)
);

...

var variablesFromServer = <?php echo json_encode($vars) ?>;
// or using Twig
var variablesFromServer = {{ vars|json_encode }};

alert(variablesFromServer.e[2]); // output: 766

It looks very similar in other languages.

You could always use a single entry point (variablesFromServer variable) to pass all the information that should be passed from the server to the client. That would make your code clean and easy to maintain.

Final usage - from the client perspective - is also really easy:

<script src="..."></script>
<script src="..."></script>
<script src="..."></script>
<script>
    var variablesFromServer = ...;

    MyProject.setConfiguration(variablesFromServer.config);
    MyProject.setRuntimeVariables(variablesFromServer.runtime);
    MyProject.run();
</script>
Crozin
  • 43,890
  • 13
  • 88
  • 135
  • OP doesn't say that he is using `PHP` as server side language – xkeshav May 08 '11 at 14:16
  • This is exactly what I said my first solution was. I guess I wasn't entirely clear what I meant by "inline javascript" I meant Javascript on the same page as the html instead of in a separate file. It works but it feels unclean. – Davy8 May 08 '11 at 14:29
  • @diEcho the problem isn't that it's PHP, I can translate it to whatever language, but the problem is that it's a solution I already mentioned in the question and I mentioned what I felt was the issue with it. – Davy8 May 08 '11 at 14:31
  • 1
    May I make a small suggestion, replace array(...) with [...], that is more JSON-like, and it will make Douglas Crockford smile. – Zoidberg May 08 '11 at 14:34
  • @Crozin Sorry to -1 but this is exactly the first solution that I already mentioned in my question and doesn't get around what I said that I don't like about it. – Davy8 May 08 '11 at 14:43
  • @Zoidberg: `array(...)` is PHP code, not JavaScript. PHP doesn't support the JSON-like `[...]` syntax. – alexia May 08 '11 at 15:26
  • LOL, didn't even notice, my bad. IN javascript you can use new array(...), so I mis-interpreted. – Zoidberg May 08 '11 at 17:51
1

One solution that I just thought of of is server-generated javascript files. I like it from a clean-code and separation of concerns perspective but it may kill any kind of browser-caching, so it would depend on how important performance is.

Davy8
  • 30,868
  • 25
  • 115
  • 173
  • Not only will it stop the browser caching the JS file, you may find certain browsers get confused and keep using an older cached version of the JS file instead of getting the newly generated one. (I've had that happen with older versions of IE.) – nnnnnn May 09 '11 at 01:54