I am new to vaadin. I have one Link like
Link link = new Link("", new ExternalResource(redirectURL));
my requirement is, I have to set value when user clicks the link. Can I add listener when user click the link. Or is there alternate ways of setting value if link is clicked.
To capture onClick on a link or a label, I always create a HorizontalLayout and put the component inside it:
HorizontalLayout hor = new HorizontalLayout();
final Link link = new Link("Click on Me!", new ExternalResource("http://www.google.com"));
hor.addComponent(link);
hor.addLayoutClickListener(new LayoutClickListener() {
#Override
public void layoutClick(LayoutClickEvent event) {
// capture the click here and do whatever you'd like to do, e.g.
// if ( event.getClickedComponent() != null ) {
// if(event.getClickedComponent().equals(link)) {}
}
});
I interpreted your question as changing the caption of the link. As far as I know it's not possibly with the Link component. Take a look at the activelink addon: http://vaadin.com/addon/activelink.
This addon behaves like Link and lets you add a LinkActivatedListener to it. The code should look like this:
final ActiveLink link = new ActiveLink("", new ExternalResource(redirectURL));
link.addListener(new LinkActivatedListener() {
#Override
public void linkActivated(LinkActivatedEvent event) {
link.setCaption("newCaption");
}
});
You could use the new BrowserWindowOpener class:
From the API:
Component extension that opens a browser popup window when the
extended component is clicked.
Example:
BrowserWindowOpener browserWindowOpener = new BrowserWindowOpener(new ExternalResource("http://google.com"));
/*
* Apparently, the BrowserWindowOpener method setWindowName uses the HTML5 target
* attribute (no longer deprecated as it was in HTML4).
* So you can use either a frame name, or one of four special attribute values:
* _blank, _self, _parent, _top
*
* browserWindowOpener.setWindowName();
*/
final Button btn = new Button("Click me");
browserWindowOpener.extend(btn);
btn.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
btn.setCaption("clicked");
}
});
More information here.
I dint work on Vaadin yet But I looked into the document. I found that the Link class internally extends AbstractComponent class which has many functions which you can override. like it has addListener function where you need to pass the Component listener as a parameter and can detect the click event and do whatever you want to.
For reference check this
and this too
Hope this will help :)
Related
Question relates to Wicket 1.6
I have a wizard step, which includes a Textfield component. When I press the Enter key, this is being handled by the default button of the Wizard bar ('Next'), and it advances to the next step in the Wizard. I don't want this to happen. When I hit Enter on the Textfield I just want the value to be updated, but remain on the same page.
I tried overriding the onBeforeRender() method of my Wizard class, which as you can see sets the default button of the containing form to null. However this now results in the 'Prev' button being triggered when I hit Enter, so the wizard goes back to the previous step.
public class ConfigurationWizard extends Wizard {
....
#Override
protected void onBeforeRender()
{
super.onBeforeRender();
Component buttonBar = getForm().get(BUTTONS_ID);
if (buttonBar instanceof IDefaultButtonProvider)
{
getForm().setDefaultButton(null);
}
}
}
So the basic question is, how do I disable the default button behaviour of the Wizard?
My approach (with a nice Wicket behavior)
Usage
TextField<String> myField = new TextField<String>("myField", myModel());
myField.add(new PreventSubmitOnEnterBehavior());
Behavior
public class PreventSubmitOnEnterBehavior extends Behavior
{
private static final long serialVersionUID = 1496517082650792177L;
public PreventSubmitOnEnterBehavior()
{
}
#Override
public void bind( Component component )
{
super.bind( component );
component.add( AttributeModifier.replace( "onkeydown", Model.of( "if(event.keyCode == 13) {event.preventDefault();}" ) ) );
}
}
This has nothing to do with the wizard buttons.
The TextField <input> is doing a form submit when the Enter key is pressed. This is standard behaviour for the <input> element.
The solution is to catch the Enter key press for the <input> and prevent the default behaviour
This bit of javascript magic does the trick for me:
<script type="text/javascript">
$(document).ready(function() {
$("#gridDiv").delegate("input","keypress",function(e){
if(e.originalEvent.keyCode == 13){
e.preventDefault();
}
});
});
</script>
where 'gridDiv' is the id of the <div> containing the TextField
I prefer another approach:
I use AjaxButtons for every button needed, with the specific submit code in the overrided onSubmit():
AjaxButton linkSubmit = new AjaxButton("linkSubmit")
#Override
public void onSubmit(AjaxRequestTarget target, Form form) {
super.onSubmit();
// Submit code goes here....
// ...
setResponsePage(new NewPage());
}
#Override
public void onError(AjaxRequestTarget target, Form form) {
}
};
My form doesn't need a "onSubmit()" method.
And the markup doesn't have any submit buttons. All buttons are coded like this:
With this approach you don't need to mess with javascript codes. The page simply will do nothing if you press Enter. You'll have to click your buttons to submit each one.
Hope this can help you.
I want include Grid in FramedPanel and using gxt dnd.
But if I add FramedPanel in DragSource:
DragSource source = new DragSource(framedPanel) {
#Override
protected void onDragStart(DndDragStartEvent event) {
super.onDragStart(event);
event.setData(framedPanel);
}
};
DnD works when I click and hold on Grid.
How I can do to DnD only worked on the header of FramedPanel.
Consider using Draggable instead of DragSource, then use the constructor that takes two arguments. This way you can specify the header as the 'handle' argument.
Draggable draggable = new Draggable(framedPanel, framedPanel.getHeader());
//assuming GXT 3, just guessing from your post
draggable.addDragStartHandler(new DragStartHandler() {
public void onDragStart(DragStartEvent event) {
//...
}
});
If you must use DragSource, subclass it to replace the Draggable instance, and create a new instance as specified above, plus making the changes found in the existing DragSource constructor.
The content of the tab is formed and displayed when the application is loaded. Later the content of the tab may be changed by other actions. I want to show the newer content after each action. And each time when I click the tab sheet, the content should be refresh/updated. But I failed.
//the content of the tab from the "reprintsTab" class
//in the "reprintsTab" it query data from database and print out
//later I update the data in the database from somewhere else, and I want the tab shows the new content
//I want to click the tab sheet to reload the "reprintTab" class and print out the new content
//here is what I did:
public TabSheet sheet;
//add tab and add the content from "reprintTab" into this tab
sheet.addTab(new reprintsTab());
//add the listener
sheet.addListener(new TabSheet.SelectedTabChangeListener() {
#Override
public void selectedTabChange(SelectedTabChangeEvent event) {
//I know it does not work, because it only reload the class. but not put the content under the tab I want
new reprintsTab();
}
});
What should I do? please help me, thanks.
You can use TabSheet.replaceComponent method to do this:
//Field to store current component
private reprintsTab currentComponent;
//during initialization
currentComponent = new reprintsTab();
sheet.addTab(currentComponent);
sheet.addListener(new TabSheet.SelectedTabChangeListener() {
#Override
public void selectedTabChange(SelectedTabChangeEvent event) {
reprintsTab newComponent = new reprintsTab();
sheet.replaceComponent(currentComponent, newComponent);
currentComponent = newComponent;
}
});
Also, you might want to reload this tab only when it's shown:
sheet.addListener(new TabSheet.SelectedTabChangeListener() {
#Override
public void selectedTabChange(SelectedTabChangeEvent event) {
if (event.getTabSheet().getSelectedTab() == currentComponent) {
//here goes the code
}
}
});
This should work for you, but I would suggest a cleaner approach: implement reprintsTab as a container for components, create method reload or buildInterface method to refresh its' state, so you can just call:
currentComponent.reload();
when you need to update interface.
Also, I hope reprintsTab is just an example name, java class names starting with lowercase letter look ugly.
I'm quite new to interface design and struggling to figure out what the best way to handle events is. In the straight forward case of the handler and the (in this case) buttons causing the event being in the same class, that's fine, I get it. The handler can see the buttons so that it can say:
if (event.getSource() == myButton)
and also, the handler is in the same class so it can add tabs to an object local to that class or similar.
Problem: I don't know how I should be dealing with the case when the handlers and event generators are in different classes.
e.g.
From my main layout class I create and show a custom dialog. That dialog is implemented in its own class. Ideally dialog would use the handler from the main layout class (it implements ClickHandler), which would be fine, but my application has a few different ClickEvents. I distinguish between them as above by checking the source. In this case the buttons are in the dialog class though, so I can't simply say:
if (event.getSource() == myDialogbutton)
as myDialogButton is not in scope.
Any hints for how this should work would be appreciated.
D
Perhaps I can help you with my solution ...
I inherited ClickHandler to an own class which is generic. You can give the ClickHandler any kind of object you want and will be able to access it from the method within.
Example:
import com.google.gwt.event.dom.client.ClickHandler;
public abstract class ClickHandlerData<T> implements ClickHandler {
private T data;
public ClickHandlerData(T data)
{
this.data = data;
}
public T getData()
{
return data;
}
public void setData(T data)
{
this.data = data;
}
}
Now, in case of a button:
Button btn = new Button("click me");
btn.addClickHandler(new ClickHandlerData<Button>(btn)) {
public void onClick(ClickEvent event) {
Button btn = getData();
...
}
}
I use this class to pass parameters like Integers or something else to the ClickHandler. For instance:
for (int i=0;i<10;i++)
{
Button btn = new Button("click me");
btn.addClickHandler(new ClickHandlerData<Integer>(i)) {
public void onClick(ClickEvent event) {
Window.alert("you klicked button "+getData());
...
}
}
}
I also do the same for AsyncCallbacks, for Commands, for everything else I need to pass data to.
Hope this helped you a bit.
It appears to me that you are trying to use one listener for multiple buttons, unless several of the buttons have the same function they should have different listeners.
In general you should try to have one listener per function, instead of one listener per "event generator".
If you have for example a logout button, it may have a listener from the LoginStatusWidget (displaying who the client is logged in as) and a listener from an object responsable of notefying the server of the logout.
It will serve to seperate the components from each other.
At first i recommend you to try to collect your Buttons and their ClickHandlers in the same class, but if in your case it is not possible, I have a suggestion to you:
When you are creating your Button you can add some information to them:
Button button = new Button("submit");
button.setLayoutData(someObj);
And then after firing event you can get your Button from event in your ClickHandler and find out which button it is :
Button button = (Button) event.getSource();
MetaData someObj = (MetaData) button.getLayoutData();
Try creating a new listener for each anonymous or serial widget e.g. button in a FlexTable. That way their life cycles are connected and they only refer to each other.
Extend the widget
Give it an id and add it to the constructor [make sure the id is one of a kind]
Implement the listener class.
create a new instance of the listener each time you create an item of the same kind.
I'm guessing there are specific objects connected to the widgets. If so keep a HashMap.
May the force be with you
Can't you just do:
final Button source= new Button("My Button");
button.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
doSomething(source);
}
}
Note the button instance has to be marked final.
im sitting on this for 4 hours now, and once again I end up on Stackoverflow because I just cant solve this (simple) problem.
I want to fire a method when I click a button, Google gives an Example like this:
// Listen for mouse events on the Add button.
addStockButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
addStock();
}
});
But this creates a new Instance(?..How can they even create an instance of Clickhandler, since its an Interface) everytime the button is clicked. How can I solve this that all buttons share a Clickhandler and the Handler askes the Button which button he is, so he can fire the method attached to that button.
Any Ideas? If you this is to vage information and you require more code please let me know.
Thanks in advance,
Daniel
Java creates a new instance of an anonymous class that implements ClickHandler. Which it can do because you provide an implementation for the onClick function specified by the interface.
This class is however not created when you click on the button but at the moment you call addClickhandler. If you need the handler for multiple events do something like:
ClickHandler handler = new ClickHandler() {
public void onClick(ClickEvent event) {
addStock();
}
};
addStockButton.addClickHandler(handler);
someOtherButton.addClickHandler(handler);
Within the handler you can identify from where the event is coming using event.getSource().
If you have access to your button variables you could simply check the pointer
if (addStockButton == event.getSource()) ...
Or you can cast the result of getSource to the appropriate type and access the properties/methods of the object.
Eelke has already answered your question. I just add that if you would use GWT's UiBinder feature, you could achieve what you want like this:
#UiField
Button addStockButton;
#UiField
Button removeStockButton;
#UiHandler({ "addStockButton", "removeStockButton" })
void handleClickEvents(ClickEvent event)
{
if (event.getSource() == addStockButton)
{
addStock();
}
else if (event.getSource() == removeStockButton)
{
removeStock();
}
}
Its an anonymous instance of the interface, this is like declaring a new class that implements that interface.
I would have to ask why you would want to do this, you would need to make the ClickHandler contain a reference to its parent. You would also need to make the buttons identifiable so you can select the right one in the body of the ClickHandler. Is your need to only have a single instance really that bad that you can't have multiple anonymous instances ?