4

I'm building a web page using spring that needs to build a table using an API call that returns a dynamic number of elements.

Here is what I have now:

@RequestMapping(value = "/managecustomerconfigurations", method = RequestMethod.GET)
public ModelAndView setUpPage(){
    ModelAndView model = new ModelAndView("customerconfigurations");
    model.addObject("cdata", custServe.listAllCustomers());
    return model;
}

I can get cdata in my web page if I type

<p th:text="'Customer:' + ${cdata}" />

but I cannot see it if I just type

${cdata}  

or if I put the data in any JavaScript (even if I use an onload method)

Quick sidenote: I am using HTML 5 not JSP.

Ideally I would want to pass in the API response into JavaScript and build a table based on that response.

2
  • You should tag your question for thymeleaf, it totally changes the scope of the issue. Take a look at: thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html Commented Mar 30, 2015 at 18:18
  • ah ok doing that now. Commented Mar 30, 2015 at 18:49

3 Answers 3

2

Dynamic content in Thymeleaf has to be defined only as th:attributes inside standard html tags. Html rendering engines just ignore unknown attributes unlike unknown tags or expressions within page content.

This is the main idea behind Thymeleaf's natural templating design, so there is no clutter of third party tags and expressions when statically displaying the page. Unlike jsp, the template processor resolves th:attributes only, not expressions elsewhere in the page so that's why your ${cdata} does not work outside th:text.

I believe (and I have used it successfully in production) that the cleanest way to pass back-end data to javascript in non-ajax way, is to use html5 data attributes. Html5 allows arbitrary attributes prefixed with data- without complaining.

So you can use a container div for example to pass the data like so :

<div id="Some-Container" th:attr="data-someDescription=${cdataJson}"></div>

then if you use jQuery you can retrieve easily all html5 data attributes as jQuery data:

$("#Some-Container").data("someDescription");

If not using jQuery but some other js framework, there is probably some similar way. In plain js you just have to write more code.

Now, in order to export your data as a json formatted text, for being easily consumable by javascript, you have first of all add an object mapper in your application context :

<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" />

declare an dependency in your controller:

@Autowired
private ObjectMapper jsonMapper;

and then, when you add the model attribute, use the object mapper to convert data to json:

String cDataJson = jsonMapper.writeValueAsString(custServe.listAllCustomers());
model.addAttribute("cdataJson", cDataJson);
Sign up to request clarification or add additional context in comments.

1 Comment

I recently figured out a way to get around my initial problem using th:each, but this is really helpful and much better for future coders. Thanks a lot for the advice.
1

If you are not using JSP, you are not going to be able to do string replacement in your HTML or JavaScript to plug the content of cdata into your document. Even if you were using JSP, your object would need a valid toString() method to convert it into readable JSON text. If you want to get your domain data into your web page without using JSP, you will have to fetch it via AJAX. Assuming your customer objects do not have any complex embedded objects, you should be able to serialize them pretty easily and read them into your page as JSON.

Create a new controller method for handling AJAX requests:

@RequestMapping(value = "/customerdata", method = RequestMethod.GET, produces = { "application/json" })
public ResponseEntity<List<Customer>> getCustomerData(){
    List<Customer> customers = custServe.listAllCustomers();
    return new ResponseEntity<>(customers, HttpStatus.OK);
}

Then request the data on your page in your JavaScript:

var cdata;
$.ajax({
   url: "/customerdata",
   dataType: "json",
   method: "get"
}).done(function(data){
    cdata = data;
    //do stuff
});

2 Comments

@rbod If you found a better solution to your problem, you should post an answer yourself, so that other people with the same problem can find it easily.
partial solution posted. What do you think? @willOEM
0

Here is a dynamic dropdown without jquery using spring.

<select name="CustomerList" th:field="*{cdata}">

    <option th:each="task : ${cdata}" th:value="${task}"
        th:text="${task}"></option>

</select>

on the Spring side

    @RequestMapping(value="/managecustomerconfigurations", method=RequestMethod.GET)
    public ModelAndView setUpPage(){
        ModelAndView model = new ModelAndView("customerconfigurations");
        try{
            JSONObject obj = new JSONObject(custServe.listAllCustomers());

            List<Integer> list = new ArrayList<Integer>();

            JSONArray array = obj.getJSONArray("returnObject");
            for(int i = 0 ; i < array.length() ; i++){
                int j = array.getJSONObject(i).getInt("id");
                list.add(j);
            }
            model.addObject("cdata", list);
        }
     return model;
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.