Password Field Prompt Bug?

Hi All,

I am using the PasswordField:



			password = new PasswordField();
			password.setInputPrompt("Create Password");
			password.setWidth("100%");
			grid.addComponent(password, 0, 1);

It shows the prompt as dots. Is this a bug or am I doing something wrong?

Thanks,
Tom
12178.png

This is a bug. I filed a ticket for the issue:
http://dev.vaadin.com/ticket/8288

Has anyone fixed this bug yet? Im still getting it in Vaadin 7.4.0.
And there is no workaround anymore, does anyone have any ideas?

I’m dealing with the same problem and I’ll try to change input type field from password to text via javascript. That’s the only solution I have right now. If I get something better, I’ll post it here.

Ouch, three years already. Sorry for that.

Instead of JavaScript, you probably could do workaround that with a FocusListener and a BlurListener, as is done
in this example
where we change a TextField to a ComboBox on focus, and back again on blur. I hope there isn’t any flicker effect or anything…

For another solution, you could use CSS to move PasswordField’s caption to inside the component to work as an input prompt. Then, hide it somehow when the field gets focus style. You could also use CSS content property to insert the text, although the property is a bit difficult to use, as it is only applicable with the :after and :before pseudo-selectors, which don’t work for input elements, so… Perhaps something like: v-caption-mypasswordfield::before { content: "My Prompt"; position: absolute; top: 45px; }
Then use that together with Focus/BlurListeners that set the style that (de)activates the prompt.

Thank you for a quick reply, your tip does the trick…

Here is my code

// some layout holder
final FormLayout fl = new FormLayout();

// password field(s)
final TextField password = new TextField();
final PasswordField tmpPassword = new PasswordField();

// placeholder value
password.setInputPrompt("Password");

password.addFocusListener(new FocusListener() {
public void focus(FieldEvents.FocusEvent event) {
fl.replaceComponent(password, tmpPassword);
tmpPassword.focus();
}
});

tmpPassword.addBlurListener(new BlurListener() {
public void blur(FieldEvents.BlurEvent event) {
password.setValue(tmpPassword.getValue());
if (password.getValue().isEmpty()) {
fl.replaceComponent(tmpPassword, password);
}
}
});

Bug is still there in 7.4.5

The easiest solution is to give the password field an ID so you can execute a javascript and change the type of input field. I have JQuery so i can use it, but i bet theres a direct javascript command to achieve the same.

password = new TextField();
password.setNullRepresentation(“”);
password.addStyleName(“login_textfield”);
password.setInputPrompt(“Password”);
password.setId(“login_password”);

    password.addFocusListener(new FocusListener() {
        
        @Override
        public void focus(FocusEvent event) {
            JavaScript.getCurrent().execute("$(\"#login_password\").attr(\"type\",\"password\");");
        }
    });
    
    password.addBlurListener(new BlurListener() {
        
        @Override
        public void blur(BlurEvent event) {
            if (password.isEmpty()){
                JavaScript.getCurrent().execute("$(\"#login_password\").attr(\"type\",\"text\");");
            }
        }
    });

Hi
I’m aware of the fact that it is an older post, however I quickly needed a simular solution and the bug is still present in Vaadin V. 7.6. With respect to another Vaadin forum entry, which I couldn’t find again (sorry), someone asked how to achieve the same in a simple way, especially by avoiding a custom component/widget implementation.

Therefore I would like to show a simple and fast way - more appropriated for Vaadin beginners like me. Furthermore, the following solution should be only suitable for very small applications. The attached icon images should be deposited in ./WebContent/themes/yourtheme/img/ . The attached screenshot give you an impression about how it will look like.

There are 3 classes, one abstraction and two subtyped implementations, and the CSS definitions you should copy paste in your yourtheme.scss. I hope, it will help someone further. By the way, it is my very first post here. I hope not to get someone angry with it. If there are any recommendations how to make a better post, please just tell me.

1.) Code for the
abstract class
:

