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.
Related
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 :)
I have an application which uses GXT and contains ±30 forms. I would like to make these forms so that when the user hits enter in a text field, the form gets submitted, like a regular browser form would.
I know I can add a key press listener to every text field, which would invoke the submit after enter is pressed, but since I want to apply this to every field in every form I am not sure if this is ideal.
Is there a simpler way to implement this in the entire application?
If not, which pattern should I use to add this functionality to every field? I can extend the TextField class, add the functionality in the child class and use the child class in the application. Or I can create a factory for the text field class which would also add the listener to the field. Or is there some other way, Decorator perhaps? I was wondering which of these approaches, if any, is generally preferred.
I would try something like this:
Event.addNativePreviewHandler(new NativePreviewHandler() {
#Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
if (event.getNativeEvent().getEventTarget() != null) {
Element as = Element.as(event.getNativeEvent().getEventTarget());
if (as.getTagName().toLowerCase().equals("input") ||
as.getTagName().toLowerCase().equals("textarea")) {
// TODO submit data;
}
}
}
}
});
Every time someone hits the Enter Key and the cursor is placed on a input- or textarea-tag, you will get the control and can submit your data.
I don't think there is a way to do what you're asking directly in the GXT library. I do want to stress that extending the TextField class just to add an event handler to it is not the correct way to handle this. Event handlers are based on the composition of a class. It would be like extending a class with a List field just to add another element into the list.
A singleton factory class that created and initialises the Textfield for you would be the cleanest solution, in my opinion. It would allow you to effectively change defaults and add other handlers as required at a later time in a single place if requirements change.
You can try it with GWT JSNI also.
Steps to follow:
define a function in JavaScript that is called on Enter key press
call GWT JSNI from above JavaScript function that is exported at the time of onModuleLoad using GWT JSNI
get the Element from where this event is triggered and finally submit the form based on its tag name or Id
Sample code:
HTML/JSP:
<script>
window.onkeydown = keydown;
function keydown(event) {
if (event.which == 13) {
formSubmit(event.target);
}
}
</script>
JAVA(Entry Point):
import com.google.gwt.dom.client.Element;
public void onModuleLoad() {
exportFormSubmit();
...
}
public static void formSubmit(Element element) {
Window.alert("element tag name:" + element.getTagName() + "form ID:"
+ element.getParentElement().getId());
}
public static native void exportFormSubmit() /*-{
$wnd.formSubmit = $entry(#com.x.y.z.client.GWTTestProject::formSubmit(Lcom/google/gwt/dom/client/Element;));
}-*/;
Can anyone tell me whether there is an equivalent method in GWT like change in jQuery for form elements like radio-buttons, checkboxes, etc, which is fired the moment any such button is checked or unchecked? If so, how do I use it? I found a method like addValueChangeHandler in the Google docs, but apart from providing the prototype, there is no working example.
Specifically, if I want a handler which will wait for a checkbox being checked or unchecked, and accordingly pop up an alert like A checkbox has been checked!!, along with that buttons accompanying text.
CheckBox newOption = new CheckBox();
newOption.setText("Check to see alert");
newOption.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
#Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
if (event.getValue()) {
Window.alert("Checkbox is checked!");
} else {
Window.alert("Checkbox is unchecked!");
}
}
});
In a Wicket app, I have a bunch of <button> elements to which I'm attacking a Link component. Now in the onClick() method of the component I want to disable or change the style of the button. How can I do that? Calling setEnabled(false) has no effect.
Repeated uses of onClick() are operating on the same object in memory. If you're not using Ajax, you can still maintain some state in an anonymous subclass of Link. Then, you can use onBeforeRender() and onComponentTag() to change how it is displayed each time.
Link<Void> link = new Link<Void>("myLink") {
private String customCSS = null;
private boolean customEnabled = true;
public void onClick() {
if (/* test to determine disabled */) {
customCSS = "disabled";
customEnabled = false;
} else {
customCSS = null;
customEnabled = true;
}
}
#Override
protected void onComponentTag(ComponentTag tag) {
super.onComponentTag(tag);
if (customCSS != null)
tag.put("class", customCSS);
}
#Override
public boolean isEnabled() {
return super.isEnabled() && customEnabled;
}
};
AttributeModifiers (or other behaviors) aren't good for this case because, if you add them in the onClick() method, they will begin stacking on the same link for each click - since they are maintained as part of the Link's state.
Your Link can keep track of all manner of state, allowing your onClick() method to enable/disable/change/etc with repeated clicks.
You can also override onBeforeRender(), isVisible(), and other methods that are run each time the link is displayed on the page. The constructor, onConfigure(), and others are run just once, regardless of how many times you click the button.
I don't think this is an entirely good idea in Wicket. Of course it could be done by trickery, but it's far simpler to either:
Override the isEnabled() method to return a value derived from the model of the form/component.
Attach an AttributeModifier when you create the component, and use a model for it which returns a value derived as above.
Whichever you choose, the principle is to let Wicket "pull" rendering information in rather than pushing it explicitly.
The answer provided by Michael Borgwardt is nearly correct.
The problem is that you use Link. Disabled Links use <span> instead of
<a>/<button> and are surrounded with <em> by default. Using Button
component will set 'disabled' attribute in the element.
I would like to add, that you need to use HTML button element instead of <a> (link). Original answer can be counfusing, because Link and Button also exist in Wicket.
I think AjaxCallDecorator should be the class you need to use to disable/change style of the button.
The problem is that you use Link. Disabled Links use <span> instead of <a>/<button> and are surrounded with <em> by default.
Using Button component will set 'disabled' attribute in the element.
Take a look at SimpleAttributeModifier and AttributeAppender. Depending on your actual requirements one of those should do the trick. SimpleAttributeModifier adds or replaces an attribute of any HTML-Tag that has a prepresentation in wicket (replaces the css class), while AttributeAppender appends to the attributes (adds another css class). This should work for enabling/disabling buttons as well but I haven't tried that.
Example:
Label label = new Label("id", "Some silly text.")
add(label);
label.add(new SimpleAttributeModifier("class", "my-css-class");
For Ajax you'll have to add the component to the target as well.
More detailed example:
Java code:
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.behavior.SimpleAttributeModifier;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.model.Model;
public class DemoPage extends WebPage {
public DemoPage() {
Form form = new Form("form");
add(form);
final WebMarkupContainer wmc = new WebMarkupContainer("greenText");
form.add(wmc);
form.add(new Link("redLink"){
#Override
public void onClick() {
wmc.add(new SimpleAttributeModifier("class", "redText"));
}});
final Button boldButton = new Button("boldButton"){
#Override
public void onSubmit() {
wmc.add(new AttributeAppender("class", true, new Model<String>("boldText"), " "));
}};
form.add(boldButton);
Link disabler = new Link("buttonDisabler") {
#Override
public void onClick() {
boldButton.add(new AttributeAppender("disabled", true, new Model<String>("disabled"), " "));
}
};
form.add(disabler);
}
}
corresponding HTML:
<html>
<head>
<style>
.redText {
color: red;
}
.greenText {
color: green;
}
.boldText {
font-weight: bold;
}
</style>
</head>
<body>
<form wicket:id="form">
<div class="greenText" wicket:id="greenText">This is Green.</div><br />
Make it red<br />
<input type="submit" wicket:id="boldButton" value="Make it bold" /><br />
Disable the button
</form>
</body>
</html>
How do you set focus on a component with Apache Wicket? Searching leads to very little information, mostly on setting the default field. I do not want to set a default field, rather I am looking to set focus when, for example, a specific radio button is selected.
I suggest using the native org.apache.wicket.ajax.AjaxRequestTarget#focusComponent(). For example:
/**
* Sets the focus in the browser to the given component. The markup id must be set. If
* the component is null the focus will not be set to any component.
*
* #param component
* The component to get the focus or null.
*/
org.apache.wicket.ajax.AjaxRequestTarget#focusComponent(Component component)
Once you create your behavior to set the focus, you should be able to add it to the component on any event, just make sure that component is part of the AjaxRequestTarget. I don't see why this wouldn't work...
myRadioButton.add(new AjaxEventBehavior("onchange") {
#Override
protected void onEvent(AjaxRequestTarget target) {
myOtherComponent.add(new DefaultFocusBehavior());
target.addComponent(myForm);
}
});
Here's a link that shows how to create the default focus behavior if you do not have one already:
http://javathoughts.capesugarbird.com/2009/01/wicket-and-default-focus-behavior.html
If you only want to setFocus through javascript and don't want to reload a form or a component, you can use the following code:
import org.apache.wicket.Component;
public class JavascriptUtils {
private JavascriptUtils() {
}
public static String getFocusScript(Component component) {
return "document.getElementById('" + component.getMarkupId() + "').focus();";
}
}
And then in any Ajax Method you can use:
target.appendJavascript(JavascriptUtils.getFocusScript(componentToFocus));
For a pop-up like modalWindow my workaround solution was to use the attribute "autofocus" on the first input tag.
An easy solution is to add it to the html directly.
<input ..... autofocus>
Another solution is to add it to the modalWindow itself:
#Override
public void show(AjaxRequestTarget target) {
super.show(target);
setUpFocus();
}
protected void setUpFocus() {
DeepChildFirstVisitor visitor = new DeepChildFirstVisitor() {
#Override
public void component(Component component, IVisit<Void> iVisit) {
if (isAutofocusable(component)) {
component.add(new AttributeAppender("autofocus", ""));
iVisit.stop();
}
}
#Override
public boolean preCheck(Component component) {
return false;
}
};
this.visitChildren(FormComponent.class, visitor);
}
protected boolean isAutofocusable(Component component) {
if (component instanceof TextArea ||
component instanceof DropDownChoice ||
// component instanceof RadioChoice ||
component instanceof AjaxCheckBox ||
component instanceof AjaxButton ||
component instanceof TextField) {
return true;
}
return false;
}
RadioChoice is commented out because this solution is not working on that. For RadioChoice i would recommend to implement a FocusedRadioChoice:
public class FocusedRadioChoice<T> extends RadioChoice<T> {
//constructors...
#Override
protected IValueMap getAdditionalAttributes(int index, T choice) {
super.getAdditionalAttributes(0, choice);
AttributeMap am = new AttributeMap();
am.put("autofocus", "");
return am;
}
}
Is there a way to achieve the same without JavaScript?
(I am implementing a form with a feedback-Panel that only comes up when Javascript is turned off, so it would not make sense to depend on JavaScript there...,-)
I could only find answers which use JS .focs()... maybe Wicket 1.5 will provide a method Component.setFocus()...
If you happen to be using an Ajax button, you can simply call target.focusComponent(myComponent); in the button's onSubmit method.
#martin-g 's solution was the only solution that got it working for my scenario - a modal/pop up.
Note:
I think autofocus embedded explicitly in HTML only works on page load, not modal load so any efforts to skillfully set the autofocus attribute in the HTML of a modal just fail miserably - always.
Here I lay out the steps for setting the focus on an input field called 'myInput' using the full power of Wicket (no JS!):
In onInitialize:
// Make sure the field has an ID in markup
myInput.setOutoutMarkupId(true);
Provide an overridden show method where you call the focusComponent method:
public void show(AjaxRequestTarget target)
{
// Make sure you call the super method first!
super.show(target);
target.focusComponent(myInput);
}
This does require that your component is an attribute of your modal content class so that you can access it in the show method. To avoid creating a class attribute for your input component you could blend this solution with the solution from BlondCode by replacing that solution's
component.add(new AttributeAppender("autofocus", ""));
with
target.focusComponent(component);
This also works!