Table of contents
1.
📄Introduction
2.
What is A Component That Has Value ❓
3.
📌The HasValue interface 
4.
📌Helper Classes
5.
💡Using a Single-element Property as the Value
5.1.
Explanation
6.
💡Combining Properties Into One Value
7.
💡Creating Fields from Other Fields
8.
Frequently Asked Questions ❓
8.1.
Are the type parameters for AbstractSinglePropertyField and AbstractField the same?
8.2.
Can AbstractField determine whether a new value is the same as the previous one?
8.3.
When should AbstractField ideally be used?
8.4.
When we use AbstractField what are the two values that we must deal with?
9.
📌Conclusion
Last Updated: Mar 27, 2024
Medium

Creating a Component That Has Value

Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

📄Introduction

We know that Vaadin is a Component based framework used for developing Java based web apps, so whatever we will work within vaadin in terms of UI will be termed as a component. A buttoncheckbox, and text field are some examples of Components. 

In this blog, we will discuss creating a component that has value(field component) so let us begin by understanding what we mean by a Component having a value.

 

Field Components CN

What is A Component That Has Value ❓

A field component's primary feature is that it has a value that the user may change. A field must implement the 'HasValue' interface to communicate this. This interface is required for a component to function with 'Binder'(A class that allows you to specify how data in a business entity is tied to UI fields).

These are the Field Components

📌The HasValue interface 

It is a general interface for UI elements with user-editable values, such as field components. It emits change events whenever the value changes, whether a user or a program makes the change. 

It defines:

  • Various methods like getValue(), which returns the object's current value, and setReadOnly(), which sets the value of the current object to read-only.
     
  • An event which fires when the value changes and a listener for the value change the event.

📌Helper Classes

Helper classes serve as a base class for custom fields. The helper classes below serve as a base class for creating custom components that show values and let users modify them. They are of three types, all used in different scenarios.

  1. AbstractSinglePropertyField: An abstract field with a single element attribute. It is appropriate when the value is a property of the Component's sole element. 
     
  2. AbstractField: It is the most fundamental but also the most adaptable base class. There are numerous aspects to consider, yet it allows sophisticated use cases.
     
  3. AbstractCompositeField: It is identical to AbstractField, except that the base class is Composite rather than Component. It is appropriate when the value input component comprises numerous separate components.

 

Now that we have learned about the various helper classes let us discuss how we can create a component with a value using these.

💡Using a Single-element Property as the Value

The first way to create a component that has value is using single element property as value. Many components extend web components, which provide a property that holds the Component's value. When the value of property changes, it triggers a value-changed event. 

When the property type is a string, integer, or Boolean, we extend AbstractSinglePropertyField and call its constructor with the name of the field, the default value, and whether or not it supports null values.

Consider the following PaperSlider component, which implements AbstractSinglePropertyField:

@Tag("paper-slider")
@NpmPackage(value = "@polymer/paper-slider", version = "3.0.1")
@JsModule("@polymer/paper-slider/paper-slider.js")
public class PaperSlider extends AbstractSinglePropertyField<PaperSlider, Integer> 
{
    public PaperSlider() 
    {
        super("value", 0, false);
    }
}
You can also try this code with Online Java Compiler
Run Code

 

Explanation

  • AbstractSinglePropertyField's type parameters are: The type of the getSource() function in value-change events that have been triggered (PaperSlider).The kind of value (Integer).
  • The clear() and isEmpty() functions utilise the default value of 0 by default. clear() returns true if the field value is empty, and isEmpty() returns true if the field value is empty.

 

Some Web Components have a Java type that is more appropriate than the type of the element attribute.

When modifying, reading, or writing the value to the element property, AbstractSinglePropertyField can use a converter.

The value attribute of < input type=" date ">, for example, is an ISO 8601-formatted string (YYYY-MM-DD). To choose a LocalDate, we may transform this into a DatePicker component.

💡Combining Properties Into One Value

In other circumstances, a component's value might be a combination of characteristics from one or more parts. In such circumstances, extending AbstractField is frequently the best answer.

When we extend AbstractField, we must deal with two value representations:

  1. Presentation Value: The value shown to the user in the browser, such as element properties.
     
  2. Model Value: The value returned by the getValue() function.

 

Let us look at one example:

Begin by creating a DatePicker component that extends AbstractField and takes the default value as a parameter to its constructor.

@Tag("date-picker") 
public class DatePicker extends AbstractField<DatePicker, LocalDate> 
{   
	public DatePicker() 
	{  
		super(null);  
	} 
}
You can also try this code with Online Java Compiler
Run Code

 

Now when we call the setValue method with a new value, AbstractField calls the setPresentationValue method with the new value, so we must implement the setPresentationValue:

 

