1

I would like to have multiple Instances of a PropertyBean (consists of property,value,datatype) to describe a document. So in the Thymeleaf Frontend (with Spring backend) a document should be displayed as a table, with a list of such PropertyBean-Instances. The "value" String of each instance should be in a an input field, enabled to be modified. (Later also the others, but i thought it would be a good idea to start small.

This is what i have:

package beans;

public class PropertyBean {
    private String property;
    private String value;
    private String datatype;

    public PropertyBean() {
    }

    public PropertyBean(String property, String value, String datatype) {
        super();
        this.property = property;
        this.value = value;
        this.datatype = datatype;
    }

    public String getProperty() {
        return property;
    }
    public void setProperty(String property) {
        this.property = property;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public String getDatatype() {
        return datatype;
    }
    public void setDatatype(String datatype) {
        this.datatype = datatype;
    }

    @Override
    public String toString() {
        return "property = "+this.property+",value = "+this.value+", datatype = "+this.datatype;
    }

}

The PropertyWrapper class (used as a Wrapper for Thymeleaf):

package beans;

import java.util.ArrayList;

public class PropertyWrapper {
    private ArrayList<PropertyBean> properties;

    public PropertyWrapper() {};

    public ArrayList<PropertyBean> getProperties() {
        if (this.properties == null) {
            this.properties = new ArrayList<PropertyBean>();
        }
        return properties;
    }

    public void setProperties(ArrayList<PropertyBean> properties) {
        this.properties = properties;
    }

    public void newProperty(String property, String value, String datatype) {
        PropertyBean newPr = new PropertyBean(property,value,datatype);
        this.getProperties().add(newPr);
    }

    public void printAll() {
        for (PropertyBean p : getProperties()) {
            System.out.println(p.toString());
        }
    }
} 

This the important part of the Spring document-controller:

/******************************************************
 * POST of one specific document
 ******************************************************/
@PostMapping("documents/{doc_id}")
public String editDocument(@PathVariable String doc_id,
        @ModelAttribute("properties_wrapper") PropertyWrapper propertiesWrapper, Model model) {

    //Just print the values
    propertiesWrapper.printAll();

    saveInDatabase(propertiesWrapper);

    Message info_msg = new Message("Changes successuflly saved!", "alert-success");
    return document(doc_id, model, info_msg);
}

/******************************************************
 * GET of one specific document
 ******************************************************/
@RequestMapping(path = "documents/{doc_id}", method = RequestMethod.GET)
public String document(@PathVariable String doc_id, Model model, Message msg) {

    PropertyWrapper prwrapper = loadFromDatabase(doc_id);

    if (msg != null) {
        model.addAttribute("msg", msg);
    }

    model.addAttribute("doc_id", doc_id);
    model.addAttribute("properties_wrapper", prwrapper);

    return "documentTmpl";
}

And here is the form-part of the thymeleaf template:

<form action="#" method="post" th:action="@{/documents/{id}(id=${doc_id})}" th:object="${properties_wrapper}">
    <h1 th:text="${doc_id}">Document</h1>
    <table class="table table-striped">
        <tr>
            <th>Property</th>
            <th>Value</th>
            <th>Datatype</th>
        </tr>
        <tr th:each="propertyItem,status : ${properties_wrapper.properties}">
            <td th:text="${propertyItem.property}">Property</td>
            <td>
                <!-- here the problem occurs: -->
                <input th:field="*${properties_wrapper.properties[__${status.index}__].value}"></input>
            </td>
            <td th:text="${propertyItem.datatype}"> </td>
        </tr>
    </table>
    <button type="submit" class="btn btn-default">Submit</button>
</form>

As you can see in the comment, i don't know how or even if it is possible to access the properties_wrapper.

The present version leads to an Exception, when i call the get-Method:

org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: "*${properties_wrapper.properties[__${status.index}__].value}" (documentTmpl:26)

I also tried the short form, i.e. instead of <input th:field="*${properties_wrapper.properties[__${status.index}__].value}"></input> i also tried <input th:field="*${propertyItem.value}"></input> but with the same effect.

Without this input-tag, all is displayed properly in the get-call

Sangram Badi
  • 4,054
  • 9
  • 45
  • 78
MS1
  • 508
  • 9
  • 23

1 Answers1

2

There is no *${} expression in the Spring Standard Dialect for Thymeleaf. However you can use the following five expressions 1 (Ref: http://www.thymeleaf.org/doc/articles/standarddialect5minutes.html):

  • ${...} : Variable expressions. These are Spring EL expressions.

  • *{...} : Selection expressions. Same as above, excepted it will be executed on a previously selected object only. (The object set by th:object)

  • #{...} : Message (i18n) expressions. Used to retrieve locale-specific messages from external sources.

  • @{...} : Link (URL) expressions. Used to build URLs.
  • ~{...} : Fragment expressions. Represent fragments of markup and move them around templates.

Answer

This line:

<input th:field="*${properties_wrapper.properties[__${status.index}__].value}"></input>

should actually be:

<input th:field="*{properties[__${status.index}__].value}"/>.

1 - taken from Thymeleaf - What is the difference between th:field="${}" and th:field="*{}"?

Community
  • 1
  • 1
Tommy Schmidt
  • 1,224
  • 1
  • 16
  • 30