HtmlFlow icon indicating copy to clipboard operation
HtmlFlow copied to clipboard

View with dynamic and static attribute / Placement of dynamic() block

Open shimikano opened this issue 2 years ago • 6 comments

The following test creates a view, adds an attribute to a div() in a dynamic() block, and then adds a static attribute.

  @Test
  public void dynamicAttribute() {
    var view = HtmlFlow.view(page -> {
      page
        .div()
          .<String>dynamic((div, model) ->
            div.addAttr("dynamic-attribute", model)
          )
          .addAttr("static-attribute", "world")
        .__();
    });

    var actual = view.render("hello");

    var expected = """
      <div dynamic-attribute="hello" static-attribute="world">
      </div>""";

    assertEquals(expected, actual);
  }

The rendered string is:

<div dynamic-attribute="hello">
static-attribute="world"
</div>

As opposed to the expected:

<div dynamic-attribute="hello" static-attribute="world">
</div>

If I move the static-attribute line into the dynamic() block, the test passes.

So I wonder if this is a bug or if dynamic() is not supposed to be used like this.

Using HtmlFlow 4.1.

shimikano avatar Dec 07 '23 22:12 shimikano

That is an issue that we were not able to solve.

In that kind of HtmlFlow view we are evaluating the static blocks before-hand without running the continuations of dynamic blocks. Thus, we have no way to know whether a dynamic block is closing (i.e. <div>) or leaving the tag opened (i.e. <div). We had to take a decision, and we assumed that is better to presume that a dynamic block always kept the tags closed.

That’s the reason of that behavior observed on your test.

Since, we do not have immediate solution for this we suggest that you move your static attribute into the dynamic block as you proposed in your work-around.

There will not be any significant overhead of processing a further attribute in dynamic.

Thank you

fmcarvalho avatar Dec 08 '23 10:12 fmcarvalho

Dear Fernando

I understand, thank you very much for your swift reply and explanation.

Best regards

shimikano avatar Dec 11 '23 09:12 shimikano

Sure thing, I'm happy to do so.

Off-topic, but I'm experimenting with HtmlFlow as a replacement for Thymeleaf. So far I'm happy with the reduced complexity and not having to deal with limitations of the external Thymeleaf DSL. For example, adding the CSRF token to the view? - Just do it yourself in Java (or Kotlin) instead of having to rely on Thymeleaf-provided magic (${_csrf.token}). This is quite liberating. The better performance is also a big plus, of course.

Disadvantages are the poorer readability compared to HTML-like templates, the inability to easily copy-paste existing HTML into your templates (sure, Flowifier may help, but it's an extra step), and the poor formatting/indenting support of IDEs (cf. #91). For the latter, Kotlin extension functions help BTW.

I'll report on further findings later on.

shimikano avatar Dec 13 '23 13:12 shimikano

I have developed a rudimentary plugin that serves its purpose, but it hasn't been submitted to the IntelliJ Marketplace. You'll need to manually install the plugin JAR file. I hope it proves useful to everyone. @shimikano https://github.com/changchengqin/indent-folder

changchengqin avatar Apr 03 '24 02:04 changchengqin

Thank you @changchengqin.

I'm using Kotlin extension functions to create a mini DSL with proper scoping using the language-level blocks ({ and }), e.g.:

htmlFlowDoc {
  table {
    thead {
      tr {
        th { t("Sample th 1") }
        th { t("Sample th 2") }
      }
    }
    tbody {
      tr {
        td { t("Sample td 1") }
        td { t("Sample td 2") }
      }
    }
  }
}

This has helped a lot when authoring HtmlFlow templates.

shimikano avatar Apr 05 '24 14:04 shimikano

Just to let you know that we have just released HtmlFlow 4.6 with full compatible API for Kotlin builder with function literals with receivers that are fully compatible with the already exiting Java API. In truth you can mixed both.

All examples are updated here https://htmlflow.org/features and snippets include a tab for Kotlin. Now you can write as bellow:

System.out.doc {
  html {
    head {
      title { text("HtmlFlow") }
    }
    body  {
      div {
        attrClass("container")
        h1 { text("My first HtmlFlow page") }
        img { attrSrc("http://bit.ly/2MoHwrU") }
        p { text("Typesafe is awesome! :-)") }
      }
    }// body
  } //html
} // doc

fmcarvalho avatar May 21 '24 17:05 fmcarvalho