@Override 
protected void setPresentationValue(LocalDate val) 
{  
	Element e = getElement();   
	if (val == null) 
	{  
		e.removeProperty("year");  
		e.removeProperty("month");  
		e.removeProperty("dayOfMonth");  
	} 
	else 
	{  
		e.setProperty("year", val.getYear());  
		e.setProperty("month",  val.getMonthValue());  
		e.setProperty("dayOfMonth",  val.getDayOfMonth());  
	} 
}
You can also try this code with Online Java Compiler
Run Code

 

To handle browser-generated value changes, the Component must listen for suitable internal events and send a new value to the setModelValue(T value, boolean fromClient) function. AbstractField checks this to see if the specified value has changed and, if so, fires a value-change event to all listeners.

We must alter the constructor to declare each of the element's properties as synchronized and must add the identical property-change listener to each of them:

 

public DatePicker()
{  
	super(null);   
	setupProperty("year", "year-changed");  
	setupProperty("month", "month-changed");  
	setupProperty("dayOfMonth", "dayOfMonth-changed"); 
}  
private void setupProperty(String name, String event) 
{  
	Element e = getElement();   
	e.addPropertyChangeListener(name, event,this::propertyUpdated); 
}
You can also try this code with Online Java Compiler
Run Code

 

Finally, use the property-change listener to generate a new LocalDate based on the element property values and provide it to setModelValue ().

 

private void propertyUpdated(  PropertyChangeEvent event) 
{  
	Element e = getElement();   
	int year = e.getProperty("year", -10);  
	int month = e.getProperty("month", -10);  
	int dayOfMonth = e.getProperty(  "dayOfMonth", -10);   
	if (year != -10 && month != -10 && dayOfMonth != -10) 
	{  
		LocalDate newvalue = LocalDate.of(year, month, dayOfMonth);
		setModelValue(newvalue, event.isUserOriginated());  
	} 
}
You can also try this code with Online Java Compiler
Run Code

💡Creating Fields from Other Fields

The third way we can create field components. In this method, we use AbstractCompositeField helper class. It allows us to design a field component determined by the value of one or more internal fields. 

Consider a student selection field that allows the user to select a course from a combo box and then another combo box to select a student from that course.

 

public class StudentField extends AbstractCompositeField<HorizontalLayout, StudentField, Student> 
{
	private ComboBox<Course> courseSelect = new ComboBox<>("Course");
	private ComboBox<Student> studentSelect = new ComboBox<>("Student");
}
You can also try this code with Online Java Compiler
Run Code

 

Now in the constructor:

-Change the value of courseSelect() to update the entries in studentSelect ().

-The constructor assigns the field's value to the student picked in studentSelect().

 

public StudentField() 
{
	super(null);
	courseSelect.setItems(StudentService.getCourses());
	courseSelect.addValueChangeListener(event -> {
	Course course = event.getValue();
	studentSelect.setItems(StudentService.getStudents(course));
	studentSelect.setEnabled(course != null);
    });
	studentSelect.addValueChangeListener(event -> 
	setModelValue(event.getValue(), true));
 	getContent().add(courseSelect, studentSelect);
}
You can also try this code with Online Java Compiler
Run Code

 

Next, use setPresentationValue() to change the combo boxes based on a specific student.

 

@Override
protected void setPresentationValue(Student student) 
{
	if (student == null) 
	{
		courseSelect.clear();
	} 
	else 
	{
		courseSelect.setValue(course.getDepartment());
                		studentSelect.setValue(student);
    }
}
You can also try this code with Online Java Compiler
Run Code

Frequently Asked Questions ❓

Are the type parameters for AbstractSinglePropertyField and AbstractField the same?

Yes, they are the same for both the helper classes.

Can AbstractField determine whether a new value is the same as the previous one?

AbstractField uses Objects.equals() by default to determine whether a new value is the same as the old value.

When should AbstractField ideally be used?

AbstractField should only be used with objects that have immutable values. If the original getValue() instance is updated and submitted to setModelValue() or setValue(), no value-change event is triggered ().

When we use AbstractField what are the two values that we must deal with?

Presentation and model value are the two values that we must deal with while using AbstractField.

📌Conclusion

Pretty much whatever we work within vaadin is a component. This article taught us about field components and how we can create them. After reading this blog, you must have gained some information about the field components. Wanna learn more about web technologies? Why not have a look at web technologies on Coding Ninjas Studio? Also, do you are looking for a set of questions which big tech giants ask during interviews then have a look on problems, interview experiences, and interview bundle which will help you in your placement preparations. Refer to other topics like computer networkstheory of computation and software engineering to expand your knowledge base. Do let us know if you come across any doubt.

Happy learning!

Live masterclass