Search code examples
playframeworkplayframework-2.4twirl

How to add composite view like HashMap to twirl in playframework 2.4.x


I want to add a HashMap Object contains many different object(s) to the twirl template, because I do not like adding one by one as parameter to the twirl, it breaks the rule with design patterns.

the normal style:

views.html.index.render(object1, object2, list3, list4, ...);

@(object1:Object1Model, object2:Object2Model, list3: List[Object3Model], list4: List[Object4Model]) 

Is there any solution to set and get parameters like this?

Map data = new HashMap();
data.put("object1", object1);
data.put("object2", object2);
data.put("list3", list3);
data.put("list4", list4);
views.html.index.render(data);

How to get and define the objects in HashMap in twirl, the official twirl document is too simple...

@(data:Map) 
Object1Model object1 = (Object1Model) data.get("object1");
Object2Model object2 = (Object2Model) data.get("object2");
List list3 = (List) data.get("list3");
List list4 = (List) data.get("list4");

Many thanks!


Solution

  • For type-safety you can create a dedicated class with fields of required types, the additional benefit is that sophisticated IDEs will recognize types of the fields and/or autocomplete field names, so it help you to prevent mistakes in the views.

    Of course as in each class you can also use the benefits of constructor and/or getters/setters.

    (pseudo code):

    package viewhelpers;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class SomeViewHelper {
    
        public String header;
        public List<String> labels = new ArrayList<>();
        public List<Integer> values = new ArrayList<>();
    
    }
    

    Fill it in controller somehow:

    public static Result incomes() {
        SomeViewHelper data = new SomeViewHelper();
        data.header = "Incomes in first quarter";
        data.labels = Arrays.asList("Jan", "Feb", "Mar");
        data.values = Arrays.asList(121, 122, 123);
        return ok(views.html.incomes.render(data));
    }
    

    and use in the view like:

    @(data: viewhelpers.SomeViewHelper)
    
    <h1>@data.header</h1>
    <table>
        <tr>
            @for(label <- data.labels) {
                <th>@label</th>
            }
        </tr>
        <tr>
            @for(value <- data.values) {
                <td>@value</td>
            }
        </tr>
    </table>