com.vaadin.flow.component.textfield.PasswordField Maven / Gradle / Ivy
/*
* Copyright 2000-2024 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.flow.component.textfield;
import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.component.shared.ClientValidationUtil;
import com.vaadin.flow.component.shared.HasAllowedCharPattern;
import com.vaadin.flow.component.shared.HasThemeVariant;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.Validator;
import com.vaadin.flow.data.value.ValueChangeMode;
/**
* Password Field is an input field for entering passwords. The input is masked
* by default. On mobile devices the last typed letter is shown for a brief
* moment. The masking can be toggled using an optional reveal button.
*
* @author Vaadin Ltd.
*/
@Tag("vaadin-password-field")
@NpmPackage(value = "@vaadin/polymer-legacy-adapter", version = "24.4.5")
@JsModule("@vaadin/polymer-legacy-adapter/style-modules.js")
@NpmPackage(value = "@vaadin/password-field", version = "24.4.5")
@JsModule("@vaadin/password-field/src/vaadin-password-field.js")
public class PasswordField extends TextFieldBase
implements HasAllowedCharPattern, HasThemeVariant {
private boolean isConnectorAttached;
private TextFieldValidationSupport validationSupport;
private boolean manualValidationEnabled = false;
/**
* Constructs an empty {@code PasswordField}.
*/
public PasswordField() {
this(true);
}
/**
* Constructs an empty {@code PasswordField}.
*
* If {@code isInitialValueOptional} is {@code true} then the initial value
* is used only if element has no {@code "value"} property value, otherwise
* element {@code "value"} property is ignored and the initial value is set.
*
* @param isInitialValueOptional
* if {@code isInitialValueOptional} is {@code true} then the
* initial value is used only if element has no {@code "value"}
* property value, otherwise element {@code "value"} property is
* ignored and the initial value is set
*/
private PasswordField(boolean isInitialValueOptional) {
super("", "", false, isInitialValueOptional);
// workaround for https://github.com/vaadin/flow/issues/3496
setInvalid(false);
setValueChangeMode(ValueChangeMode.ON_CHANGE);
addValueChangeListener(e -> validate());
}
/**
* Constructs an empty {@code PasswordField} with the given label.
*
* @param label
* the text to set as the label
*/
public PasswordField(String label) {
this();
setLabel(label);
}
/**
* Constructs an empty {@code PasswordField} with the given label and
* placeholder text.
*
* @param label
* the text to set as the label
* @param placeholder
* the placeholder text to set
*/
public PasswordField(String label, String placeholder) {
this(label);
setPlaceholder(placeholder);
}
/**
* Constructs an empty {@code PasswordField} with a value change listener.
*
* @param listener
* the value change listener
*
* @see #addValueChangeListener(com.vaadin.flow.component.HasValue.ValueChangeListener)
*/
public PasswordField(
ValueChangeListener> listener) {
this();
addValueChangeListener(listener);
}
/**
* Constructs an empty {@code PasswordField} with a value change listener
* and a label.
*
* @param label
* the text to set as the label
* @param listener
* the value change listener
*
* @see #setLabel(String)
* @see #addValueChangeListener(com.vaadin.flow.component.HasValue.ValueChangeListener)
*/
public PasswordField(String label,
ValueChangeListener> listener) {
this(label);
addValueChangeListener(listener);
}
/**
* Constructs a {@code PasswordField} with a value change listener, a label
* and an initial value.
*
* @param label
* the text to set as the label
* @param initialValue
* the initial value
* @param listener
* the value change listener
*
* @see #setLabel(String)
* @see #setValue(Object)
* @see #addValueChangeListener(com.vaadin.flow.component.HasValue.ValueChangeListener)
*/
public PasswordField(String label, String initialValue,
ValueChangeListener> listener) {
this(label);
setValue(initialValue);
addValueChangeListener(listener);
}
private TextFieldValidationSupport getValidationSupport() {
if (validationSupport == null) {
validationSupport = new TextFieldValidationSupport(this);
}
return validationSupport;
}
/**
* Maximum number of characters (in Unicode code points) that the user can
* enter.
*
* @param maxLength
* the maximum length
*/
public void setMaxLength(int maxLength) {
getElement().setProperty("maxlength", maxLength);
getValidationSupport().setMaxLength(maxLength);
}
/**
* Maximum number of characters (in Unicode code points) that the user can
* enter.
*
* @return the {@code maxlength} property from the webcomponent
*/
public int getMaxLength() {
return (int) getElement().getProperty("maxlength", 0.0);
}
/**
* Minimum number of characters (in Unicode code points) that the user can
* enter.
*
* @param minLength
* the minimum length
*/
public void setMinLength(int minLength) {
getElement().setProperty("minlength", minLength);
getValidationSupport().setMinLength(minLength);
}
/**
* Minimum number of characters (in Unicode code points) that the user can
* enter.
*
* @return the {@code minlength} property from the webcomponent
*/
public int getMinLength() {
return (int) getElement().getProperty("minlength", 0.0);
}
@Override
public void setRequired(boolean required) {
super.setRequired(required);
getValidationSupport().setRequired(required);
}
/**
* Sets a regular expression for the value to pass on the client-side. The
* pattern must be a valid JavaScript Regular Expression that matches the
* entire value, not just some subset.
*
* @param pattern
* the new String pattern
*
* @see
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefpattern>
* @see
* https://html.spec.whatwg.org/multipage/input.html#attr-input-pattern>
*/
public void setPattern(String pattern) {
getElement().setProperty("pattern", pattern == null ? "" : pattern);
getValidationSupport().setPattern(pattern);
}
/**
* A regular expression that the value is checked against. The pattern must
* match the entire value, not just some subset.
*
* @return the {@code pattern} property from the webcomponent
*/
public String getPattern() {
return getElement().getProperty("pattern");
}
/**
* Set to false
to hide the eye icon which toggles the password
* visibility.
*
* @return true
if the button is visible, false
* otherwise
*/
public boolean isRevealButtonVisible() {
return !getElement().getProperty("revealButtonHidden", false);
}
/**
* Set to false
to hide the eye icon which toggles the password
* visibility.
*
* @param revealButtonVisible
* true
to set the button visible,
* false
otherwise
*/
public void setRevealButtonVisible(boolean revealButtonVisible) {
getElement().setProperty("revealButtonHidden", !revealButtonVisible);
}
@Override
public String getEmptyValue() {
return "";
}
/**
* Sets the value of this password field. If the new value is not equal to
* {@code getValue()}, fires a value change event. Throws
* {@code NullPointerException}, if the value is null.
*
* Note: {@link Binder} will take care of the {@code null} conversion when
* integrates with password field, as long as no new converter is defined.
*
* @param value
* the new value, not {@code null}
*/
@Override
public void setValue(String value) {
super.setValue(value);
}
/**
* Returns the current value of the password field. By default, the empty
* password field will return an empty string.
*
* @return the current value.
*/
@Override
public String getValue() {
return super.getValue();
}
@Override
public void setRequiredIndicatorVisible(boolean requiredIndicatorVisible) {
super.setRequiredIndicatorVisible(requiredIndicatorVisible);
getValidationSupport().setRequired(requiredIndicatorVisible);
}
@Override
public Validator getDefaultValidator() {
return (value, context) -> getValidationSupport().checkValidity(value);
}
@Override
public void setManualValidation(boolean enabled) {
this.manualValidationEnabled = enabled;
}
/**
* Performs server-side validation of the current value. This is needed
* because it is possible to circumvent the client-side validation
* constraints using browser development tools.
*/
protected void validate() {
if (!this.manualValidationEnabled) {
setInvalid(getValidationSupport().isInvalid(getValue()));
}
}
@Override
protected void onAttach(AttachEvent attachEvent) {
super.onAttach(attachEvent);
ClientValidationUtil.preventWebComponentFromModifyingInvalidState(this);
}
}