/** 
 * The abstract class <b>AbstractTextInputField</b> implements a 
 * <b>{@link com.vaadin.ui.TextField TextField}</b> together with a customized 
 * input prompt with an icon for a user login form. Although the default 
 * TextField supports this functionality, it cannot be transfered to a
 * <b>{@link com.vaadin.ui.PassordField PasswordField}</b> due to a bug. This implementation
 * bypasses the bug in a simple manner and is only recommended for small applications. */ 

public abstract class AbstractTextInputField extends HorizontalLayout {

    private static final long serialVersionUID = -2315520775986077104L;
    protected AbstractTextField textField;

    /** Sub Container of the input prompt for an icon with text. */
    protected HorizontalLayout inputPrompt;
    protected String promptText;
    protected ThemeResource promptIcon;
    private HorizontalLayout loginButton;

    protected AbstractTextInputField(ThemeResource icon, String inputPrompt) {
        this.promptIcon = icon;
        this.promptText = inputPrompt;
    }

    /** 
     * Create a new <b>{@link #textField TextField}</b>, before this method 
     * is getting internally invoked during sub-typing. */
    protected void initTextField() {
        this.setSpacing(false);
        this.setMargin(false);

        // Sub Container of the input prompt for an icon with text
        inputPrompt = new HorizontalLayout();
        inputPrompt.setStyleName("login-prompt-layout");
        inputPrompt.setMargin(false);
        inputPrompt.setSpacing(true);
        inputPrompt.addLayoutClickListener(new LayoutClickListener() {
            private static final long serialVersionUID = -7641546629628480340L;
            @Override
            public void layoutClick(LayoutClickEvent event) {
                if(inputPrompt.isVisible()) {
                    inputPrompt.setVisible(false);    
                }
                textField.focus();
            }
        });

        // Icon for the input prompt with a height of 20px
        Image promptIconImg = new Image();
        promptIconImg.setIcon(promptIcon);
        // Label to align the input prompt text
        Label promptLabel = new Label(promptText);
        promptLabel.setStyleName("login-prompt-label");
        // Puts the text of the put input prompt aside its icon
        inputPrompt.addComponents(promptIconImg, promptLabel);
        // Will be only visible, if the value of the pw filed is empty
        inputPrompt.setVisible(false);
        
         textField.addStyleName("login-field");
        // Makes the text change event faster
        textField.setTextChangeEventMode(TextChangeEventMode.EAGER);

        this.addComponents(inputPrompt, textField);
    }

    protected void addListeners() {
        // Updates the visibility of the input prompt while typing
        textField.addTextChangeListener(new TextChangeListener() {
            private static final long serialVersionUID = -1614671000835508255L;
            @Override
            public void textChange(TextChangeEvent event) {
                String text = event.getText();
                if(text.length()>0) {
                    inputPrompt.setVisible(false);
                    textField.setValue(text);
                    textField.focus();
                } else {
                    inputPrompt.setVisible(true);
                }
            }
        });

        // Updates the visibility of the input prompt on focus
        textField.addFocusListener(new FocusListener() {
            private static final long serialVersionUID = -3037044373029000838L;
            @Override
            public void focus(FocusEvent event) {
                if(textField.getValue().equals("")) {
                    inputPrompt.setVisible(true);
                } else {
                    inputPrompt.setVisible(false);
                }
                textField.focus();        
            }
        });

        // Updates the visibility of the input prompt, if the text field focus is lost 
        textField.addBlurListener(new BlurListener() {
            private static final long serialVersionUID = -2138143074891913097L;
            @Override
            public void blur(BlurEvent event) {
                if(textField.getValue().isEmpty()) {
                    inputPrompt.setVisible(true);
                }
            }
        });
    }

    @SuppressWarnings("unchecked")
    public <T extends AbstractTextField> T getPasswordField() {
        return (T) textField;
    }

    public void setFocus() {
        textField.focus();
    }    

    public HorizontalLayout getLoginButton() {
        return loginButton;
    }
}

2.) Code for the
user name
field:

