Timeleaf, Javascript Inline and Iteration

Using Spring MVC and Thymeleaf, I am creating an html view with some javascript inside.

Inside the page, th: each is used with iterative values ​​to give the button set a unique HTML identifier.

<td th:each="optionValue,iterStat : ${someObject.optionValues}"> <button class="btn btn-default" th:id="${'optionBtn_' + (iterStat.count - 1)}" th:text="${optionValue.toString()}" /> </td> 

My problem occurs when trying to generate javascript that will use a jQuery link for each button id.

In the 'other' permission permission language, I would use the code:

 <% for(var i = 0; i < someObject.optionValues.length; i++) { %> $('#optionBtn_<%- i %>').on("click", function() { doSomething('<%= someObject.optionValues[i] %>'); }); <% } %> 

(the above may not be 100% syntactically correct, but I hope you understand what I'm trying to do using this style)

but in Thymeleaf, although I understand that I can use

 th:inline="javascript" 

to refer to individual elements of the model, I don’t see how I can use the appearance to generate several jQuery function call definitions in a script block.

Any ideas? (I can approach the problem completely wrong, so I'm open to new ideas on this front too)

+1
source share
2 answers

I will accept your invitation to new ideas and put on the table my methodology for approximating such cases.
Obviously, the problem is mainly related to the exchange of data between internal and javascript data. The data that the javascript function needs is an argument in this case. Since html5 introduces data attributes and improved jQuery performance with them in later versions, you can identify any data that you want to use as attributes, starting with "data-". It acts according to html5 . In jQuery, you can access them as if they were jQuery data by translating the html naming convention into camelCase after shortening the original "data-" pefix. (e.g. data-my-attribute = myAttribute). You can either access them in the original html agreement (e.g. my-attribute). This is a matter of preference.

Then your html can be much cleaner:

 <td th:each="optionValue,iterStat : ${someObject.optionValues}"> <button class="btn btn-default" th:id="${'optionBtn_' + (iterStat.count - 1)}" th:text="${optionValue.toString()}" th:attr="data-my-func-attr=${optionValue}"/> </td> 

You can bind event handlers, and then:

 $("button.btn").on("click", function() { buttonPressed($(this).data("my-func-attr")) } 

or similar.

This way you also keep your code cleaner and separate from markup, which is one of the principles of Unobtrusive JS

+2
source

So, I made a workaround.

Since several elements may exist on the page, I simply create an external tag loop and create it for each button. Details in the method call will have the same index / text mapping as in the iteration to create buttons in the first place, although creating the text was somewhat complicated:

 <script th:each="optionValue,iterStat : ${someObject.optionValues}"> $([[${'#optionBtn_' + (iterStat.cont - 1)}]]).on("click", function() { buttonPressed([[${iterStat.count - 1}]], [[${estimateOption.toString()}]]); }); </script> 

Not the smallest once the code is generated, but it works.

0
source

Source: https://habr.com/ru/post/978804/


All Articles