You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@wicket.apache.org by Joel Jabez <jo...@gmail.com> on 2025/06/09 09:06:47 UTC

Fwd: Get help for Apache Wicket User list

Hi so i recently, made some text field with some wrapper around with some
bootstrap class also. Im using this in alot of places, so for that i
created a component for it. Here is the java class and html page

public abstract class FormComponentTextField extends Panel
{
    private final String propertyExpression;
    private final Form<?> form;
    private final Class<?> resourceClazz;
    private final String displayName;

    protected FormComponentTextField(String id, Form<?> form)
    {

        this(id, form, (Class<?>) null);
    }

    protected FormComponentTextField(String id, Form<?> form, String
propertyExpression)
    {

        this(id, form, null, id, propertyExpression);
    }

    protected FormComponentTextField(String id, Form<?> form, Class<?>
resourceClazz)
    {
        this(id, form, resourceClazz, id, id);
    }

    protected FormComponentTextField(String id, Form<?> form, Class<?>
resourceClazz, String displayName, String propertyExpression)
    {
        super(id);
        this.form = form;
        this.resourceClazz = resourceClazz == null ?
this.getClass().getNestHost() : resourceClazz;
        this.displayName = displayName;
        this.propertyExpression = propertyExpression;
        init();
    }

    protected void init()
    {
        add(createTextFieldLabel());
        add(createTextField());
    }

    protected Label createTextFieldLabel()
    {
        Label label = new Label("fieldLabel", getLabel());
        if (isRequiredTextField()) {
            label.add(AttributeModifier.append("class", "mandatory-field"));
        }

        return label;
    }

    protected TextField<String> createTextField()
    {
        TextField<String> textField = isRequiredTextField() ? new
RequiredTextField<>("textField") :
                                              new TextField<>("textField");

        textField.setLabel(getLabel());
        textField.setOutputMarkupId(true);
        textField.add(getMaximumLength());
        textField.setDefaultModel(new
PropertyModel<>(form.getDefaultModel(), propertyExpression));
        getValidators().forEach(textField::add);

        return textField;
    }

    protected boolean isRequiredTextField()
    {
        return false;
    }

    protected Model<String> getLabel()
    {
        return Model.of(getPropertyValue(displayName));
    }

    public String getPropertyValue(String property)
    {
        return StringResourceUtils.getString(resourceClazz, property);
    }

    protected StringValidator getMaximumLength()
    {
        return StringValidator.maximumLength(255);
    }

    protected List<IValidator<String>> getValidators()
    {
        return List.of();
    }
}



<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="
http://wicket.apache.org">
<body>
<wicket:panel>
  <div class="mb-3 row">
    <span class="col-sm-3 col-form-label" wicket:id="fieldLabel"></span>
    <div class="col-sm-9">
      <input class="form-control" type="text" wicket:id="textField"/>
    </div>
  </div>
</wicket:panel>
</body>
</html>


I wanna ask whether this is the best way to do, or is there a better way to
do it

Re: Fwd: Get help for Apache Wicket User list

Posted by andrew goh <go...@yahoo.com.INVALID>.
In fact I shared something a little back about "An Apache Wicket 
reusable Data List":

https://gist.github.com/ag88/a0232510c28b4c45b82943527b7ea87e

I worked that by organizing data into javabeans 
https://en.wikipedia.org/wiki/JavaBeans. e.g. records are classes with 
fields along with getter and setter methods.
And using the BeanInfo class to specify the 'configuration' .

In that way, it is possible to render a list of beans as html tables, 
and to the extent of 'configuring' the rendering using a Beaninfo class.
It is practically, 'generic' for simple tables. e.g. any list of beans 
with a bunch of fields can be displayed as a table using those classes.

I think there are / may be better implementations out there that 
possibly does much more.