[code]
public class UserNameComponent extends AbstractTextInputField {

private static final long serialVersionUID = 8843196250501825210L;

protected UserNameComponent(ThemeResource icon, String inputPrompt) {
    super(icon, inputPrompt);
    super.textField = new TextField();
    super.initTextField();
}

public UserNameComponent(String inputPrompt) {
    this(new ThemeResource("img/user.png"), inputPrompt);
    addListeners();
}

}
[/code]3.) Code for the
password field
:

[code]
public class PasswordComponent extends AbstractTextInputField {

private static final long serialVersionUID = 3139243312504341566L;
private HorizontalLayout loginButton;

protected PasswordComponent(ThemeResource icon, String inputPrompt) {
    super(icon, inputPrompt);
    super.textField = new PasswordField();
    super.initTextField();
    loginButton = new HorizontalLayout();
    loginButton.setMargin(false);
    loginButton.setSpacing(false);
    loginButton.setStyleName("login-btn");
    loginButton.setVisible(false);    

    this.addComponent(loginButton);
}

public PasswordComponent(String inputPrompt) {
    this(new ThemeResource("img/padlock.png"), inputPrompt);
    addListeners();
}

@Override
protected void addListeners() {
    /* Displays the login button on the right of the password field and let the 
     * input prompt disappear while entering the password. */
    textField.addTextChangeListener(new TextChangeListener() {
        private static final long serialVersionUID = -1614671000835508255L;
        @Override
        public void textChange(TextChangeEvent event) {
            String text = event.getText();
            if(text.length()>0) {
                inputPrompt.setVisible(false);
                loginButton.setVisible(true);
                textField.setValue(text);
                textField.focus();
            } else {
                inputPrompt.setVisible(true);
                loginButton.setVisible(false);
            }
        }
    });

    /* Displays the login button on the right of the password field and let the 
     * input prompt disappear on focus, if a password has been entered */
    textField.addFocusListener(new FocusListener() {
        private static final long serialVersionUID = -3037044373029000838L;
        @Override
        public void focus(FocusEvent event) {
            if(textField.getValue().equals("")) {
                inputPrompt.setVisible(true);
                loginButton.setVisible(false);
            } else {
                inputPrompt.setVisible(false);
                loginButton.setVisible(true);
            }
            textField.focus();        
        }

    });

    /* Detects if the password field looses focus on client site. It displays
     * the input prompt, if the password field value is still empty and out of focus.  */
    textField.addBlurListener(new BlurListener() {
        private static final long serialVersionUID = -2138143074891913097L;
        @Override
        public void blur(BlurEvent event) {
            if(textField.getValue().isEmpty()) {
                inputPrompt.setVisible(true);
                loginButton.setVisible(false);
            }
        }
    });
}

public HorizontalLayout getLoginButton() {
    return loginButton;
}

}
[/code]4.)
CSS classes
adding to your theme styles:

[code]
.login-field-component {
position: relative;
margin-top: -35px;
background: transparent;
border: none;
}

.login-prompt-layout {
position: absolute;
height: 26px;
top: 7px;
left: 10px;
background: transparent;
border: none;
cursor: text;
}

.login-prompt-label {
background: transparent;
color: grey;
font-weight: 400;
}

.login-field {
width: 210px;
height: 37px;
cursor: auto;
border: 2px solid grey;
color: grey;
background: transparent;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
-o-appearance: none;
user-select: text;
-webkit-user-select: text;
-moz-user-select: text;
-o-user-select: text;
-ms-user-select: text;
margin: 0;
font: inherit;
font-weight: 400;
line-height: normal;
-webkit-box-shadow: inset 0 0px 0 #f7f7f7, 0 0px 0 rgba(255, 255, 255, 0.1);
-moz-box-shadow: inset 0 0px 0 #f7f7f7, 0 0px 0 rgba(255, 255, 255, 0.1);
-ms-box-shadow: inset 0 0px 0 #f7f7f7, 0 0px 0 rgba(255, 255, 255, 0.1);
-o-box-shadow: inset 0 0px 0 #f7f7f7, 0 0px 0 rgba(255, 255, 255, 0.1);
box-shadow: inset 0 0px 0 #f7f7f7, 0 0px 0 rgba(255, 255, 255, 0.1);
-webkit-transition: box-shadow 180ms, border 180ms;
-moz-transition: box-shadow 180ms, border 180ms;
-ms-transition: box-shadow 180ms, border 180ms;
-o-transition: box-shadow 180ms, border 180ms;
transition: box-shadow 180ms, border 180ms;
}

