xmlet/HtmlFlow

option.attrSelected unexpected behavior

benzen opened this issue · 7 comments

benzen commented

when using

option
                               .attrSelected( /*some logic returning true or false*/

Ouput might look like this
Capture d’écran, le 2023-10-20 à 00 17 03

Which seems fine except, that since selected is a boolean attr, it means that in this exemple every option is selected.
In my opinion it would have been nicer if attrSelected would have not produce anything if the value passed as argument is falsy

benzen commented

Here is my way out

                            .<ProduitListModel>dynamic((option, model) -> {
                              if(model.form().bois().equals(b)) {
                                 option.attrSelected(true);
                              }
                            }
                            )

Uggly but it get's the expected (by me) behavior :)

Your issue is related and with same behaviour of #89. And the constrain here is the aforementioned:

HtmlFlow API is automatically generated through an ASM pre processor included in our project XsdAsmFaster that generates the API from a XSD file with the HTML 5 specification.

Although I totally agree with you that "would have been nicer if attrSelected would have not produce anything if the value passed as argument is falsy". However we cannot easily add new extensions with the desired behaviour that you described.

So your workaround is the right alternative here.

When Java provides extension functions it would be easy to build an auxiliary function wrapping that logic and using it smoothly in an HtmlFlow template.

benzen commented

Maybe the api is auto generator, but couldn't we introduce specific behavior later in the chain ?

Quiclly I've found this https://github.com/xmlet/HtmlFlow/blob/master/src/main/java/htmlflow/visitor/HtmlVisitor.java#L176-L178 which seems to be the place to produce the output.

Seems like a good place for the selected attribute specific behavior. Every boolean attribute could have a specific behavior inproduce this way. Doesn't it ?

Maybe, that's a good place.

And, is that the expected behaviour for every HTML boolean attribute set to false?

Can we suppress the emission of any boolean attribute that is false? Would be this safe?

@Override
public final void visitAttribute(String attributeName, String attributeValue) {
    if(!attributeValue.equals(false))
        addAttribute(out, attributeName, attributeValue);
}

Or it should be even more like:

@Override
public final void visitAttribute(String attributeName, String attributeValue) {
    if((attributeName.equals("checked") || attributeName.equals("selected")) && !attributeValue.equals(false))
        addAttribute(out, attributeName, attributeValue);
}

I don't like the latter.

benzen commented

Well, an attriute only need to be present.
But to help out older browser, I think most template engine does is producing a value that match the attribute name.

I think in our case the following should be enough:

@Override
public final void visitAttribute(String attributeName, String attributeValue) {
    if(attributeValue.equals("true"))
        addAttribute(out, attributeName, attributeName);
}

But the trick is to document how this works
https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#fixed-value-boolean-attributes

REF:
https://developer.mozilla.org/en-US/docs/Glossary/Boolean/HTML

visitAttribute is called for all kind of attributes, and not only boolean attributes.

Thus, we can only jump over the call to addAttribute for boolean attributes.

Version 4.1 released and solve this issue.