On 29/06/2025 02:04, andrew goh wrote:
> I did something similar to this.
>
> I think this works well, especially for Bootstrap( 
> https://getbootstrap.com/ ) based forms.
>
> A trouble with Bootstrap is that form fields are styled with various 
> <div> and <span> around the input fields.
> That makes these fields compound markup elements i.e. a field is 
> practically a structure made up of <div> and <span> constructs in 
> addition to the <input> element itself.
>
> Making Wicket components (Panels) out of them is very useful as it 
> significantly reduce boilerplate (spagetti) HTML codes used in forms 
> and fields, especially with Bootstrap.
>
> I swtiched from Spring-Boot Thymeleaf to Apache Wicket mainly as 
> Thymeleaf (without using 'dialects') evolves to become a huge amount 
> (mess) of spagetti HTML codes
> when forms and tables becomes more complex and larger (e.g. lots of 
> fields).
>
> For the various scripting engines e.g. Thymeleaf - a dialect is 
> needed, and JSP - custom tag libraries is needed, to rework those 
> clusters of html tags around fields etc into components.
>
> while for Apache Wicket, components are built-in and helps very much 
> to reduce those repetitive HTML codes.
>
> On 09/06/2025 17:06, Joel Jabez wrote:
>> Hi so i recently, made some text field with some wrapper around with 
>> some
>> bootstrap class also. Im using this in alot of places, so for that i
>> created a component for it. Here is the java class and html page
>>
>> public abstract class FormComponentTextField extends Panel
>> {
>>      private final String propertyExpression;
>>      private final Form<?> form;
>>      private final Class<?> resourceClazz;
>>      private final String displayName;
>>
>>      protected FormComponentTextField(String id, Form<?> form)
>>      {
>>
>>          this(id, form, (Class<?>) null);
>>      }
>>
>>      protected FormComponentTextField(String id, Form<?> form, String
>> propertyExpression)
>>      {
>>
>>          this(id, form, null, id, propertyExpression);
>>      }
>>
>>      protected FormComponentTextField(String id, Form<?> form, Class<?>
>> resourceClazz)
>>      {
>>          this(id, form, resourceClazz, id, id);
>>      }
>>
>>      protected FormComponentTextField(String id, Form<?> form, Class<?>
>> resourceClazz, String displayName, String propertyExpression)
>>      {
>>          super(id);
>>          this.form = form;
>>          this.resourceClazz = resourceClazz == null ?
>> this.getClass().getNestHost() : resourceClazz;
>>          this.displayName = displayName;
>>          this.propertyExpression = propertyExpression;
>>          init();
>>      }
>>
>>      protected void init()
>>      {
>>          add(createTextFieldLabel());
>>          add(createTextField());
>>      }
>>
>>      protected Label createTextFieldLabel()
>>      {
>>          Label label = new Label("fieldLabel", getLabel());
>>          if (isRequiredTextField()) {
>>              label.add(AttributeModifier.append("class", 
>> "mandatory-field"));
>>          }
>>
>>          return label;
>>      }
>>
>>      protected TextField<String> createTextField()
>>      {
>>          TextField<String> textField = isRequiredTextField() ? new
>> RequiredTextField<>("textField") :
>>                                                new 
>> TextField<>("textField");
>>
>>          textField.setLabel(getLabel());
>>          textField.setOutputMarkupId(true);
>>          textField.add(getMaximumLength());
>>          textField.setDefaultModel(new
>> PropertyModel<>(form.getDefaultModel(), propertyExpression));
>>          getValidators().forEach(textField::add);
>>
>>          return textField;
>>      }
>>
>>      protected boolean isRequiredTextField()
>>      {
>>          return false;
>>      }
>>
>>      protected Model<String> getLabel()
>>      {
>>          return Model.of(getPropertyValue(displayName));
>>      }
>>
>>      public String getPropertyValue(String property)
>>      {
>>          return StringResourceUtils.getString(resourceClazz, property);
>>      }
>>
>>      protected StringValidator getMaximumLength()
>>      {
>>          return StringValidator.maximumLength(255);
>>      }
>>
>>      protected List<IValidator<String>> getValidators()
>>      {
>>          return List.of();
>>      }
>> }
>>
>>
>>
>> <?xml version="1.0" encoding="UTF-8"?>
>> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="
>> http://wicket.apache.org">
>> <body>
>> <wicket:panel>
>>    <div class="mb-3 row">
>>      <span class="col-sm-3 col-form-label" 
>> wicket:id="fieldLabel"></span>
>>      <div class="col-sm-9">
>>        <input class="form-control" type="text" wicket:id="textField"/>
>>      </div>
>>    </div>
>> </wicket:panel>
>> </body>
>> </html>
>>
>>
>> I wanna ask whether this is the best way to do, or is there a better 
>> way to
>> do it
>>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Fwd: Get help for Apache Wicket User list

Posted by andrew goh <go...@yahoo.com.INVALID>.
I did something similar to this.

I think this works well, especially for Bootstrap( 
https://getbootstrap.com/ ) based forms.

A trouble with Bootstrap is that form fields are styled with various 
<div> and <span> around the input fields.
That makes these fields compound markup elements i.e. a field is 
practically a structure made up of <div> and <span> constructs in 
addition to the <input> element itself.

Making Wicket components (Panels) out of them is very useful as it 
significantly reduce boilerplate (spagetti) HTML codes used in forms and 
fields, especially with Bootstrap.

I swtiched from Spring-Boot Thymeleaf to Apache Wicket mainly as 
Thymeleaf (without using 'dialects') evolves to become a huge amount 
(mess) of spagetti HTML codes
when forms and tables becomes more complex and larger (e.g. lots of fields).

For the various scripting engines e.g. Thymeleaf - a dialect is needed, 
and JSP - custom tag libraries is needed, to rework those clusters of 
html tags around fields etc into components.

while for Apache Wicket, components are built-in and helps very much to 
reduce those repetitive HTML codes.

On 09/06/2025 17:06, Joel Jabez wrote:
> Hi so i recently, made some text field with some wrapper around with some
> bootstrap class also. Im using this in alot of places, so for that i
> created a component for it. Here is the java class and html page
>
> public abstract class FormComponentTextField extends Panel
> {
>      private final String propertyExpression;
>      private final Form<?> form;
>      private final Class<?> resourceClazz;
>      private final String displayName;
>
>      protected FormComponentTextField(String id, Form<?> form)
>      {
>
>          this(id, form, (Class<?>) null);
>      }
>
>      protected FormComponentTextField(String id, Form<?> form, String
> propertyExpression)
>      {
>
>          this(id, form, null, id, propertyExpression);
>      }
>
>      protected FormComponentTextField(String id, Form<?> form, Class<?>
> resourceClazz)
>      {
>          this(id, form, resourceClazz, id, id);
>      }
>
>      protected FormComponentTextField(String id, Form<?> form, Class<?>
> resourceClazz, String displayName, String propertyExpression)
>      {
>          super(id);
>          this.form = form;
>          this.resourceClazz = resourceClazz == null ?
> this.getClass().getNestHost() : resourceClazz;
>          this.displayName = displayName;
>          this.propertyExpression = propertyExpression;
>          init();
>      }
>
>      protected void init()
>      {
>          add(createTextFieldLabel());
>          add(createTextField());
>      }
>
>      protected Label createTextFieldLabel()
>      {
>          Label label = new Label("fieldLabel", getLabel());
>          if (isRequiredTextField()) {
>              label.add(AttributeModifier.append("class", "mandatory-field"));
>          }
>
>          return label;
>      }
>
>      protected TextField<String> createTextField()
>      {
>          TextField<String> textField = isRequiredTextField() ? new
> RequiredTextField<>("textField") :
>                                                new TextField<>("textField");
>
>          textField.setLabel(getLabel());
>          textField.setOutputMarkupId(true);
>          textField.add(getMaximumLength());
>          textField.setDefaultModel(new
> PropertyModel<>(form.getDefaultModel(), propertyExpression));
>          getValidators().forEach(textField::add);
>
>          return textField;
>      }
>
>      protected boolean isRequiredTextField()
>      {
>          return false;
>      }
>
>      protected Model<String> getLabel()
>      {
>          return Model.of(getPropertyValue(displayName));
>      }
>
>      public String getPropertyValue(String property)
>      {
>          return StringResourceUtils.getString(resourceClazz, property);
>      }
>
>      protected StringValidator getMaximumLength()
>      {
>          return StringValidator.maximumLength(255);
>      }
>
>      protected List<IValidator<String>> getValidators()
>      {
>          return List.of();
>      }
> }
>
>
>
> <?xml version="1.0" encoding="UTF-8"?>
> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="
> http://wicket.apache.org">
> <body>
> <wicket:panel>
>    <div class="mb-3 row">
>      <span class="col-sm-3 col-form-label" wicket:id="fieldLabel"></span>
>      <div class="col-sm-9">
>        <input class="form-control" type="text" wicket:id="textField"/>
>      </div>
>    </div>
> </wicket:panel>
> </body>
> </html>
>
>
> I wanna ask whether this is the best way to do, or is there a better way to
> do it
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Get help for Apache Wicket User list

Posted by Joel Jabez <jo...@gmail.com>.
Oh i see, thank you so much. Just one more question, if i implement it will
it cause any problems to the FormVisitor?

On Tue, Jun 10, 2025 at 9:48 PM Martijn Dashorst <ma...@gmail.com>
wrote:

> You can take a look at the wicket-bootstrap integration/components project
> for inspiration (or use that).
>
> But I don't have many issues with your code.
>
> I'd probably use TypedPanel (or is it GenericPanel) as a base class, which
> takes the model object's class as a parameter, to make sure the textfield
> uses a type converter for the value. I guess you can switch out the editor
> field based on the type to be a numeric/date/text field or even an enum
> field.
>
> the init method is unnecessary, there is already an 'onInitialize()` method
> you can override and should use.
>
> That's about it.
>
> Martijn
>
>
> On Mon, Jun 9, 2025 at 11:29 AM Joel Jabez <jo...@gmail.com> wrote:
>
> > Hi so i recently, made some text field with some wrapper around with some
> > bootstrap class also. Im using this in alot of places, so for that i
> > created a component for it. Here is the java class and html page
> >
> > public abstract class FormComponentTextField extends Panel
> > {
> >     private final String propertyExpression;
> >     private final Form<?> form;
> >     private final Class<?> resourceClazz;
> >     private final String displayName;
> >
> >     protected FormComponentTextField(String id, Form<?> form)
> >     {
> >
> >         this(id, form, (Class<?>) null);
> >     }
> >
> >     protected FormComponentTextField(String id, Form<?> form, String
> > propertyExpression)
> >     {
> >
> >         this(id, form, null, id, propertyExpression);
> >     }
> >
> >     protected FormComponentTextField(String id, Form<?> form, Class<?>
> > resourceClazz)
> >     {
> >         this(id, form, resourceClazz, id, id);
> >     }
> >
> >     protected FormComponentTextField(String id, Form<?> form, Class<?>
> > resourceClazz, String displayName, String propertyExpression)
> >     {
> >         super(id);
> >         this.form = form;
> >         this.resourceClazz = resourceClazz == null ?
> > this.getClass().getNestHost() : resourceClazz;
> >         this.displayName = displayName;
> >         this.propertyExpression = propertyExpression;
> >         init();
> >     }
> >
> >     protected void init()
> >     {
> >         add(createTextFieldLabel());
> >         add(createTextField());
> >     }
> >
> >     protected Label createTextFieldLabel()
> >     {
> >         Label label = new Label("fieldLabel", getLabel());
> >         if (isRequiredTextField()) {
> >             label.add(AttributeModifier.append("class",
> > "mandatory-field"));
> >         }
> >
> >         return label;
> >     }
> >
> >     protected TextField<String> createTextField()
> >     {
> >         TextField<String> textField = isRequiredTextField() ? new
> > RequiredTextField<>("textField") :
> >                                               new
> TextField<>("textField");
> >
> >         textField.setLabel(getLabel());
> >         textField.setOutputMarkupId(true);
> >         textField.add(getMaximumLength());
> >         textField.setDefaultModel(new
> > PropertyModel<>(form.getDefaultModel(), propertyExpression));
> >         getValidators().forEach(textField::add);
> >
> >         return textField;
> >     }
> >
> >     protected boolean isRequiredTextField()
> >     {
> >         return false;
> >     }
> >
> >     protected Model<String> getLabel()
> >     {
> >         return Model.of(getPropertyValue(displayName));
> >     }
> >
> >     public String getPropertyValue(String property)
> >     {
> >         return StringResourceUtils.getString(resourceClazz, property);
> >     }
> >
> >     protected StringValidator getMaximumLength()
> >     {
> >         return StringValidator.maximumLength(255);
> >     }
> >
> >     protected List<IValidator<String>> getValidators()
> >     {
> >         return List.of();
> >     }
> > }
> >
> >
> >
> > <?xml version="1.0" encoding="UTF-8"?>
> > <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="
> > http://wicket.apache.org">
> > <body>
> > <wicket:panel>
> >   <div class="mb-3 row">
> >     <span class="col-sm-3 col-form-label" wicket:id="fieldLabel"></span>
> >     <div class="col-sm-9">
> >       <input class="form-control" type="text" wicket:id="textField"/>
> >     </div>
> >   </div>
> > </wicket:panel>
> > </body>
> > </html>
> >
> >
> > I wanna ask whether this is the best way to do, or is there a better way
> to
> > do it
> >
>
>
> --
> Become a Wicket expert, learn from the best: http://wicketinaction.com
>

Re: Get help for Apache Wicket User list

Posted by Martijn Dashorst <ma...@gmail.com>.
You can take a look at the wicket-bootstrap integration/components project
for inspiration (or use that).

But I don't have many issues with your code.

I'd probably use TypedPanel (or is it GenericPanel) as a base class, which
takes the model object's class as a parameter, to make sure the textfield
uses a type converter for the value. I guess you can switch out the editor
field based on the type to be a numeric/date/text field or even an enum
field.

the init method is unnecessary, there is already an 'onInitialize()` method
you can override and should use.

That's about it.

Martijn


On Mon, Jun 9, 2025 at 11:29 AM Joel Jabez <jo...@gmail.com> wrote:

> Hi so i recently, made some text field with some wrapper around with some
> bootstrap class also. Im using this in alot of places, so for that i
> created a component for it. Here is the java class and html page
>
> public abstract class FormComponentTextField extends Panel
> {
>     private final String propertyExpression;
>     private final Form<?> form;
>     private final Class<?> resourceClazz;
>     private final String displayName;
>
>     protected FormComponentTextField(String id, Form<?> form)
>     {
>
>         this(id, form, (Class<?>) null);
>     }
>
>     protected FormComponentTextField(String id, Form<?> form, String
> propertyExpression)
>     {
>
>         this(id, form, null, id, propertyExpression);
>     }
>
>     protected FormComponentTextField(String id, Form<?> form, Class<?>
> resourceClazz)
>     {
>         this(id, form, resourceClazz, id, id);
>     }
>
>     protected FormComponentTextField(String id, Form<?> form, Class<?>
> resourceClazz, String displayName, String propertyExpression)
>     {
>         super(id);
>         this.form = form;
>         this.resourceClazz = resourceClazz == null ?
> this.getClass().getNestHost() : resourceClazz;
>         this.displayName = displayName;
>         this.propertyExpression = propertyExpression;
>         init();
>     }
>
>     protected void init()
>     {
>         add(createTextFieldLabel());
>         add(createTextField());
>     }
>
>     protected Label createTextFieldLabel()
>     {
>         Label label = new Label("fieldLabel", getLabel());
>         if (isRequiredTextField()) {
>             label.add(AttributeModifier.append("class",
> "mandatory-field"));
>         }
>
>         return label;
>     }
>
>     protected TextField<String> createTextField()
>     {
>         TextField<String> textField = isRequiredTextField() ? new
> RequiredTextField<>("textField") :
>                                               new TextField<>("textField");
>
>         textField.setLabel(getLabel());
>         textField.setOutputMarkupId(true);
>         textField.add(getMaximumLength());
>         textField.setDefaultModel(new
> PropertyModel<>(form.getDefaultModel(), propertyExpression));
>         getValidators().forEach(textField::add);
>
>         return textField;
>     }
>
>     protected boolean isRequiredTextField()
>     {
>         return false;
>     }
>
>     protected Model<String> getLabel()
>     {
>         return Model.of(getPropertyValue(displayName));
>     }
>
>     public String getPropertyValue(String property)
>     {
>         return StringResourceUtils.getString(resourceClazz, property);
>     }
>
>     protected StringValidator getMaximumLength()
>     {
>         return StringValidator.maximumLength(255);
>     }
>
>     protected List<IValidator<String>> getValidators()
>     {
>         return List.of();
>     }
> }
>
>
>
> <?xml version="1.0" encoding="UTF-8"?>
> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="
> http://wicket.apache.org">
> <body>
> <wicket:panel>
>   <div class="mb-3 row">
>     <span class="col-sm-3 col-form-label" wicket:id="fieldLabel"></span>
>     <div class="col-sm-9">
>       <input class="form-control" type="text" wicket:id="textField"/>
>     </div>
>   </div>
> </wicket:panel>
> </body>
> </html>
>
>
> I wanna ask whether this is the best way to do, or is there a better way to
> do it
>


-- 
Become a Wicket expert, learn from the best: http://wicketinaction.com