xmlet/HtmlFlow

Possible to create component or fragment or partial (customised Element) with any parent?

kask-service opened this issue · 3 comments

I am trying to create a system of reusable components, example button component:

public class ButtonExtended {
  public static Void content(Div<?> view, final ButtonExtendedOptions options) {
    view
      .a()
         .attrClass(CSS.BUTTON + CSS.BUTTON_IMAGE_EXT)
         .attrHref(options.getHref())
         .text(options.getText())
      .__(); // a
      return null;
  }
}

One issue is that this component must have a div as a parent.

Example use case (also second question does this approach still take advantage of static HTML blocks? - HtmlView instantiation)

public static final ButtonExtendedOptions btnOption = ButtonExtendedOptions.of("text", "/link");
---
.div().of(o -> ButtonExtended.content(o, btnOption)).__()

======
Attempted solutions
I tried Element as it a parent of Div but looks like it's not supposed to be used on own

public static Void content(Element<?, ?> view, final ButtonExtendedOptions options) {

also tried

public static Void content(HtmlView view, final ButtonExtendedOptions options) {

but only div and tr and html are allowed as children.
Is there a way to make a component that can have any parent rather than copying the implementation for each parent type?

Yes, you can.

You just may instantiate any of the available elements from the org.xmlet.htmlapifaster package and it works with both static (HtmlDoc) or dynamic (HtmlView) pages.

It is only required a parent Element to get its element visitor responsible for emitting the output.

Here is the revised version of your content function (I don't know if is that a requirement but I replaced Void by void. You may exchange it again if you wish):

static void content(Element<?,?> parent, final ButtonExtendedOptions options) {
    new A<>(parent)
            .attrClass(CSS.BUTTON + CSS.BUTTON_IMAGE_EXT)
            .attrHref(options.getHref())
            .text(options.getText())
            .__(); // a
}

Now you may use that content in a Dynamic view like the next one. You can replace section by any other kind of block Element:

HtmlView<Object> view = HtmlFlow.view(v -> v
        .html()
          .body()
            .div()
              .section()
                .of(section -> content(section, new ButtonExtendedOptions()))
              .__() // section
            .__() // div
          .__() // body
        .__() // html
    );
view.setOut(System.out).write();

Also you may use it in a static page:

HtmlFlow.doc(System.out)
        .html()
          .body()
            .div()
              .section()
                .of(section -> content(section, new ButtonExtendedOptions()))
              .__() // section
            .__() // div
          .__() // body
        .__(); // html

@kask-service does it solve this issue?

Yes that solved the issue, thank you for your help!