Thymeleaf syntax is not working in java script file - javascript

I am using spring boot to provide data to thymeleaf.
var list = [(${listStudents})];
listStudents is a list of students with the help of which I populate data in HTML which is working fine but fetching the same list in java script using thymeleaf shows error in the above line as:
, expected.
I have added th:inline="javascript" attribute to script tag in HTML file as:
<script th:inline="javascript" src="home_script.js"></script>
Trying to solve this since yesterday.
Thanks in advance!

The , expected error is the standard JavaScript syntax error for var list = [(${listStudents})];. To handle this, Thymeleaf supports placing its inline expressions inside JavaScript comments:
var list = /*[[${listStudents}]]*/ [];
Because the Thymeleaf expression is in a JS comment, note how we have to provide a default (visible) JS value, to keep JavaScript from raising a different syntax error. I used [] because you have a list. You could have used '', or null or whatever is most suitable. Assuming your Thymeleaf is rendered correctly, this extra syntax will be ignored.
See JavaScript natural templates for details.
However, I do not think this will completely resolve your problem, unless you have already configured a JavaScript template resolver in your application.
You are using this:
<script th:inline="javascript" src="home_script.js"></script>
First of all, the th:inline="javascript" portion has no effect, because your JavaScript code is in an external file: home_script.js (i.e. it is not embedded in your HTML file).
If you want Thymeleaf to process the Thymeleaf expressions in that separate JS file, you have to tell Thymeleaf to explicitly process external JavaScript files (just like it processes HTML files).
You probably only have a HTML resolver - and your JS code is not embedded in your HTML file - it is in its own separate JS file. See this demo application which shows how to set up what I think you may need.
Alternatively you can simply embed your JS directly into the <body> of your HTML file, and don't use an external JS file:
<body>
<script th:inline="javascript">
var list = /*[[${listStudents}]]*/ [];
</script>
</body>
If you still need to use an external JS file, you can assign all your Thymeleaf-generated variables inside your HTML file (like the example above) and then pass these variables as function parameters into the various JavaScript functions in your JS file.
Using this approach means your JS file does not need to contain any Thymeleaf expressions - it just receives the rendered values from the JS fragment in your HTML file.

You should use [[${listStudents})]] (so 2 square brackets, not using round brackets)

Related

Preferred way to dynamically change variable in Javascript using Python/Flask framework

