vaadin / flow

Vaadin Flow is a Java framework binding Vaadin web components to Java. This is part of Vaadin 10+.
Apache License 2.0
598 stars 165 forks source link

Fluent HTML component API? #486

Open Legioth opened 8 years ago

Legioth commented 8 years ago

We should evaluate whether the benefits of a fluid api for the HTML components would outweigh the inconsistencies caused by overriding.

denis-anisimov commented 8 years ago

The test added to #555 shows that there will be no way to implement fluent API for components "correctly" (make component parameterized so that setters return parameter type not current one). So

public class Div<D extends Div> extends HtmlComponent {

   public D setWhatever(){
   }
}

won't work.

So it's better to use Builders instead.

macjuan commented 8 years ago

Added to the backlog

Legioth commented 8 years ago

Affects #495 and #494

svenruppert commented 5 years ago

There is a way to add a Fluent API, completely out of the inheritance. The same could be used to add a DSL for Kotlin later ( additionally dependency). I created the solution and it looks like the following...

  private final VerticalLayout layout = new VerticalLayoutBuilder(VerticalLayout::new)
      .setDefaultHorizontalComponentAlignment(Alignment.START)
      .setSizeUndefined()
      .add(new HorizontalLayout(username , password))
      .add(rememberMe)
      .add(new HorizontalLayout(btnLogin , btnCancel))
      .build();
private final Button btnCancel = new ButtonBuilder(Button::new)
      .setId(BTN_CANCEL_ID)
      .addClickListener(e -> clearFields())
      .setText(getTranslation(BTN_CANCEL_CAPTION))
      .setVisible(true)
      .build();
pleku commented 5 years ago

Thanks for the effort @svenruppert ! but personally, I would hate having to write the following to instantiate something

new VerticalLayoutBuilder(VerticalLayout::new)

and I would never use this. There needs to be a simpler way. (less is more)

And as someone commented on our Slack, this would be a good thing to pitch as an add-on. IMO not part of @mstahv's Viritin, but something separate so that it would be possible to see how many people opt to use it. Viritin has bunch of other stuff too that make it harder to see what features should be promoted as official framework features.

svenruppert commented 5 years ago

ok

Legioth commented 5 years ago

A builder API could be made in a way that typically doesn't require the new VerticalLayoutBuilder(VerticalLayout::new) step, even though it would be kept there for the really advanced cases. Instead, there could be static builder factory methods in the class itself. In that way, the examples could be changed to look like this:

private final Button btnCancel = Button.builder(getTranslation(BTN_CANCEL_CAPTION))
      .setId(BTN_CANCEL_ID)
      .addClickListener(e -> clearFields())
      .setVisible(true)
      .build();

 private final VerticalLayout layout = VerticalLayout.builder()
      .setDefaultHorizontalComponentAlignment(Alignment.START)
      .setSizeUndefined()
      .add(new HorizontalLayout(username , password))
      .add(rememberMe)
      .add(new HorizontalLayout(btnLogin , btnCancel))
      .build();

The biggest challenge in any way is that we would have to ensure the builder classes are always in sync with the actual components. It might be possible to use some kind of code generation library for automating this, but I'm not too familiar with such things.

svenruppert commented 5 years ago

Sure, the solution from me was assuming that there is no change in the existing framework and to support extended Components.

svenruppert commented 5 years ago

To keep them in sync, I started working on an AnnotationProcessor. It is not too difficult.. With this approach, we could add support for custom components as well. (maybe a Pro)

jhult commented 4 years ago

Just leaving this here as a plug for a great existing Kotlin DSL for Vaadin: