TokenField
A field for selecting multiple tokens/tags; a.k.a multi-select ComboBox
A field that allows the user to select multiple 'tokens' using a ComboBox (which by default actually looks like a TextField w/ suggestions).
The field is very configurable, as can be seen in the demo.
Features include:
- tokens can be inserted before/after input (over/under/etc depending on layout)
- backspace/delete removes last token (customizeable)
- layout can be changed
- suggestions from container
- auto add new to container
- disallow tokens not in container
- custom action on add (+ detect if token is in container)
- custom configuring of the token button (style, caption, etc)
- custom action on remove
- built in style for either Token or ComboBox input look
- built in styles for buttons, default and "emphasize"
Note that Vaadin 6.3.3 fixes some bugs in the ComboBox, which TokenField uses.
Sample code
/* * This is the most basic use case using all defaults; it's * empty to begin with, the user can enter new tokens, * which are automatically added to the container */ TokenField f = new TokenField("Add tags"); addComponent(f);
TokenField f = new TokenField(lo) { protected void onTokenInput(Object tokenId) { // default adds the token } protected void onTokenClicked(final Object tokenId) { // default removes w/o dialog } protected void configureTokenButton(Object tokenId, Button button) { // default sets sets style & caption } }; f.setStyleName(TokenField.STYLE_TOKENFIELD); // remove fake textfield look f.setWidth("100%"); // width... f.setInputWidth("100%"); // and input width separately f.setContainerDataSource(tokens); // 'address book' f.setFilteringMode(ComboBox.FILTERINGMODE_CONTAINS); // suggest f.setTokenCaptionPropertyId("name"); // use container item property "name" in input f.setInputPrompt("Enter contact name or new email address"); f.setRememberNewTokens(false); // we can opt to do this ourselves
{ /* * In this example, most features are exercised. A container * with generated contacts is used. The input has filtering * (a.k.a suggestions) enabled, and the added token button is * configured so that it is in the standard "Name <email>" * -format. New contacts can be added to the container ('address * book'), or added as-is (in which case it's styled * differently). */ Panel p = new Panel("Full featured example"); p.getContent().setStyleName("black"); addComponent(p); // generate container Container tokens = generateTestContainer(); // we want this to be vertical VerticalLayout lo = new VerticalLayout(); lo.setSpacing(true); final TokenField f = new TokenField(lo) { private static final long serialVersionUID = 5530375996928514871L; // dialog if not in 'address book', otherwise just add protected void onTokenInput(Object tokenId) { Set<Object> set = (Set<Object>) getValue(); Contact c = new Contact("", tokenId.toString()); if (set != null && set.contains(c)) { // duplicate getWindow().showNotification( getTokenCaption(tokenId) + " is already added"); } else { if (!cb.containsId(c)) { // don't add directly, // show custom "add to address book" dialog addWindow(new EditContactWindow(tokenId .toString(), this)); } else { // it's in the 'address book', just add addToken(tokenId); } } } // show confirm dialog protected void onTokenClick(final Object tokenId) { getWindow().addWindow( new RemoveWindow((Contact) tokenId, this)); } // just delete, no confirm protected void onTokenDelete(Object tokenId) { this.removeToken(tokenId); } // custom caption + style if not in 'address book' protected void configureTokenButton(Object tokenId, Button button) { super.configureTokenButton(tokenId, button); // custom caption button.setCaption(getTokenCaption(tokenId) + " <" + tokenId + ">"); // width button.setWidth("100%"); if (!cb.containsId(tokenId)) { // it's not in the address book; style button .addStyleName(TokenField.STYLE_BUTTON_EMPHAZISED); } } }; p.addComponent(f); // This would turn on the "fake tekstfield" look: f.setStyleName(TokenField.STYLE_TOKENFIELD); f.setWidth("100%"); f.setInputWidth("100%"); f.setContainerDataSource(tokens); // 'address book' f.setFilteringMode(ComboBox.FILTERINGMODE_CONTAINS); // suggest f.setTokenCaptionPropertyId("name"); // use name in input f.setInputPrompt("Enter contact name or new email address"); f.setRememberNewTokens(false); // we'll do this via the dialog // Pre-add a few: Iterator it = f.getTokenIds().iterator(); f.addToken(it.next()); f.addToken(it.next()); f.addToken(new Contact("", "thatnewguy@example.com")); } /** * This is the window used to confirm removal */ class RemoveWindow extends Window { private static final long serialVersionUID = -7140907025722511460L; RemoveWindow(final Contact c, final TokenField f) { super("Remove " + c.getName() + "?"); setStyleName("black"); setResizable(false); center(); setModal(true); setWidth("250px"); setClosable(false); // layout buttons horizontally HorizontalLayout hz = new HorizontalLayout(); addComponent(hz); hz.setSpacing(true); hz.setWidth("100%"); Button cancel = new Button("Cancel", new Button.ClickListener() { private static final long serialVersionUID = 7675170261217815011L; public void buttonClick(ClickEvent event) { f.getWindow().removeWindow(getWindow()); } }); hz.addComponent(cancel); hz.setComponentAlignment(cancel, Alignment.MIDDLE_LEFT); Button remove = new Button("Remove", new Button.ClickListener() { private static final long serialVersionUID = 5004855711589989635L; public void buttonClick(ClickEvent event) { f.removeToken(c); f.getWindow().removeWindow(getWindow()); } }); hz.addComponent(remove); hz.setComponentAlignment(remove, Alignment.MIDDLE_RIGHT); } } /** * This is the window used to add new contacts to the 'address book'. It * does not do proper validation - you can add weird stuff. */ class EditContactWindow extends Window { private Contact contact; EditContactWindow(final String t, final TokenField f) { super("New Contact"); if (t.contains("@")) { contact = new Contact("", t); } else { contact = new Contact(t, ""); } setModal(true); center(); setWidth("250px"); setStyleName("black"); setResizable(false); // Just bind a Form to the Contact -pojo via BeanItem Form form = new Form(); form.setItemDataSource(new BeanItem<Contact>(contact)); form.setImmediate(true); addComponent(form); // layout buttons horizontally HorizontalLayout hz = new HorizontalLayout(); addComponent(hz); hz.setSpacing(true); hz.setWidth("100%"); Button dont = new Button("Don't add", new Button.ClickListener() { private static final long serialVersionUID = -1198191849568844582L; public void buttonClick(ClickEvent event) { if (contact.getEmail() == null || contact.getEmail().length() < 1) { contact.setEmail(contact.getName()); } f.addToken(contact); f.getWindow().removeWindow(getWindow()); } }); hz.addComponent(dont); hz.setComponentAlignment(dont, Alignment.MIDDLE_LEFT); Button add = new Button("Add to contacts", new Button.ClickListener() { private static final long serialVersionUID = 1L; public void buttonClick(ClickEvent event) { if (contact.getEmail() == null || contact.getEmail().length() < 1) { contact.setEmail(contact.getName()); }
Links
Compatibility
Was this helpful? Need more help?
Leave a comment or a question below. You can also join
the chat on Discord or
ask questions on StackOverflow.
Version
Converted to work with Vaadin 7. Also added a possibility to customize the adding of new items to the dropdown.
- Released
- 2012-04-13
- Maturity
- STABLE
- License
- Apache License 2.0
Compatibility
- Framework
- Vaadin 7.0+
- Vaadin 6.0+ in 0.1
- Browser
- Internet Explorer
- Internet Explorer
- Internet Explorer
- Firefox
- Opera
- Safari
- Google Chrome
- Internet Explorer
TokenField - Vaadin Add-on Directory
A field for selecting multiple tokens/tags; a.k.a multi-select ComboBoxA field that allows the user to select multiple 'tokens' using a ComboBox (which by default actually looks like a TextField w/ suggestions).
The field is very configurable, as can be seen in the demo.
Features include:
- tokens can be inserted before/after input (over/under/etc depending on layout)
- backspace/delete removes last token (customizeable)
- layout can be changed
- suggestions from container
- auto add new to container
- disallow tokens not in container
- custom action on add (+ detect if token is in container)
- custom configuring of the token button (style, caption, etc)
- custom action on remove
- built in style for either Token or ComboBox input look
- built in styles for buttons, default and "emphasize"
Note that Vaadin 6.3.3 fixes some bugs in the ComboBox, which TokenField uses.