.login-field:focus {
outline: none;
-webkit-transition: none;
-moz-transition: none;
-ms-transition: none;
-o-transition: none;
transition: none;
border-color: grey;
-webkit-box-shadow: 0 0 0 0px rgba(25, 125, 225, 0.5), inset 0 0px 0 #f7f7f7, 0 0px 0 rgba(255, 255, 255, 0.1);
-moz-box-shadow: 0 0 0 0px rgba(25, 125, 225, 0.5), inset 0 0px 0 #f7f7f7, 0 0px 0 rgba(255, 255, 255, 0.1);
-ms-box-shadow: 0 0 0 0px rgba(25, 125, 225, 0.5), inset 0 0px 0 #f7f7f7, 0 0px 0 rgba(255, 255, 255, 0.1);
-o-box-shadow: 0 0 0 0px rgba(25, 125, 225, 0.5), inset 0 0px 0 #f7f7f7, 0 0px 0 rgba(255, 255, 255, 0.1);
box-shadow: 0 0 0 0px rgba(25, 125, 225, 0.5), inset 0 0px 0 #f7f7f7, 0 0px 0 rgba(255, 255, 255, 0.1);
-webkit-box-shadow: 0 0 0 0px rgba(25, 125, 225, 0.5);
-moz-box-shadow: 0 0 0 0px rgba(25, 125, 225, 0.5);
-ms-box-shadow: 0 0 0 0px rgba(25, 125, 225, 0.5);
-o-box-shadow: 0 0 0 0px rgba(25, 125, 225, 0.5);
box-shadow: 0 0 0 0px rgba(25, 125, 225, 0.5);
}

.login-btn {
position: absolute;
width: 34px;
height: 26px;
top: 6px;
right: 6px;
background-color: transparent;
// Background Image height 32px
background: url(“img/login.png”) no-repeat;
background-position: 0px 0px;
background-size: initial;
cursor: pointer;
}

.login-btn:hover {
background: url(“img/login_hover.png”) no-repeat;
}
[/code]5.) Inside the
init() method
of your UI class:

...   
    @Override
    protected void init(VaadinRequest request) {
        final VerticalLayout layout = new VerticalLayout();
        setContent(layout);
...
        // Wrapper for the password field and its input prompt to align it as one component 
        PasswordComponent passwordComponent = new PasswordComponent("OTP");
        passwordComponent.setStyleName("login-field-component");
        passwordComponent.setFocus();
...
        layout.addComponent(passwordComponent);
        layout.setComponentAlignment(passwordComponent, Alignment.BOTTOM_CENTER);    
...
}
...  

26201.png
26202.png
26203.png
26204.png
26205.png

I understand that no open source solution can serve everyone’s interests equally. However, this is a bug with a 5 year old ticket on it. There are various addons which once worked yet no longer do. I only started using Vaadin perhaps a year ago, but I am feeling as though it is becoming a diminishing returns product.

I implemented a workaround via JavaScript and the placeholder html attribute:

[url=https://gist.github.com/dim-s/9a5783bd67d55e93b8a071f51a99bc34]
https://gist.github.com/dim-s/9a5783bd67d55e93b8a071f51a99bc34

VaadinUtils.setPlaceholder(passwordField, "Enter your password");

P.S. Also, it can be used for any text fields instead of setInputPrompt() method.
[/url] It will work in IE 10-11, Firefox, Chrome, Opera (Desktop) and many modern web browsers.
http://caniuse.com/#feat=input-placeholder

Thanks Dmitry!

I’m using your solution and it is working very well. :slight_smile: