I have my string variable I want to display
final String wrongPw = "Wrong Password";
My AJAX yes button:
AjaxButton yesButton = new AjaxButton("yesButton", yesNoForm) {
private static final long serialVersionUID = -3827487963204274386L;
#Override
protected void onSubmit(AjaxRequestTarget target, Form form) {
if (target != null && password.equals(getPw())) {
answer.setAnswer(true);
modalWindow.close(target);
}else if(target != null && !password.equals(getPw())){
answer.setAnswer(false);
wrongPW.setVisible(true);
}
}
};
Further down:
wrongPW.setVisible(false);
add(wrongPW);
When I hit the yes button I must refresh the page for the wrongPW to display.
How can this be done dynamically?
You have to add the component you want to update to the target like this:
target.add(wrongPW);
Be sure to set the markup placeholder tag on initialization of the component you want to dynamically change the visibility of, else Wicket won't find it.
wrongPW.setOutputMarkupPlaceholderTag(true);
The reasons for this are explained here: https://stackoverflow.com/a/9671796/2795423
Related
I'm quite new using Wicket framework.
Currently I'm working on to set the setEnabled of the TextField. In my case, I have two TextField to control using AjaxCheckbox. During my trial, I have no issue to setEnabled for the first TextField, but when I add second TextField with AjaxCheckbox, the second one didn't work, only the first one.
Is there something that I missed out?
The first one
mobileNo = new TextField<String>("mobileNo", new PropertyModel<String>(getModelObject(), "mobileNo")) {
#Override
protected void onConfigure() {
setEnabled(mobileNoCheckBoxValue);
}
};
mobileNo.setOutputMarkupPlaceholderTag(true);
form.add(mobileNo);
AjaxCheckBox mobileNoCheckBox = new AjaxCheckBox("mobileNoCheckBox", new PropertyModel<Boolean>(this, "mobileNoCheckBoxValue")) {
private static final long serialVersionUID = 1L;
#Override
protected void onUpdate(AjaxRequestTarget target) {
target.add(mobileNo);
}
};
form.add(mobileNoCheckBox);
and the second one
appliedAmount = new TextField<BigDecimal>("appliedAmount", new BigDecimalFormatProperty<BigDecimal>(getModel(), "appliedAmount")) {
#Override
protected void onConfigure() {
setEnabled(appliedAmountCheckBoxValue);
}
};
appliedAmount.setOutputMarkupPlaceholderTag(true);
form.add(appliedAmount);
AjaxCheckBox appliedAmountCheckBox = new AjaxCheckBox("appliedAmountCheckBox", new PropertyModel(this, "appliedAmountCheckBoxValue")) {
private static final long serialVersionUID = 1L;
#Override
protected void onUpdate(AjaxRequestTarget target) {
target.add(appliedAmount);
}
};
form.add(appliedAmountCheckBox);
Check your HTML code and make sure you use different id attribute values for <input type="checkbox" .../>.
If you have id attribute in your HTML template then better remove it completely and let Wicket to auto-generate it. The ids must be unique by HTML specification. But also Wicket uses them to lookup the HTML elements when sending their values with Ajax.
I guess when you click the second checkbox Wicket sends the state of the first one, which does not toggle.
I am building a preference page in Eclipse by extending the FieldEditorPreferencePage class. this page contains 2 fields : 1 BooleanFieldEditor (checkbox) and 1 FileFieldEditor. I would like to disable/enable the file field following the checkbox value.
I went up to something like this (some obvious code is not displayed):
public class PreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
public static final String PREF_KEY_1 = "checkBoxPref";
public static final String PREF_KEY_2 = "filePref";
private FileFieldEditor pathField;
private BooleanFieldEditor yesOrNoField;
private Composite pathFieldParent;
#Override
protected void createFieldEditors() {
this.yesOrNoField = new BooleanFieldEditor(PREF_KEY_1, "Check this box!", getFieldEditorParent());
this.pathFieldParent = getFieldEditorParent();
this.pathField = new FileFieldEditor(PREF_KEY_2, "Path:", this.pathFieldParent);
addField(this.yesOrNoField);
addField(this.pathField);
boolean isChecked = getPreferenceStore().getBoolean(PREF_KEY_1);
updatePathFieldEnablement(! isChecked);
}
/**
* Updates the fields according to entered values
*/
private void updatePathFieldEnablement(boolean enabled) {
this.pathField.setEnabled(enabled, this.pathFieldParent);
}
#SuppressWarnings("boxing")
#Override
public void propertyChange(PropertyChangeEvent event) {
if (event.getProperty().equals(FieldEditor.VALUE) && event.getSource() == this.yesOrNoField) {
updatePathFieldEnablement(! (boolean) event.getNewValue());
}
super.propertyChange(event);
}
}
My question is about this second parameter in FieldEditor#setEnabled. This parameter is the parent composite of the FieldEditor's controls ("Used to create the controls if required" says the javadoc) . At first, I set the value with the return of getFieldEditorParent but then I got an exception "Different parent". So I ended storing it (cf. this.pathFieldParent) and give it back to setEnabled and it works (or it seems to work).
But I am not sure I am doing well, especially because I had to create a member in my class that means nothing to it (and I would have to create many of them if I had many fields to enable/disable).
Do you think I am doing well or is there a better way to provide this parent ? And could you explain to me why *setEnabled" needs it ?
Thanks.
You are using the default FLAT layout for the preference page. When this layout is used each call to getFieldEditorParent generates a new Composite so you have to make just one call and remember the correct parent. Using the GRID layout getFieldEditorParent always returns the same parent. This is the actual code:
protected Composite getFieldEditorParent() {
if (style == FLAT) {
// Create a new parent for each field editor
Composite parent = new Composite(fieldEditorParent, SWT.NULL);
parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
return parent;
}
// Just return the parent
return fieldEditorParent;
}
setEnabled does sometimes create a new Label control so it needs to know the correct parent Composite.
I have to add a class to a component. I can't add the component via ajax because this is a problem with the input. My code is:
private ListView<Opzioni> setListOpzioni(boolean b) {
return new ListView<Opzioni>("list_opzioni", opzioniDao.findAll()) {
#Override
protected void populateItem(ListItem<Opzioni> item) {
erroriAssociatiAlTextField = new HashMap<>();
List<Opzioni> opzioniCron = opzioniDao.getOpzioniFormatore();
final Opzioni o = item.getModelObject();
final WebMarkupContainer errorContainer = new WebMarkupContainer("errorContainer");
errorContainer.setOutputMarkupId(true);
errorContainer.setOutputMarkupPlaceholderTag(true);
Boolean isSelected = false;
Boolean isAzienda = o.getAzienda() != null ? o.getAzienda().equals(getAziendaLogged()) : false;
if (isAdminFormatore(getUserLogged())) {
isSelected = o.getControlFormatore() || isAzienda;
} else {
isSelected = isAzienda;
}
Boolean visibile = isSa || isSelected;
Label name_op = new Label("name_op", o.getName());
item.add(name_op.setVisible(visibile));
TextField val_op = new TextField("val_op", new PropertyModel(o, "val"));
val_op.add(new OnChangeAjaxBehavior() {
#Override
protected void onUpdate(AjaxRequestTarget art) {
if (opzioniCron.contains(o)) {
controllaStringa(o);
}
if (valoriScorretti == true) {
contatore++;
} else {
contatore = 0;
}
if (contatore > 0) {
ciSonoErrori = true;
String error = "Valori inseriti nel box " + o.getName() + " non corretti";
if (!erroriAssociatiAlTextField.containsKey(o)) {
erroriAssociatiAlTextField.put(o, error);
}
for (Map.Entry<Opzioni, String> map : erroriAssociatiAlTextField.entrySet()) {
val_op.error(map.getValue());
}
art.add(errorContainer.setVisible(true));
refreshFp(art);
art.add(save_btn.setVisible(false));
} else {
ciSonoErrori = false;
if (!erroriAssociatiAlTextField.isEmpty()) {
art.add(save_btn.setVisible(false));
if (erroriAssociatiAlTextField.containsKey(o)) {
erroriAssociatiAlTextField.remove(o);
}
for (Map.Entry<Opzioni, String> map : erroriAssociatiAlTextField.entrySet()) {
val_op.error(map.getValue());
}
}
if (erroriAssociatiAlTextField.isEmpty()) {
art.add(save_btn.setVisible(true));
}
art.add(errorContainer.setVisible(false));
refreshFp(art);
}
}
});
item.add(val_op.setEnabled(b).setVisible(visibile));
item.add(errorContainer.setVisible(false));
if (visibile) {
o.setModificato(true);
} else {
o.setModificato(false);
}
}
};
}
With this code every time a user insert a letter inside the field the cursor go to the first position and it's impossible to use it. Is there an alternative mode to add the class dynamically?
With this code every time a user insert a letter inside the field the
cursor go to the first position and it's impossible to use it.
That is because of the OnChangeAjaxBehavior you are using.
This behavior checks after every user input if the FormComponent validates correct and if it does it will call the onUpdate method.
For a TextField without an IValidator added that means onUpdate is called after every input. If you then reprint the TextField via AjaxRequestTarget you get the behaviour of an input field where you type "backwards" as you currently do.
how can i modify attributes without adding the component in Wicket?
If you want you're changes to be visible in the browser then you need to update the component with ajax at some point. There is no way around it.
You probably have to rethink you're aproach because what you are currently doing doesn't make much sense.
At the moment you have a TextField and when the user enters something that is valid you add the css class "field-error" to the html input.
Shouldn't it be the other way around and the " field-error" should get added when the users enters something that is invalid?
Do you really want to validate and do an ajax update while the user enters something? Why not validate the input when the form/textfield actually gets submitted, or when the user is done typing into the field?
Edit
Instead of updating the input with the AjaxRequestTarget you could use the AjaxRequestTarget to send the jQuery command to add the css class to the input:
val_op.setOutputMarkupId(true);
val_op.add(new OnChangeAjaxBehavior() {
#Override
protected void onUpdate(AjaxRequestTarget art) {
art.appendJavaScript("$('#"+val_op.getMarkupId()+"').addClass('field-error');");
}
}
Instead of updating the whole input via ajax, this will just send a jQuery Javascript to be executed in the AjaxResponse. You can then just do the Javascript call in the page you linked and the adding of the css class will be done on client side.
The only thing you need is the id of your input so that jquery can find it. So setOutputMarkupId must be set to true and you can then get the id that wicket created by calling getMarkupId() and insert it into the javascript command.
As I already said it seems strange to me that you add the error-class in the onUpdate method. The correct way would seem to me to add the error class in the onError method (called when input is invalid) and remove it in the onUpdate (when input is valid).
val_op.setOutputMarkupId(true);
val_op.add(new OnChangeAjaxBehavior() {
#Override
protected void onUpdate(AjaxRequestTarget art) {
art.appendJavaScript("$('#"+val_op.getMarkupId()+"').removeClass('field-error');");
}
#Override
protected void onError(AjaxRequestTarget art, RuntimeException e) {
art.appendJavaScript("$('#"+val_op.getMarkupId()+"').addClass('field-error');");
}
}
i needed an Widget to display text properly, containing HTML elements. Therefore i used the GWT HTML-Widget like that.
HTML text= new HTML(new SafeHtml() {
#Override
public String asString() {
return "<b>TestText</b>";
}
});
Now i would like to select text displayed by that widget, and somehow get the String.
I would like to right click the marked text, and do something with that String
It's also no problem if your ideas making use of other gwt widgets, i am not too focused on that HTML one.
I also have access to Sencha GXT libarys.
Any ideas would be appreciated.
I'm assuming you want the user to select text and then retrieve the selected text on right click. Am I right? I don't recall any way of retrieving selected text in GWT, so I would use pure javascript for that. There is already a thread explaining how to do that with javascript, so you can grab that code and wrap it in a JSNI method:
public class MyClass implements IsWidget {
private final HTML text;
public MyClass() {
text = new HTML(SafeHtmlUtils.fromTrustedString("<b>Some text</b>"));
text.addDomHandler(new ContextMenuHandler() {
#Override
public void onContextMenu(ContextMenuEvent event) {
String test = getSelection();
Window.alert(test);
}
}, ContextMenuEvent.getType());
}
private native String getSelection() /*-{
var text = "";
if ($wnd.getSelection) {
text = $wnd.getSelection().toString();
} else if ($doc.selection && $doc.selection.type != "Control") {
text = $doc.selection.createRange().text;
}
return text;
}-*/;
#Override
public Widget asWidget() {
return text;
}
}
You can use sth like this:
final Label label = new Label("Some text");
label.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
label.getElement().getStyle().setBackgroundColor("#ff0"); //sth. like select
String txt = label.getText(); //get the String
Window.alert(txt); //do sth. with text
}
});
But it works on left click. If you have to use right click, you can use native JS code using eg. jQuery click.
And do not use b tag. It is deprecated in HTML5.
I've actually found a GWT-Libary that can get the selected text.
Watch this https://code.google.com/p/gwt-selection/
After installing the libary i just had to
String currentSelection = Selection.getBrowserRange().getText();
Thank you for answering though - you helped me a lot
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.