I am relatively new to HTML/Javascript, and I have a need which I am sure is common, but I don't know the preferred/standard way to handle it.
Basically, I have a web page with Javascript/jQuery code to use AJAX to dynamically change values on a page. I prefer not to encode the AJAX URL statically in the Javascript, but rather be able to pass the URL using Jinja from the Flask application.
So, for example:
$("#inputtext").autocomplete({
source: function (request, response) {
$.getJSON("{{ url_for('main.auto') }}?q=" + request.term,
function(data) { console.log('doing something in the function') }}
The key question is the Jinja template in the middle {{ url_for('main.auto') }}. This correctly renders the route for 'main.auto' if the Javascript code is embedded in the HTML file. However, I prefer to separate the JS from the HTML. So, I took the above code and put it in a separate .js file and imported it into the HTML like this:
<script type="text/javascript" src="{{ url_for('static', filename='js/memberSearch.js') }}"></script>
The above code is in the memberSearch.js file in this example.
When I import the JS code like this, Jinja doesn't render the {{url_for('main.auto')}}. I suppose that this is because Jinja goes through the HTML code first before the JS code is imported.
I found an answer by #martijn-pieters here that lists four methods of passing data from HTML to Javascript:
You can put that information in HTML tags. In the above example, your data is put in the repeated tags.
Or you could add data attributes to your HTML, which are accessible both to Javascript code and to CSS.
Or use AJAX to load data asynchronously; e.g. when you pick an option in the box, use Javascript and AJAX to call a separate
endpoint on your Flask server that serves more data as JSON or
ready-made HTML, then have the Javascript code update your webpage
based on that.
Or generate JSON data and put it directly into your HTML page. Just a some_variable_name = {{datastructure|tojson|safe}};
section is enough; then access that some_variable_name from your
static Javascript code to do interesting things on the page. JSON is a
(almost entirely a) subset of Javascript, and the way the tojson
filter works is guaranteed to produce a Javascript-compatible data
structure for you. The browser will load it just like any other
embedded Javascript code.
Of these methods, I have successfully used the first one by embedding the Jinja template in a element like this, for example:
<input type="hidden" id="urlForPdf" value={{ url_for('main.auto') }}>
Which allows me to access the rendered URL in my JS code.
I have also tried the fourth method of generating JSON directly in JS like this:
<script type="text/javascript">var url = {{ url_for('main.auto')|tojson}}</script>
which allows me to access the variable url from the JS function.
The answer I referred to above also mentions using Data Attributes. I haven't tried this, but I believe it would work as well.
My question, then, is simply whether there is a preferred way of doing something like this? It seems that this must be a very common scenario and I assume that there is some more-or-less standard way of handling this. I'm just not sure which of the four possible solutions is preferred, or if perhaps there is another way altogether.
Thanks in advance for any light you can shed on this.

Why should JavaScript access to a list sent by Flask only if it is executed within the <script> tag in HTML?

I would like to send a list to JavaScript from Flask. I noticed that if I write JavaScript code inside an HTML tag it works, while if I do the same thing in a file linked inside the header I get the following error:
Uncaught SyntaxError: Unexpected token {
The javascript code is as follows:
var docs = {{ txtDocs | tojson }};
console.log(docs);
The Python code is the following:
app = Flask(__name__)
#app.route('/')
def landingPage():
return render_template('landingPage.html', txtDocs=json.dumps(os.listdir(pathToTxtDocs)))
I think that piece of JavaScript code inside the HTML is interpreted by Jinja2, while in case the js code is inside a file it is not interpreted. I'm quite sure.
But I would like to have separate html code and javascript code, for better reading.
So, is there a way to read a list sent by python to a js file? (Obviously linked in the HTML header).
Thanks in advance.
I think that piece of JavaScript code inside the HTML is interpreted by Jinja2, while in case the js code is inside a file in itself it is not interpreted
Indeed.
But I would like to have separate html code and javascript code, for better reading.
This only makes sense if your js code is used in more than one template - else having to open and read each js file linked in your template (directly or via a parent template) to find out what js code is actually executed really doesn't make your code more readable.
Now for the technical solutions: the first one is to have a function in your .js file and call it from the template - which means you'll STILL need to have some js in the template:
# yourlib.js
function doSomethingWithDocs(docs) {
// your real code here
}
and
# template
<script src="/your/js/yourlib.js"></script>
<script>doSomethingWithDocs({{ txtDocs | tojson }});</script>
The other solution is to expose an API endpoint in your flask app that returns the docs as json already, and make a call to this endpoint in your js file. You will very probably STILL need to pass some data from the view to the template to the js function to make the correct API call though...
IOW: your code is fine this way, it works, and it's as simple and obvious as possible.

How to call .sjs file from HTML?

I just started learning programming using MarkLogic.
I followed documentation, created "sample.sjs" file like in below.
https://docs.marklogic.com/guide/jsref/language#id_71272
xdmp.setResponseContentType("text/plain");
"hello"
How should I call this "sample.sjs" to display result in HTML?
Or should I better include HTML code inside "sample.sjs" file?
Your SJS code must construct whatever content you want to return to the caller, including HTML. The content returned by your module becomes the response data.
There's a bit more robust example using JSON instead of HTML, here:
https://developer.marklogic.com/learn/sjs/http

How to read model attribute from js outside jsp

If my javascript/jquery code is written inside a jsp-file, I can refer to Spring's modelAttribute value with "${varName}".
However I would like to move the javascript code into it's own file to keep the jsp-file more readable. When I do that, it won't however be able to find that modelAttribute anymore. How should I solve this problem?
How can I point to model attribute from a .js -file?
Thanks in advance!
Alright, I've experimented on my end to try to find and answer for this question.
Actually, it seems there's no direct solution, and here's why:
When you are moving your Javascript code to a separate file, this means that the browser will launch a separate request to fetch that file. As such, data that you store in your request scope (a.k.a. ${varName}) is not part of the request that fetches the .js file; it's only part of the request that fetches your .jsp file instead. As such, the ${varName} value will not be available in your Javascript file.
Another reason on top of the above: .js files are not processed as server-side code by the web engine (most likely Tomcat in this case), so the ${varName} text is outright ignored. For fun, I tried to do a hack: I renamed my script file from .js to .jsp, and used this within my .jsp page:
<script type="text/javascript" src="js/actually_javascript.jsp"></script>
It fooled the web server to process the file server-side, but this still didn't work, because of reason #1 stated above. It could work if you stored the value in the session instead, but at the end of the day, it would be kind of an ugly hack and you'd lose out on the code highlighting and completion features of your IDE, which would be fooled into thinking you're editing an actual .jsp file. Not recommended.
To conclude, I think the only way to access {$varName} inside your JavaScript is either:
Having the Javascript being a part of your .jsp file, within <script> tags
Having your Javascript in its own .js file, but still having a <script> tag in your .jsp page which initializes the module you programmed in the .js file and passes the values from the request, like ${varName}
You should initialize your javascript file via your jsp file.
Example:
Create a seperate script section for initialization of your variables after loading the .js file in your jsp page:
<script src="js-path/file.js"></script>
<script>
init(${varFromModel1}, ...);
</script>
And define the init-method in your javascript file:
function init(param1, ...) {
// initialize variables of .js file here
}
Remember, for this to work, you need to ensure, that the model-attribute output has correct javascript syntax.

How to transfer mvc view javascript code to separate js file

I am using Knockoutjs in my asp.net MVC-5 application. I have the following javascript in view:
<script type="text/javascript">
var model = "#Html.Raw(Json.Encode(Model))";
$.get("#Url.Action("_CityPartial")" ...)
//any much more code using similar Html helpers + pure javacsript code.
</script>
Now i want to know, is there any way to transfer this javascript code in a separate js file (keeping Html helpers as it is).
I want to transfer javascript code to separate file because i dont want any user to check my javascript code (using chrome inspect element or any other way).
If the transfer is not possible than please let me know if there is a any way to minifiy the javascript in view itself ??
You could create an external .js file with your code in and pass your serialized json object to it like this:
<script type="text/javascript">
var model = #Html.Raw(Json.Encode(Model));
DoThis(model);
</script>
This has the benefits of keeping the main body of javascript in a separate file.
Any other razor variables can be passed across to the methods defined in the javascript in the same manor as the model has been above.
However as Stanyer mentions this is still javascript and it will run on the client.
You can load it via an external JavaScript file, but unfortunately as JavaScript is a client-side scripting language regardless of whether its loaded inline or externally, the client can still view the code which is being executed on their browser.
You mention minifying - again this can still be interpreted by a client if they really wanted to see your code, but there are many tools online which can minify your JavaScript for you.
Examples:
http://jscompress.com/
http://www.jsmini.com/
No you cant keep the #Html helpers in external javascript file. They are all server side syntax and will be rendered in your HTML page inline.
What maximum you can do is, assign it in a var variable in your page and refer it inside a external page.

Categories

Resources