xmlet/HtmlFlow

Multiple model with single template

benzen opened this issue · 3 comments

benzen commented

In a template, if I need to use two distinct object to build my view, am i requried to build a new object to pass only one parameter to the render function ?

If so, this is something that need to be clarified in the documentation, otherwhise we have a bug

                    .form().attrMethod(EnumMethodType.GET).attrAction("/produits").attrClass("ui form")
                      .select().attrClass("ui clearable dropdown").attrName("bois")
                        .option().attrValue("")
                            .text("Type de bois")
                          .__()
                        .of(select ->
                          Stream.of(Bois.values()).forEach(b -> select
                            .option().attrValue(b.toString())
                            .<ProduitSearchForm>dynamic((option, form) -> option
                               .attrSelected(form.bois().equals(b))
                            )
                              .text(b)
                            .__()
                          )
                        )
                      .__()
                    .__()
....
.tbody()
                        .<Set<Produit>>dynamic((tbody, produits)->
                          produits.stream().forEach(produit -> tbody
                            .tr() 
                              .td().text(produit.bois()).__()
                              .td().text(produit.largeur()).__()
                              .td().text(produit.hauteur()).__()
                              .td().text(produit.creation()).__()
                              .td().text(produit.etat()).__()
                            .__() //tr
                          )
                        )
                    .__() //tbody

In this example, Im trying to use form and produits in the same template.

I'm trying to make a giga template, that will be the complete page, maybe that's the source of my problem. It's the way i'm used to work with Thymleaf, but maybe by decomposing , this will be easier

Yes, your are required to build a new object to pass only one parameter to the render() method of an HtmlView.

And you should not do things like Bois.values() in template of an HtmlView. Bois.values() should be part of your model and passed to the render()

Alternatively, you may use HtmlDoc rather than an HtmlView.

  • HtmlDoc is simpler but not so performant, since the entire template will be processed every time you produce the output.
  • On the other hand, an HtmlView internally store the static parts that are resolve only once.

However for most use cases, diferences in template performance should be insignificant and overwhelmed by IO which is orders of magnitude higher than template processing.

To use HtmlDoc in your case you may have something like:

static void docProduits(Appendable out, ProduitSearchForm form, Set<Produit> produits) {
  HtmlFlow
    .doc(out)
         ....
        .form().attrMethod(EnumMethodType.GET)
                .table()
                .tbody()
                .of((tbody)->
                        produits.stream().forEach(produit -> tbody
                                .tr()
                                .td().text(produit.bois()).__()
                             

}

NOTICE:

  • your model are the function arguments.
  • Do not use dynamic() in HtmlDoc. Use of() everywhere.

You may render it to System.out or StringBuidler or any kind of Appendable.

benzen commented

In this instance Bois is an enum, so while the app is running, there is no chance that this part of the template to be modified. That's why I opted for using .of()

But anyway, thanks for the quick response on model.
Since i'm using a recent version of java, this will be a nice place to use record.

benzen commented

Closing