I am sending my HTML file to the client in node.js as shown below
app.get('/get', function(req, res) {
res.render(index.html);
});
Here, index.html refers to a json file.
How can I send both together or refer the json file in the client?
If you don't want to request the JSON file from the client as an independent HTTP request you can do one of the following:
Full server side rendering:
Use a template technology like moustache or handlebars, and try to render that data inline with the response. For example if you your JSON file returns a name and an address the index.html could look like:
<div>
<span>Name: {{name}} </span>
<address>Address: {{address}} </span>
<div>
Then when rendering you could pass a js object with properties name and address to the template and you wouldn't need to ask for the JSON file separately. This example follows moustache guidelines just in case I wasn't explicit enough.
Inline object
A bit like the previous solution but less elegant, you can add the full JSON response as an object with within a script tag, and then use it however you see fit. Try to append a block to he HEAD of index.html like this:
<script>
var myObject = <contents of your JSON object>
</script>
The other possible solution was just described in another answer.
I hope this helps.
HTTP only sends one resource at a time. If your page is requesting a JSON file, it needs to be served as a second request.
Alternatively, you can render HTML with a <script> block that has a variable assignment with your JSON-encoded data as a value.
You can't send two types of files back in a single request, but you could either do an ajax call in the html to get the json you need:
<script type="text/javascript">
var json_data;
$.getJSON("URL_HERE", function(data) { json_data = data; });
</script>
or add the json to the html as a javascript object via a template engine (jade shown below):
script(type="text/javascript").
var json_data = #{ JSON.stringify(JSON_OBJECT_HERE) }
Related
I have a flask server spitting out json data converted from pandas dataframe which look like:
[{'name': 'FBtr0075557',
'score': '164.00'},
{'name': 'FBtr0075557',
'score': '162.00'}]
The python code I'm using to convert the dataframe to json and serve in flask is:
result = df.to_json(orient="records")
parsed = json.loads(result)
return render_template('mirtar.html', targets=json.dumps(parsed))
When I use internal javascript, the data is parsed without any error:
<script type="text/javascript">
const targets = {{ targets|tojson }};
const entries = JSON.parse(targets);
console.log(entries);
</script>
However when I try to do the same using an external JS script, I get an error
Uncaught SyntaxError: Unexpected token { in JSON at position
From what I understand, the line const targets = {{ targets|tojson }}; in the external javascript doesn't behave the same way as in internal and the first '{' of the line is considered as an error.
I'm sure this is a very basic problem and there must be an easy way to do it that I have definitely missed.
Jinja syntax is only parsed in flask html templates, not externally loaded JS assets: because it's the python app doing the parsing, and in a deployed environment you'd typically serve static assets with a webserver like nginx.
The quickest way to sort this might be with this method where instead you use a data attribute within an HTML element. This appreciates that you're passing data to the template as an argument to render_template, so the data is present in the template at page load.
In your case this might look like
<!-- a hidden tag -->
<input type='hidden' id='targetid' data-thetargets='{{ targets|tojson }}' />
Then in your javascript load it up with:
var targets = JSON.parse(document.getElementById("targetid").dataset.thetargets);
I am building a Python/Flask based web app. The python script produces a dictionary of words and their corresponding weights. I have a javascript file (let's call it custom.js), which I call from the output.html. The way this javascript works is that it takes this dictionary and then uses d3.v3.min.js and d3.layout.cloud.js to create a wordcloud. When the dictionary is hard-coded into custom.js, the output file shows the wordcloud. However, the dictionary values will change depending on other parameters in the python script. Therefore, I would like to pass this dictionary from Python to custom.js. I am not sure how to do that.
I know that the parameters could be passed to HTML using {{ params |safe }}, but I am trying to figure out how to do that so that custom.js will receive the parameters (dictionary of words and weights, in this case) and word clouds can be rendered dynamically.
Thank you in advance!
If I understood you correctly you need to create a view function (a route) in the flask backend with url like this /get_dictionary. This function can look like this:
from flask import request, jsonify
...
#app.route('/get_dictionary'):
def get_dictionary():
...
your_dictionary = []
# Fill in your_dictionary with data
...
render_template('your_template.html', your_dictionary=your_dictionary)
EDIT:
You can pass the data from flask to script section of the html template using standard jinja2 notation:
<html>
<head>
<script>
your_dictionary = {{ your_dictionary | tojson }}
<!-- Do what you need with your_dictionary -->
</script>
...
</head>
...
you can try define a var in your template html, like this:
<script>
var your_var = '{{ value }}'
</script>
then use "your_var" in external js file. But please make sure above definition is at ahead of your js file refer.
My scenario is this - the user asks for the home page and then the javascript code of the page executes an ajax GET request to the same server to get some object.
The server keeps the home page as a jade template.
So, right now it takes two roundtrips to load the home page:
GET the home page
GET the JSON object
I am OK with it, but just out of curiosity - what are my options to incorporate the object requested later into the initial GET request of the home page?
I see one way is to have a hidden html element, which inner HTML would be the string representation of the object. A bit awkward, but pretty simple on the server side, given that the home page jade template is preprocessed anyway.
What are my other options?
Please, note that I am perfectly aware that sparing this one roundtrip does not really matter. I am just curious about the techniques.
Another option is to always return a JSON object, then the HTML for your home page would be the value of some property on this object. This would probably require some changes on your client-side logic, though.
One more option: instead of a hidden HTML input/textarea containing a JSON string, the home page code could contain a script block where an object literal is declared as a variable. Something like this:
<script>
var myObj = ... // Your JSON string here.
// myObj will be an object literal, and you won't need
// to parse the JSON.
</script>
The initial GET request will retrieve just that document. You can have additional documents loaded defined as scripts at the bottom of your page, so you don't need to do a XHR, for the initial load.
For instance:
GET /index.html
//At the bottom you have a <script src="/somedata.js"></script>
GET /somedata.js
//here you define you var myObj = {}.... as suggested by bfavertto
Depending on which server side technology are you using, this could be for instance in MVC3
public partial class SomeDataController : BaseController
{
public virtual ContentResult SomeData()
{
var someObject = //GET the JSON
return Content("var myObj = " + someObject, "application/javascript");
}
}
You can embed the Json data inside a hidden tag in your HTML. At runtime, your javascript reads the data from this hidden tag instead of making a Json call (or make the call if this data is not available).
<!--the contents of this div will be filled at server side with a Json string-->
<div id="my-json-data" style="display:hidden">[...json data...]</div>
on document ready:
var jsonStr = document.getElementById( "my-json-data" ).innerHTML;
I want to access the data that was sent from response.render in my html file.
I have this code in my server.
app.post('/game',function(req,res){
var name = "Jude";
res.render(__dirname +'/game.html',{user:name});
});
How do i access user variable in my game.html?
You'd have to use a template language like Jade, EJS and so on. If you already have the HTML in place, try EJS.
I'm trying to make a variable (eventually to be replaced by more complex json selected from the database) accessible to client-side javascript. I wanted to load it when the page is rendered instead of an ajax call and its not going to be rendered via a template like ejs (I want to pass the data to an extjs store for a combobox). So I have a standart response I render:
function (req, res) {
res.render('index.html', {foo: ['a','b']});
}
and a blank html page I want to access foo:
<!DOCTYPE html>
<html>
<head>
<script type=text/javascript>
console.log(foo);
</script>
</head>
<body>
</body>
</html>
any ideas? I've thought of maybe writing the whole html page via res.send() (which has a few more things than the example above) but that seems like such a workaround for something that should be obvious to do...
Assuming the same array foo in your question above, here are a couple ways you could do this.
This one uses an EJS filter to write an array literal:
<script type="text/javascript">
var foo = ['<%=: foo | join:"', '" %>'];
</script>
This one encodes it as JSON, to later be parsed by your client-side javascript:
<script type="text/javascript">
// note the "-" instead of "=" on the opening tag; it avoids escaping HTML entities
var fooJSON = '<%-JSON.stringify(foo)%>';
</script>
IIRC, ExtJS can handle JSON directly as its data. If not, then you could use its JSON parser first and then hand it a local variable. If you weren't using ExtJS, you could use this to parse on the client: https://github.com/douglascrockford/JSON-js
If you choose to encode it as JSON, it would make it also make it easier to later switch back to AJAX for retrieving your data. In some cases, that would have an advantage. The page could load and display some data, along with a busy icon over the element for which you're loading data.
This isn't to say there's anything inherently wrong with including all the data in the original request. It's just that sticking with JSON gives you the flexibility to choose later.
In EJS the following should work
<script type=text/javascript>
console.log( <%= foo %>);
</script>
I do recommend against dynamically generating JavaScript though as it breaks seperation of concerns and forces JavaScript to be on.
Edit:
Turns out the above doesn't work nicely for arrays. So simply encode your data in semantic HTML. Then enhance it with JavaScript. If the JavaScript must get data then store it somewhere more sensible like the cookie or retrieve it through ajax.