Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to create a custom tag/element? #80

Closed
iyerha opened this issue Jan 7, 2022 · 9 comments
Closed

How to create a custom tag/element? #80

iyerha opened this issue Jan 7, 2022 · 9 comments

Comments

@iyerha
Copy link

iyerha commented Jan 7, 2022

I am evaluating htmlFlow for our project. We are using web components and don't see how custom elements are supported. I see that kotlinx.html has support for the same and I am hoping that htmlFlow has an equivalent feature.

@fmcarvalho
Copy link
Member

No, we do not have support for custom Elements yet. It is a nice feature and I would like to include it in HtmlFlow DSL. We will have to discuss the best way to do it. But I think that we should place some effort to develop it soon. We will analyze it an then I will give a estimated date here soon.

It would be useful if you could provide your use cases on custom elements use.

Regarding HTML fragments/partials support and reuse, we can already do it in HtmlFlow in an unopinionated manner. There is some lack of details in documentation but there is a high level idea here about that: https://htmlflow.org/features/#partial-and-layout.

@fmcarvalho
Copy link
Member

fmcarvalho commented Jan 13, 2022

@iyerha we may have 2 options:

  1. Simplest - Similar to existing .of(elem -> ....) that let us chain control flow over the last created element. We may introduce a custom(<custom tag>, elem ->... ) to let us include a custom element. And, then in the lambda we could add any kind of attributes over that element. In this case, the definition of the custom element itself would be on charge of the programmer that should provide the JavaScript code, e.g. custom.js, and link it to the HtmlFlow document through the script tag, i.e. ....head().script().attrSrc('custom.js')

  2. Harder - Beyond solution 1) we could include an additional DSL to define the custom element itself, where we could take advantage of HtmlFlow to write the HTML of that custom element. But what should be the resulting output? 2 files: html and js? And if we are streaming?

Is this a realistic use of custom elements and an example of the desired output?
custom-elements

@iyerha
Copy link
Author

iyerha commented Jan 13, 2022

That is the typical usage. Solution 1 looks good enough. On a separate note, we also use custom data attributes in regular html.

@fmcarvalho
Copy link
Member

@iyerha What kind of content can we find inside a custom element? Always empty? Text? Text or other custom element? Or text or any kind of other elements?

Is this a valid example?

<my-custom-element>
   <ul>
      <li>...</li>
       ...
   </ul>
</my-custom-element>

@iyerha
Copy link
Author

iyerha commented Jan 14, 2022

All of the above. That is a valid example.

@fmcarvalho
Copy link
Member

@lcduarte With the new custom element feature we should be able to define HtmlFlow views such as the listing at the end of this comment (this feature applies regardless being a static or a dynamic view).

I think that invoking .custom("alert-info") should return an instance of a new class CustomElement that inherits from existing Div class. Hence, we will have most HTML features available at the resulting instance.

Moreover, that class CustomElement should store the custom tag (e.g. alert-info) in some way that will be accessible to the HtmlVisitor, which is responsible for printing <alert-info>. NOTICE that currently the resulting HTML tag is printed through:

@Override
public final void visitElement(Element element) {
    newlineAndIndent();
    if (isWriting()){
        beginTag(element.getName()); // "<elementName"
        isClosed = false;
    }
}

So, the getName() in the new class CustomElement should return the same String passed to .custom(<String>), e.g. alert-info.

HtmlView viewWithCustomElements() {
    return StaticHtml
        .view()
            .html()
                .head()
                    .script()
                        .attrSrc("alert.js") // Link to alert-info definition
                        .attrDefer(true)
                    .__()
                .__()
                .body()
                    .div()
                        .attrClass("container")
                        .p().text("Testing custom elements!").__()
                        .custom("alert-info") // alert-info should be stored in the new Element and accessible to the Visitor.
                            .addAttr("title", "Information")
                            .addAttr("message", "This is a message for a custom element")
                            .addAttr("kind", "success")
                            .ul()
                                .li().text("For any reason we could even include other elements.").__()
                            .__() // ul
                        .__() // alert-info
                    .__() // div
                .__() // body
            .__(); //html
}

@lcduarte
Copy link
Member

Hello,

This change looks doable, I'll investigate it further on the weekend and I'll prepare the changes needed.

@lcduarte
Copy link
Member

Hi,

I've made the required changes on our related projects and I've added a new test in the development branch to validate the example provided above.

@fmcarvalho
Copy link
Member

@iyerha Just released HtmlFlow 3.9 with support for custom elements as announced here: https://htmlflow.org/2022/01/30/Release-3.9/

I will wait a few days and if there is no more updates on this issue I will close it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants