I'm having trouble to adding input validation for a double in wicket when useing an ajaxEditableLabel.
This is my code: (item is a listitem from a listview)
item.add(new AjaxEditableLabel("myDouble", new Model(myObject.getMyDouble())) {
#Override
protected void onSubmit(AjaxRequestTarget target) {
super.onSubmit(target);
myObject.setMyDouble(new Double(getEditor().getInput())); //here it fails to read the input when a use enters a wrong number
//Do something when it's a double
}
});
How can I add a validator to this component to check wheter this a double value?
At the moment I'm using:
Double.parseDouble(myval);
With try catch...
But this also needs the input string to be changed because of , and .
There should be a wicket way to validate this input?
Edit**:
Maybe I have to add NumericTextField to this component but I don't understand how.
Check this:
Java:
public class MyPage extends WebPage {
private List<Double> list = Arrays.asList(2013.0, 100.500);
public MyPage() {
final FeedbackPanel feedback = new FeedbackPanel("feedback");
feedback.setOutputMarkupId(true);
add(feedback);
ListView<Double> items = new ListView<Double>("items", new PropertyModel(this, "list")) {
#Override
protected void populateItem(ListItem<Double> item) {
item.add(new AjaxEditableLabel("item", item.getModel()) {
#Override
protected void onSubmit(AjaxRequestTarget target) {
System.out.println(Arrays.toString(list.toArray()));
target.add(feedback);
super.onSubmit(target);
}
#Override
protected void onError(AjaxRequestTarget target) {
target.add(feedback);
super.onError(target);
}
}.add(new IValidator<Object>() {
#Override
public void validate(IValidatable<Object> validatable) {
String in = String.valueOf(validatable.getValue());
try {
Double.parseDouble(in.replace(".", ","));
} catch (Exception ignore) {
try{
Double.parseDouble(in.replace(",", "."));
}catch (Exception e){
ValidationError error = new ValidationError(String.format("`%s` is not a Double", in));
validatable.error(error);
}
}
}
}));
}
};
add(items);
}
}
Markup:
<div wicket:id="feedback"/>
<ul wicket:id="items">
<li wicket:id="item"></li>
</ul>
The validator above made just for demonstration, in real code I suggest to create a separate class (not an anonimous class).
I solved by changing getInput to getConvertedInput(); This was my old way of solving it.
Using getModelObject() is better and since the Type is set to Double this is better.
I've also changed the type to Double. .setType(Double.class
item.add(new AjaxEditableLabel("myDouble", new Model(myObject.getMyDouble())) {
#Override
protected void onSubmit(AjaxRequestTarget target) {
super.onSubmit(target);
myObject.setMyDouble((Double)getEditor().getModelObject())); //changes here!!!
//Do something when it's a double
}
}.setType(Double.class));
Related
I am building an app that will be submitting the details of your siblings to the database.
MY idea is since i dont know number of your children, i just have a floating button that am using to call a class that adds a contaner with some textFields to be filled.
so I have like a Form here....
private Button btnSubmit;
private Container cnt_box;
public class ChildrenForm extends Form
{
private List<Child> listofchildren;
public ChildrenForm()
{
super("CHILDREN DETAILS",BoxLayout.y());
FloatingActionButton fab=FloatingActionButton.createFAB(FontImage.MATERIAL_ADD);
fab.bindFabToContainer(this);
fab.addActionListener((e) -> addNewChild());
getToolbar().addMaterialCommandToRightBar("", FontImage.MATERIAL_CLEAR_ALL, (e) ->
clearAll());
btnSubmit=new Button("Submit");
cnt_box = new Container(new BoxLayout(BoxLayout.Y_AXIS));
cnt_box.add(btnSubmit);
add(cnt_box);
}
//....here i have some other methods...
}
i have a method to enable the editing here....
public void edit()
{
txtname.startEditingAsync();
txtname3.startEditingAsync();
txtbirth.startEditingAsync();
txtdbirth.startEditingAsync();
}
the floatingAction Button calls this method here....
public void addNewChild()
{
Childdetails td=new Childdetails("","","","",false);
add(td);
revalidate();
td.edit();
}
that method now called this class which i want to take the details showing this container.....
public class Childdetails extends Container
{
private TextField txtname;
private TextField txtname3;
private TextField txtbirth;
private TextField txtdbirth;
private CheckBox done=new CheckBox();
private Container cnt_child;
public Childdetails(String name,String name3,String birthcertno,String dateofbirth ,boolean checked)
{
super(new BorderLayout());
cnt_child=new Container();
cnt_child.addComponent(new Label("First Name"));
txtname = new TextField(name);
txtname.setHint("First Name");
cnt_child.addComponent(txtname);
cnt_child.addComponent(new Label("Surname"));
txtname3 = new TextField(name3);
txtname3.setHint("Surname");
cnt_child.addComponent(txtname3);
cnt_child.addComponent(new Label("Birth Certificate/Notification No"));
txtbirth = new TextField(birthcertno);
txtbirth.setHint("Birth Certificate No:");
cnt_child.addComponent(txtbirth);
cnt_child.addComponent(new Label("Date of Birth"));
txtdbirth = new TextField(dateofbirth);
txtdbirth.setHint("dd/MM/yyyy");
cnt_child.addComponent(txtdbirth);
add(CENTER,cnt_child);
add(LEFT,done);
done.setSelected(checked);
}
public void edit()
{
txtname.startEditingAsync();
txtname3.startEditingAsync();
txtbirth.startEditingAsync();
txtdbirth.startEditingAsync();
}
public boolean isChecked(){
return done.isSelected();
}
public String getText(){
return txtname.getText();
}
}
this is the method which am using to delate any selected container....but i understand its because of that save method......
private void clearAll()
{
int cc=getContentPane().getComponentCount();
for(int i=cc-1; i>=0; i--)
{
Childdetails t=(Childdetails)getContentPane().getComponentAt(i);
if(t.isChecked())
{
t.remove();
}
}
save();
getContentPane().animateLayout(300);
}
the save method....which after following some tutorial i believe its saving the taken data.... here
private void save()
{
listofchildren = new ArrayList<>();
Childdetails detail=new Childdetails("","","","",false);
Child child=new Child()
.name.set(detail.getText())
.name3.set(detail.getText())
.birthcertno.set(detail.getText())
.dateofbirth.set(detail.getText())
.checked.set(detail.isChecked());
listofchildren.add(child);
PropertyIndex.storeJSONList("child.json", listofchildren);
}
i also have a class i constructed following certain tutorial to save the data.....here
public class Child implements PropertyBusinessObject
{
public final Property<String,Child> name=new Property<>("firstname","");
public final Property<String,Child> name3=new Property<>("Surname","");
public final Property<String,Child> birthcertno=new Property<>("BirthCertNo","");
public final Property<String,Child> dateofbirth=new Property<>("dateofbirth","");
public final BooleanProperty<Child> checked=new BooleanProperty<>("checked", false);
private final PropertyIndex idx=new PropertyIndex(this,"Todo", name, name3, birthcertno, dateofbirth, checked);
#Override
public PropertyIndex getPropertyIndex(){
return idx;
}
now my main main problem... i just want when that submit button is pressed, to send the filled details..... i tried this,,,
btnSubmit.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent evt)
{
Log.p("Button pressed", 1);
save();
Log.p("data saved...", 1);
if(existsInStorage("child.json"))
{
Log.p("loading data ...", 1);
listofchildren=new Child().getPropertyIndex().loadJSONList("child.json");
String NationalID=Storage.getInstance().readObject("NationalID").toString();
String UserName=Storage.getInstance().readObject("UserName").toString();
Hashtable hash=new Hashtable();
hash.put("ChildDet", listofchildren);
hash.put("ReadIdCopy", NationalID);
hash.put("UserName",UserName);
final Result res=Result.fromContent(hash);
final String checkthis=res.toString();
//--------check url......
String myUrl="http://localhost:50111/AddChildren";
String Reply="";
requestclass c=new requestclass();
try {
Reply=c.checking(checkthis,myUrl);
} catch (IOException ex) {
// Logger.getLogger(AddChildren.class.getName()).log(Level.SEVERE, null, ex);
} catch (requestclass.JSONException ex) {
// Logger.getLogger(AddChildren.class.getName()).log(Level.SEVERE, null, ex);
}
if(Reply.equals("SuccesfullyRecieved"))
{
Dialog.show("SuccesfullyRecieved", "Details Succesfuly Recieved", "OK", null);
/*----redirect---*/
nextofkin nkin=new nextofkin();
nkin.nxtofkscreen();
}
else if(Reply.equals("sorry"))
{
Dialog.show("SORRY!!!", "Seems their is a problem updating Next of kin details... try again", "OK", null);
}
else
{
Dialog.show("Error", "Something went wrong, try checking your connection and try again later.", "OK", null);
}
}
else
{
ToastBar.showErrorMessage("Sorry, no data to submit....");
}
}
});
i dont know how to do it,,,, also my save method has some errors...please help me out, thanks in advance
This is caused by this line:
Childdetails t=(Childdetails)getContentPane().getComponentAt(i);
What you are doing here is looping over all the components in the content pane and downcasting them to Childdetails.
This is bad. You don't check instanceof which would be helpful. You might have other problems but this line:
add(cnt_box);
Specifically adds a non Childdetails component to the content pane (doing add without a context on a Form implicitly adds to the content pane).
Also about startEditingAsync. This is wrong.
This isn't the way to make them visible.
Notice your code adds a lot of components before the form is shown and uses animateLayout on these instances. This is probably why things aren't visible since you do that on a Form that isn't shown yet (from the constructor) and so the animation "runs" without any effect. The components are probably in the wrong area.
I suggest removing that whole block of startEditingAsync and also try:
if(getContentPane().isInitialized()) {
getContentPane().animateLayout(300);
}
I am trying to set up a unit test for an Ajax behavior that I have added to a DropDownChoice component. When I make a call to tester.executeAjaxEvent(…) the DropDownChoice model value gets reset to “null”. I am not understanding something fundamental on how ajax works in wicket. Can anybody help me out here? Why is triggering the "change" event, causing the component to set it's model to null.
DropDownPage.html
<?xml version="1.0" encoding="UTF-8"?>
<html>
<head>
<title>DropDownPage</title>
</head>
<body>
<form wicket:id="form">
<select wicket:id="dropDown">
<option>Option 1</option>
</select>
</form>
</body>
</html>
DropDownPage.java
public class DropDownPage extends WebPage {
private static final Logger log = LogManager.getLogger(DropDownPage.class);
public DropDownPage() {
Form<Void> form = new Form<Void>("form");
add(form);
DropDownChoice<String> dropDown = new DropDownChoice<String>("dropDown", new Model<String>(new String()), Arrays.asList(new String[] { "A", "B" }));
dropDown.setOutputMarkupId(true);
dropDown.add(new AjaxFormComponentUpdatingBehavior("change") {
#Override
protected void onUpdate(AjaxRequestTarget target) {
String choice = dropDown.getModelObject();
if (choice == null) {
nullCall(target);
return;
}
switch (choice) {
case "A":
doAStuff(target);
break;
case "B":
doBStuff(target);
break;
default:
unknownType(target);
}
}
});
form.add(dropDown);
}
protected void doAStuff(AjaxRequestTarget target) {
log.info("doAStuff(...)");
}
protected void doBStuff(AjaxRequestTarget target) {
log.info("doBStuff(...)");
}
protected void nullCall(AjaxRequestTarget target) {
log.info("nullCall(...)");
}
protected void unknownType(AjaxRequestTarget target) {
log.info("unknownType(...)");
}
}
TestDropDownAjax.java
public class TestDropDownAjax {
private WicketTester tester;
#Before
public void setup() throws Exception {
tester = new WicketTester();
}
#After
public void tearDown() {
tester.destroy();
}
int aCount = 0;
int nullCount = 0;
#SuppressWarnings("unchecked")
#Test
public void testDropDownPage() {
DropDownPage dropDownPage = new DropDownPage() {
#Override
protected void doAStuff(AjaxRequestTarget target) {
super.doAStuff(target);
++aCount;
}
#Override
protected void nullCall(AjaxRequestTarget target) {
super.nullCall(target);
++nullCount;
}
};
DropDownChoice<String> dropDown = (DropDownChoice<String>) dropDownPage.get("form:dropDown");
assertNotNull(dropDown);
List<String> choices = (List<String>) dropDown.getChoices();
String choice = choices.get(0);
dropDown.setModelObject(choice);
tester.startPage(dropDownPage);
tester.assertModelValue("form:dropDown", dropDown.getModelObject());
assertEquals(choice, dropDown.getModelObject());
assertEquals(0, nullCount);
assertEquals(0, aCount);
tester.executeAjaxEvent("form:dropDown", "change");
assertEquals(0, nullCount); // fails here
assertEquals(1, aCount);
}
}
The AjaxFormComponentUpdatingBehavior, prior to calling your update method, calls the internal method inputChanged. This method tries to turn the latest user input into a new value for the dropdown's model. Since you didn't actually input anything new, this will be interpreted as selecting the empty option, causing the model value to become null.
As such, you need to do the form input through WicketTester as well.
One way to do this, is through FormTester:
FormTester formTester = tester.newFormTester("form");
formTester.select("dropDown", 0);
tester.executeAjaxEvent("form:dropDown", "change");
This will make your test pass.
I have the following ButtonCell. How do I make it respond to a click please (e.g., addClickHandler)? I have tried a number of ways I have found yet none work. None of the Window.alert return a response.
ButtonCell selectButton = new ButtonCell();
Column <HikingMeals,String> update = new Column <HikingMeals,String>(selectButton){
#Override
public String getValue(HikingMeals selectButton)
{
return "Select";
}
public void execute(HikingMeals selectButton) {
// EDIT CODE
Window.alert("Pressed");
}
//#Override
public void update(int index, HikingMeals object, String value) {
// The user clicked on the button for the passed auction.
Window.alert("Pressed2");
}
};
table.addColumn(update, "Select");
You just need to set a FieldUpdater on the update column:
update.setFieldUpdater(new FieldUpdater<HikingMeals, String>() {
#Override
public void update(int index, HikingMeals object, String value) {
Window.alert("Pressed");
}
});
I have an object, Supply, that can either be an ElecSupply or GasSupply (see related question).
Regardless of which subclass is being edited, they all have a list of BillingPeriods.
I now need to instantiate N number of BillingPeriodEditors based on the contents of that list, and am pretty baffled as to how I should do it.
I am using GWTP. Here is the code of the SupplyEditor I have just got working:
public class SupplyEditor extends Composite implements ValueAwareEditor<Supply>
{
private static SupplyEditorUiBinder uiBinder = GWT.create(SupplyEditorUiBinder.class);
interface SupplyEditorUiBinder extends UiBinder<Widget, SupplyEditor>
{
}
#Ignore
final ElecSupplyEditor elecSupplyEditor = new ElecSupplyEditor();
#Path("")
final AbstractSubTypeEditor<Supply, ElecSupply, ElecSupplyEditor> elecSupplyEditorWrapper = new AbstractSubTypeEditor<Supply, ElecSupply, ElecSupplyEditor>(
elecSupplyEditor)
{
#Override
public void setValue(final Supply value)
{
setValue(value, value instanceof ElecSupply);
if(!(value instanceof ElecSupply))
{
showGasFields();
}
else
{
showElecFields();
}
}
};
#Ignore
final GasSupplyEditor gasSupplyEditor = new GasSupplyEditor();
#Path("")
final AbstractSubTypeEditor<Supply, GasSupply, GasSupplyEditor> gasSupplyEditorWrapper = new AbstractSubTypeEditor<Supply, GasSupply, GasSupplyEditor>(
gasSupplyEditor)
{
#Override
public void setValue(final Supply value)
{
setValue(value, value instanceof GasSupply);
if(!(value instanceof GasSupply))
{
showElecFields();
}
else
{
showGasFields();
}
}
};
#UiField
Panel elecPanel, gasPanel, unitSection;
public SupplyEditor()
{
initWidget(uiBinder.createAndBindUi(this));
gasPanel.add(gasSupplyEditor);
elecPanel.add(elecSupplyEditor);
}
// functions to show and hide depending on which type...
#Override
public void setValue(Supply value)
{
if(value instanceof ElecSupply)
{
showElecFields();
}
else if(value instanceof GasSupply)
{
showGasFields();
}
else
{
showNeither();
}
}
}
Now, as the list of BillingPeriods is a part of any Supply, I presume the logic for this should be in the SupplyEditor.
I got some really good help on the thread How to access PresenterWidget fields when added dynamically, but that was before I had implemented the Editor Framework at all, so I think the logic is in the wrong places.
Any help greatly appreciated. I can post more code (Presenter and View) but I didn't want to make it too hard to read and all they do is get the Supply from the datastore and call edit() on the View.
I have had a look at some examples of ListEditor but I don't really get it!
You need a ListEditor
It depends of how you want to present them in your actual view, but the same idea apply:
public class BillingPeriodListEditor implements isEditor<ListEditor<BillingPeriod,BillingPeriodEditor>>, HasRequestContext{
private class BillingPeriodEditorSource extends EditorSource<BillingPeriodEditor>{
#Override
public EmailsItemEditor create(final int index) {
// called each time u add or retrive new object on the list
// of the #ManyToOne or #ManyToMany
}
#Override
public void dispose(EmailsItemEditor subEditor) {
// called each time you remove the object from the list
}
#Override
public void setIndex(EmailsItemEditor editor, int index) {
// i would suggest track the index of the subeditor.
}
}
private ListEditor<BillingPeriod, BillingPeriodEditor> listEditor = ListEditor.of(new BillingPeriodEditorSource ());
// on add new one ...
// apply or request factory
// you must implement the HasRequestContext to
// call the create.(Proxy.class)
public void createNewBillingPeriod(){
// create a new one then add to the list
listEditor.getList().add(...)
}
}
public class BillingPeriodEditor implements Editor<BillingPeriod>{
// edit you BillingPeriod object
}
Then in you actual editor edit as is in the path Example getBillingPeriods();
BillingPeriodListEditor billingPeriods = new BillingPeriodListEditor ();
// latter on the clickhandler
billingPeriods.createNewBillingPeriod()
You are done now.
I have code like this:
TextBox txt = new TextBox(){
public void onLoad(){
this.addFocusHandler(new FocusHandler(){
//some codes here
//if I use "this" keyword, it refers to the handler, but how can I get a reference to the textbox?
});
}
};
Question is embedded in the position.
Edit:
In respect to the answers, the creation of a pre-defined reference works for this situation, but this apparently lost (or at least reduce) the benefits of anonymous object/function.
I hope to find a way without creating a new reference. Rather just to get the reference from that scope.
After all the answers, here is a conclusion:
Reflection does not work in GWT. (at least I did not succeed) obj.getClass() works, but others like getMethods() or getEnclosingClass() don't work.
The way to get a reference can either be declaring a reference in the right scope, or get a higher level object reference and reference downwards. I prefer the latter simply because you don't need to create a new variable.
TextBox txt = new TextBox(){
public void onLoad(){
final TextBox finalThis = this;
this.addFocusHandler(new FocusHandler(){
finalThis.doSomething();
);
}
};
The enclosing instance of a non-static inner class (anonymous or named) in Java is available as ClassName.this, i.e.
TextBox txt = new TextBox(){
public void onLoad(){
this.addFocusHandler(new FocusHandler(){
doSomethingCleverWith(TextBox.this);
});
}
};
This has worked for me in the past. It works in client side js too. Here is a reference to more detail
What is the difference between Class.this and this in Java
public class FOO {
TextBox txt = new TextBox(){
public void onLoad(){
this.addFocusHandler(new FocusHandler(){
#Override
public void onFocus(FocusEvent event) {
FOO.this.txt.setHeight("100px");
}
});
}
};
}
This may work for you:
TextBox txt = new TextBox(){
public void onLoad(){
final TextBox ref = this;
this.addFocusHandler(new FocusHandler(){
public void doSomething(){
//some codes
ref.execute();
}
});
}
};
But I prefer to migrate inner classes to named classes:
public class Test {
public void demo(){
TextBox txt = new TextBox(){
public void onLoad(){
this.addFocusHandler(new DemoFocusHandler(this));
}
};
}
}
External FocusHandler:
public class DemoFocusHandler extends FocusHandler {
private TextBox textBox;
public DemoFocusHandler(TextBox textBox){
this.textBox = textBox;
}
public void doSomething(){
//some codes
textBox.execute();
}
}
If gwt supported reflection you could do something along the lines of this:
final TextBox txt = new TextBox() {
public void onLoad() {
final Object finalThis = this;
this.addFocusHandler(new FocusHandler() {
#Override
public void onFocus(FocusEvent event) {
try {
Method method= finalThis.getClass().getMethod("getVisibleLength");
method.invoke(finalThis);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
};
Without reflection the existing answers are you best bet. There are two gwt reflection projects gwt reflection and gwt-preprocessor both are in beta and I have not tried them.