Important Notice - Forums is archived
To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
PopupButton component
Hello!
I created a Vaadin component called PopupButton. It's a button, which opens a popup when the button is clicked. PopupButton is licensed under the Apache License 2.0.
-Henri
Quite cool!
Suggestion: make a click close the popup if it is already open.
I just released version 0.8 of PopupButton. This version now closes the popup when the button is clicked. Also, this version containts one bug fix, and clicking Vaadin's debug window doesn't close the popup.
Hi,
I am using your PopupComponent, but I have a little problem.
I have a layout in a window, when the window moves the popup does not move.
Any idea how it could solve this problem?
Could I close the popup by code when the window is moved?
Thanks for your help!
One really really minor enhancement proposal: should the down-arrow in the button automatically be changed to "up-arrow" if the menu opens on top of the button?
Joonas Lehtinen: One really really minor enhancement proposal: should the down-arrow in the button automatically be changed to "up-arrow" if the menu opens on top of the button?
Let's say that we have a scrollable window, which contains a PopupButton and other components. Initially, the popup opens above the button because there is no enough space below the button. The user scrolls down the window and now there is enough space to open the popup below the button. In this case, the PopupButton should somehow detect scroll events and change the arrow accordingly.
So I guess it's better that the component not try to be too smart. If somebody wants to change the arrow, it can be done with CSS.
-Henri
It would be nice if dropdown button was different from the right part of button.
So a behavior like Eclipse "Run" "Debug" toolbar buttons.
Hi,
You are correct, that would be useful in some cases. However, the current implementation of PopupButton bases on a single button. Maybe Peter's MultiButton would help you?
-Henri
Hi,
Love this one. A minor improvement proposal: adding a default constructor would make the PopupButton more Visual Editor-friendly as the Visual Editor (in its current incarnation) generates code that expects a default constructor to be present in components.
-Martin Söderström
Martin Söderström: A minor improvement proposal: adding a default constructor would make the PopupButton more Visual Editor-friendly as the Visual Editor (in its current incarnation) generates code that expects a default constructor to be present in components.
I just released a new version 1.2.0 of PopupButton that has a default constructor. Other improvments:
- For easier styling of popup, button's style names are copied to popup. Thanks to Marcus for implementing this feature.
- Disabled PopupButton does't try to send events to server anymore
I just tried the latest 1.2.0 version of the addon and I can't get it to work at all.
On click the button does create 2 divs in the upper-left of the screen but the element styling on them is visibility:hidden.
So it creates the divs in the wrong place and they are not even visible.
Here is the code I am testing with:
public class TestApplication extends Application
{
@Override
public void init()
{
Window w = new Window();
PopupButton popupButton = new PopupButton("Action");
HorizontalLayout popupLayout = new HorizontalLayout();
popupButton.setComponent(popupLayout); // Set popup content
Button modifyButton = new Button("Modify");
modifyButton.setIcon(new ThemeResource("../runo/icons/16/document-txt.png"));
popupLayout.addComponent(modifyButton);
Button addButton = new Button("Add");
addButton.setIcon(new ThemeResource("../runo/icons/16/document-add.png"));
popupLayout.addComponent(addButton);
Button deleteButton = new Button("Delete");
deleteButton.setIcon(new ThemeResource("../runo/icons/16/document-delete.png"));
popupLayout.addComponent(deleteButton);
w.addComponent(popupButton);
this.setMainWindow(w);
}
}
Phoenix Clearwater: I just tried the latest 1.2.0 version of the addon and I can't get it to work at all.
On click the button does create 2 divs in the upper-left of the screen but the element styling on them is visibility:hidden.
So it creates the divs in the wrong place and they are not even visible.Here is the code I am testing with:
public class TestApplication extends Application { @Override public void init() { Window w = new Window(); PopupButton popupButton = new PopupButton("Action"); HorizontalLayout popupLayout = new HorizontalLayout(); popupButton.setComponent(popupLayout); // Set popup content Button modifyButton = new Button("Modify"); modifyButton.setIcon(new ThemeResource("../runo/icons/16/document-txt.png")); popupLayout.addComponent(modifyButton); Button addButton = new Button("Add"); addButton.setIcon(new ThemeResource("../runo/icons/16/document-add.png")); popupLayout.addComponent(addButton); Button deleteButton = new Button("Delete"); deleteButton.setIcon(new ThemeResource("../runo/icons/16/document-delete.png")); popupLayout.addComponent(deleteButton); w.addComponent(popupButton); this.setMainWindow(w); } }
In my tests, your code works as expected. In which browsers do you have this problem? Have you recompiled the widgetset after updating the addon?
Hi,
can you give me an example to change the indicator with CSS, pls.
I found a solution by adding the div tag.
div.v-button div.v-popup-indicator {
display: inline-block;
cursor: pointer;
width: 13px;
height: 11px;
background: transparent url(../../themes/base/common/img/sprites.png) no-repeat -5px 5px;
}
But I want to control the Indicator with a stylename. Is that possible?
Thanks
Jan
Jan Habeck: But I want to control the Indicator with a stylename. Is that possible?
If add a style name to your PopupButton by saying
popupButton.addStyleName("mystyle");
then you can say in your CSS:
div.v-button-mystyle div.v-popup-indicator { … }
This was the component I was really looking for: needed a popUp window appear right out from the button and This did the trick.
There is one thing though I'd like to comment:
PopUp window closes now just by mouseclick somewhere else. Can there be also a choise to use CloseWindow button with event also.
CloseButton could also have the icon property and place in the layout.
Thanx.
:)
Max Santalahti: PopUp window closes now just by mouseclick somewhere else. Can there be also a choise to use CloseWindow button with event also.
CloseButton could also have the icon property and place in the layout.
Did I understand correctly that you want to close the popup by pressing a button in the popup? If so, the following button should do the trick:
Button button = new Button("Close", new ClickListener() {
public void buttonClick(ClickEvent event) {
popupButton.setPopupVisible(false);
}
});
Cheers,
-Henri
Hi Henri,
we are using your component, version 1.2.1 and found 2 issues.
- Component does not atach his child components to the application. This was easily solved by overriding attach() method but still caused some confusion.
- In IE9 when tagpopup button is clicked and popup is opened there is no way to close it. Mouseclick somewhere else has no result. It works fine with other browsers.
Can you check if these issues exist and fix them or provide some workaround.
Hi Henri,
Great addon. I am using it now. I have a question that I can use it with eclipse vaadin plugin to compile it. But when I was using maven-vaadin-plugin to compile it. It always displays:
Widgetset does not contain implementation for org.vaadin.hene.popupbutton.PopupButton. Check its @ClientWidget mapping, widgetsets GWT module description file and re-compile your widgetset. In case you have downloaded a vaadin add-on package, you might want to refer to add-on instructions. Unrendered UIDL://...
So how can I fix this issue?
Thank you very much!
Best,
Chun
Chun W: Hi Henri,
Great addon. I am using it now. I have a question that I can use it with eclipse vaadin plugin to compile it. But when I was using maven-vaadin-plugin to compile it. It always displays:
Widgetset does not contain implementation for org.vaadin.hene.popupbutton.PopupButton. Check its @ClientWidget mapping, widgetsets GWT module description file and re-compile your widgetset. In case you have downloaded a vaadin add-on package, you might want to refer to add-on instructions. Unrendered UIDL://...
So how can I fix this issue?
Have you tried to use other add-ons with Maven? Do they work?
Hi, Henri! Thank you for the component. I use it and meet the problem with setWidget inside PopupLayout when newPopupComponent is VVerticalLayout:
public void updateFromUIDL(final UIDL uidl) {
if (Util.isCached(uidl.getChildUIDL(0))) {
return;
}
Paintable newPopupComponent = client.getPaintable(uidl
.getChildUIDL(0));
if (!newPopupComponent.equals(getPaintable())) {
if (getPaintable() != null) {
client.unregisterPaintable(getPaintable());
}
setWidget((Widget) newPopupComponent);
}
getPaintable().updateFromUIDL(uidl.getChildUIDL(0), client);
}
VVerticalLayout try to invoke client method, when I do the following in server-side:
final PopupButtonContainerWidth open = new PopupButtonContainerWidth("");
open.setImmediate(true);
open.addPopupVisibilityListener(new org.vaadin.hene.popupbutton.PopupButtonContainerWidth.PopupVisibilityListener() {
@Override
public void popupVisibilityChange(
org.vaadin.hene.popupbutton.PopupButtonContainerWidth.PopupVisibilityEvent event) {
if( event.isPopupVisible() )
open.addComponent(multiSelectControl);
else
open.removeComponent(multiSelectControl);
open.requestRepaintAll();
}
});
where multiSelectControl is verticalLayout with TreeTable and TextField. You can try it using the following example with minor modification: TreeTableBug
I would appreciate you for any hints.
Thanks in advance,
Anatoly
It would be nice if the shadow component could also be modified.
For example, when the developer does this:
popupbutton.addStyleName("bubble")
and this is at the moment seen in HTML code in the actual popup overlay element as:
v-popupbutton-popup-bubble
, this would also be added to the overlay's shadow component as class name:
v-shadow-bubble
with regards, Marko.
Hi Marko,
you are correct, that feature would be useful. I'll try to add it to the next release of PopupButton.
-Henri
Hi,
First of all - great add-on! :) It works very good. I have a problem with it though. My case is the following: I'm implementing a button bar which is basically a CssLayout, where I put my buttons. The thing is that I want to have a button count threshold, so if I have more than 5 buttons, the rest shall be hidden into the PopupButton. So far so good. When the buttons become too many I try to remove the button from the CssLayout and add it into the PopupButton container. The problem occures when I try to hide some button, that has already been added to the CssLayout and I just want to move it to the popup, then the button is not visualized. If the button that I try to add is let's say "new", I mean it has not been added anywhere before that, it is properly shown in the popup. Also I made an experiment If I "open" (popup.setPopupVisible(true)) the popup right after I add the button, it is also properly shown. Any ideas ?
Regards! :)
Blagovest Biserov Bashev: Hi,
First of all - great add-on! :) It works very good. I have a problem with it though. My case is the following: I'm implementing a button bar which is basically a CssLayout, where I put my buttons. The thing is that I want to have a button count threshold, so if I have more than 5 buttons, the rest shall be hidden into the PopupButton. So far so good. When the buttons become too many I try to remove the button from the CssLayout and add it into the PopupButton container. The problem occures when I try to hide some button, that has already been added to the CssLayout and I just want to move it to the popup, then the button is not visualized. If the button that I try to add is let's say "new", I mean it has not been added anywhere before that, it is properly shown in the popup. Also I made an experiment If I "open" (popup.setPopupVisible(true)) the popup right after I add the button, it is also properly shown. Any ideas ?Regards! :)
Would be great if you can prepare a small test application that demonstrates the problem.
Henri Kerola:
Blagovest Biserov Bashev: Hi,
First of all - great add-on! :) It works very good. I have a problem with it though. My case is the following: I'm implementing a button bar which is basically a CssLayout, where I put my buttons. The thing is that I want to have a button count threshold, so if I have more than 5 buttons, the rest shall be hidden into the PopupButton. So far so good. When the buttons become too many I try to remove the button from the CssLayout and add it into the PopupButton container. The problem occures when I try to hide some button, that has already been added to the CssLayout and I just want to move it to the popup, then the button is not visualized. If the button that I try to add is let's say "new", I mean it has not been added anywhere before that, it is properly shown in the popup. Also I made an experiment If I "open" (popup.setPopupVisible(true)) the popup right after I add the button, it is also properly shown. Any ideas ?Regards! :)
Would be great if you can prepare a small test application that demonstrates the problem.
Hi Henri,
I prepared a demo app, I tried to simplify as much as possible and in the same time preserve the approach that I use, because that might be the problem.
Here is the application:
package com.example.popupbuttonproblem;
import com.vaadin.Application;
import com.vaadin.ui.Button;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
public class PopupbuttonproblemApplication
extends Application
implements Button.ClickListener
{
private Button hideInPopup;
private Button unhide;
private Button button1;
private Button button2;
private Button button3;
private Button button4;
private Button button5;
private Segment segment;
@Override
public void init()
{
Window mainWindow = new Window("Popupbuttonproblem Application");
setMainWindow(mainWindow);
button1 = new Button("Button 1");
button2 = new Button("Button 2");
button3 = new Button("Button 3");
button4 = new Button("Button 4");
button5 = new Button("Button 5");
disableSomeButtons();
segment = new Segment();
segment.setButtonsThreshold(2);
segment.addButton(button1);
segment.addButton(button2);
segment.addButton(button3);
segment.addButton(button4);
segment.addButton(button5);
hideInPopup = new Button("Enable More Buttons", this);
unhide = new Button("Disable buttons", this);
mainWindow.addComponent(segment);
mainWindow.addComponent(hideInPopup);
mainWindow.addComponent(unhide);
segment.recalculateLayout();
}
private void disableSomeButtons()
{
button1.setVisible(false);
button2.setVisible(false);
button5.setVisible(false);
}
private void enableSomeButtons()
{
button1.setVisible(true);
button2.setVisible(true);
button5.setVisible(true);
}
@Override
public void buttonClick(ClickEvent event)
{
if (event.getButton().equals(hideInPopup))
{
enableSomeButtons();
}
else if (event.getButton().equals(unhide))
{
disableSomeButtons();
}
segment.recalculateLayout();
}
}
What it does is basically create a new "Segment" which is my button bar and add some buttons in the button bar. Then I have two buttons "Enable More Buttons" and "Disable Buttons" that in a nutshell enable and disable some of the buttons and call Segment.recalculateLayout(), so when enabled the buttons become too many and some of them are hidden into the popup.
Here is the code of the Segment class:
package com.example.popupbuttonproblem;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import org.apache.commons.collections.IteratorUtils;
import org.vaadin.hene.popupbutton.PopupButton;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
public class Segment
extends CssLayout
{
private static final long serialVersionUID = -3927863829208310646L;
private static int DEFAULT_BUTTONS_THRESHOLD = 5;
private int buttonsThreshold;
private PopupButton popup;
private VerticalLayout popupLayout;
private LinkedHashSet<AbstractComponent> buttonsSet;
public Segment()
{
setImmediate(true);
buttonsSet = new LinkedHashSet<AbstractComponent>();
}
public void addButton(Button button)
{
if (!(button instanceof PopupButton))
{
buttonsSet.add(button);
}
}
private ArrayList<AbstractComponent> getVisibleButtons()
{
Component c = null;
ArrayList<AbstractComponent> visibleButtons = new ArrayList<AbstractComponent>();
for (Iterator<AbstractComponent> iterator = buttonsSet.iterator(); iterator.hasNext();)
{
c = iterator.next();
if (c.isVisible())
{
visibleButtons.add((AbstractComponent)c);
}
}
return visibleButtons;
}
public void setButtonsThreshold(int threshold)
{
buttonsThreshold = threshold;
}
private int getButtonsThreshold()
{
if (buttonsThreshold > 0)
{
return buttonsThreshold;
}
return DEFAULT_BUTTONS_THRESHOLD;
}
public void recalculateLayout()
{
removeAllComponents();
if (popupLayout != null)
{
popupLayout.removeAllComponents();
}
ArrayList<AbstractComponent> visibleButtons = getVisibleButtons();
if (visibleButtons.size() > getButtonsThreshold())
{
popup = null;
for (int j = 0; j < getButtonsThreshold(); j++)
{
addComponent((Button)IteratorUtils.toArray(visibleButtons.iterator())[j]);
}
for (int j = getButtonsThreshold(); j < visibleButtons.size(); j++)
{
hideInPopup((Button)IteratorUtils.toArray(visibleButtons.iterator())[j]);
}
}
else
{
for (int j = 0; j < visibleButtons.size(); j++)
{
addComponent((Button)IteratorUtils.toArray(visibleButtons.iterator())[j]);
}
}
}
private void hideInPopup(Button button)
{
if (popup == null || !popup.isVisible())
{
popup = addPopupButton("More");
}
addButton(button, popup);
}
public void addButton(Button b, final PopupButton popupButton)
{
if (popupLayout != null)
{
popupLayout.addComponent(b);
}
b.addListener(new ClickListener()
{
private static final long serialVersionUID = 4170589828529711781L;
@Override
public void buttonClick(ClickEvent event)
{
popupButton.setPopupVisible(false);
}
});
popupButton.requestRepaintRequests();
}
public PopupButton addPopupButton(String caption)
{
popup = new PopupButton(caption);
popup.setImmediate(true);
popupLayout = new VerticalLayout();
popupLayout.setWidth("80px");
popup.setComponent(popupLayout);
addComponent(popup);
return popup;
}
}
In a nutshell here I keep a set of all buttons that could be available for the button bar. From that set I get the buttons that are visible for the moment and if their count is more than the threshold I create a PopupButton and hide them into it. That logic is in method recalculateLayout().
So what happens when the app is started. Fist only "Button 3" and "Button 4" are visible. After clicking button "Enable More Buttons" "Button 1", "Button 2" and "Button 5" are enabled, so the visible buttons become more than the treshold so the popup appears and it should contain "Button 3", "Button 4" and "Button 5". The problem is that "Button 3" and "Button 4" are not displayed properly, because they have been added to the CssLayot and then moved to the popup. And "Button 5" is displayed properly, because it has never been added before.
I'm sorry for the long post, I know it sounds a little bit confusing. I attach the war, so you could run it and take a closer look.
Thaks for the help, I appreciate it ! :)
I was able to solve the problem by adding a PopupVisibilityListener and within it I call event.getPopupButton().requestRepaintAll();
popup.addPopupVisibilityListener(new PopupVisibilityListener()
{
public void popupVisibilityChange(PopupVisibilityEvent event)
{
if(event.isPopupVisible())
{
event.getPopupButton().requestRepaintAll();
}
}
});
Regards,
Blagovest
Hi, quick question.
I have a Form and an OpenLayers map wrapped in a Horizontal Layout as PopupButton content.
The first time i open the popup everything looks fine, but if i close it and open it again the map layers are not visible, I can only see the PanZoom and LayerSwitcher.
I tried the requestRepaintAll() solution and it does not even show the Popup content anymore.
map.requestRepaint has no effect either.
What do you think the problem is and how should i go about solving it?
Henri Kerola: Initially, the popup opens above the button because there is no enough space below the button. The user scrolls down the window and now there is enough space to open the popup below the button.
-Henri
Hi Henri, first of all thanks for this useful component!
Here's my question: You wrote, the button opens its components above itself, when there's not enough space below it. Where is this issue checked? I'd like to force my content always to be displayed below my button. Or any other hints?
Greetings, Guy
Guy Brush:
Here's my question: You wrote, the button opens its components above itself, when there's not enough space below it. Where is this issue checked? I'd like to force my content always to be displayed below my button. Or any other hints?
That's checked in the client-side code.
Hello,
When I add PopupButton on panel which is scrollable,
and then open pop up and then scroll panel up or down with mouse wheel,
pop up is not moving with the content on panel which is below.
Pop up is fixed on its position inside browser.
I would like that pop up window is moving with the scrolled panel content below.
Is that any solution to force pop up to move together with the panel content while scrolling with mouse wheel,
or at least is there any solution to close pop up on mouse wheel.
Thanks for your response in advance,
best regards,
Dragan
Hello,
Can anyone help me to set the popup indicator right aligned, as you can see in the figure, it's not right aligned ! I tried "float: right;" but not working fine !
how can i add and remove component from PopupButton dynamic? it is not working, when i dynamic create and remove component.demo code:
PopupButton switchButton = new PopupButton("dynamic test");
switchButton.setStyleName(BaseTheme.BUTTON_LINK);
this.addComponent(switchButton);
final HorizontalLayout buttonLayout = new HorizontalLayout();
switchButton.setComponent(buttonLayout);
buttonLayout.setSpacing(true);
buttonLayout.setMargin(true);
buttonLayout.addComponent(new Button("Button-One"));
buttonLayout.addComponent(new Button("Button-Two"));
Button addButton = new Button("add component");
addButton.addListener(new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
buttonLayout.addComponent(new Button("Button-X"));
}
});
Button removeButton = new Button("remove component");
removeButton.addListener(new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
buttonLayout.removeAllComponent();
}
});
Hi, will be there newer version of this plugin for Vaadin 7.0.0beta11 (or RC1, when it's out) in the near future? I use this useful component in my application which I'm currently migrating to Vaadin 7. The plugin version 2.1.0 works for beta9 and beta11 after some source code changes (via Vaadin migration guide), but in beta11, popup layout is broken and Vaadin Buttons added to popup aren't shown like pushable components. Screenshots from PopupButton Plugin Demo in version beta9 and beta11:
Henri,
are you planning to port this to Vaadin 7 beta11/RC anytime soon? My FilteringTable add-on is kind of depending on it :) I tried the alpha version but could not make it function properly with the V7RC (although tbh I didn't put that much effort into it).
-tepi
hi henry..... ur addon is great i just develop a POC on thst its working fine ....but while using it in myapplication i am unable to useit.... in place of button some text is showing ...like
a tree structure
like as follows....
Widgetset does not contain implementation for org.vaadin.hene.popupbutton.PopupButton. Check its @ClientWidget mapping, widgetsets GWT module description file and re-compile your widgetset. In case you have downloaded a vaadin add-on package, you might want to refer to add-on instructions. Unrendered UIDL:
-Unrendered UIDL
-org.vaadin.hene.popupbutton.PopupButton(NO CLIENT IMPLEMENTATION FOUND) id=PID93 caption=here click position=auto xoffset=0 yoffset=0
-variables
kailasapu murali: hi henry..... ur addon is great i just develop a POC on thst its working fine ....but while using it in myapplication i am unable to useit.... in place of button some text is showing ...like
a tree structure
like as follows....Widgetset does not contain implementation for org.vaadin.hene.popupbutton.PopupButton. Check its @ClientWidget mapping, widgetsets GWT module description file and re-compile your widgetset. In case you have downloaded a vaadin add-on package, you might want to refer to add-on instructions. Unrendered UIDL:
-Unrendered UIDL
-org.vaadin.hene.popupbutton.PopupButton(NO CLIENT IMPLEMENTATION FOUND) id=PID93 caption=here click position=auto xoffset=0 yoffset=0
-variables
You have to compile a widgetset for your application that contains PopupButton. Information about how to do it can be found from the forum or for example from here.
thanks henry....
its working ...
actually i forgot to set the compilation.....
its a nice add-on
Hey Henri,
Acutally the popup closes when I click somewhere outside the popup.
I would like to switch this behaviour to only close the popup when a my ClickListener is fired.
In all other cases the popup should stay visible.
THX
Oliver