I am having a bit of trouble making a required form field update from an
ajax button.

The field is marked required and has an OnChangeAjaxBehavior.

The user deletes the contents of the field
Presses an AjaxButton (todo some DB work which yields a new value)
Ajax button sets a new value,
The updated value is not pushed to the screen.


I've got a quick start example.
Tested with Wicket 1.5.5

All help is appreciated.



==== HomePage.java ====

package com.mycompany;

import java.math.BigDecimal;
import java.util.Locale;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.util.convert.IConverter;

public class HomePage extends WebPage {

  /**
   * Simulate values from the DB
   */
  private BigDecimal fromDBWith = BigDecimal.valueOf(500);
  private BigDecimal fromDBWithout = BigDecimal.valueOf(600);


  private BigDecimal withPrice = BigDecimal.valueOf(100);
  private BigDecimal withoutPrice = BigDecimal.valueOf(200);


  Model<BigDecimal> withModel = new Model<BigDecimal>() {
    @Override public BigDecimal getObject() { return withPrice; }
    @Override public void setObject(BigDecimal newVal) { withPrice =
newVal; }
  };

  Model<BigDecimal> withoutModel = new Model<BigDecimal>() {
    @Override public BigDecimal getObject() { return withoutPrice; }
    @Override public void setObject(BigDecimal newVal) { withoutPrice =
newVal; }
  };




  public HomePage(final PageParameters parameters) {

    Form form = new Form("someForm");
    add(form);

    final FeedbackPanel feedback = new FeedbackPanel("feedback");
    feedback.setOutputMarkupId(true);
    form.add(feedback);

    final MoneyTextField withTF = new MoneyTextField("withTF", withModel);
    withTF.setOutputMarkupId(true);

    // Required AND OnChangeAjaxBehavior means I cant update the form field
from the button
    // when the field is empty.
    withTF.setRequired(true);
    withTF.add(new OnChangeAjaxBehavior() {
      @Override public void onUpdate(AjaxRequestTarget art) {
        System.out.println("In withTF onUpdate " + withPrice);
      }
    });
    form.add(withTF);


    final MoneyTextField withoutTF = new MoneyTextField("withoutTF",
withoutModel);
    withoutTF.setRequired(true);
    withoutTF.setOutputMarkupId(true);
    form.add(withoutTF);

    AjaxLink withBtn = new AjaxLink("withBtn") {

      @Override
      public void onClick(AjaxRequestTarget art) {
        System.out.println("In withBtn onClick " + withPrice);
        fromDBWith = fromDBWith.add(BigDecimal.ONE);
        withPrice = fromDBWith;
        art.add(withTF, feedback);
      }
    };
    form.add(withBtn);


    AjaxLink withoutBtn = new AjaxLink("withoutBtn") {
      @Override
      public void onClick(AjaxRequestTarget art) {
        System.out.println("In withoutBtn onClick " + withoutPrice);
        fromDBWithout = fromDBWithout.add(BigDecimal.ONE);
        withoutPrice = fromDBWithout;
        art.add(withoutTF, feedback);
      }
    };
    form.add(withoutBtn);
  }
}


/**
 *
 * @author peter
 */
class MoneyTextField extends TextField<BigDecimal> {


  public MoneyTextField(String id, IModel<BigDecimal> model) {
    super(id, model, BigDecimal.class);
    add(AttributeModifier.append("class", "money"));
  }

  @Override public String getInputType() { return "number"; }

  @Override public <C> IConverter<C> getConverter(Class<C> ctype) {
    if (BigDecimal.class.isAssignableFrom(ctype)) {
      MoneyConverter mc = new MoneyConverter(false, false);

      IConverter<C> res = (IConverter<C>)mc;
      return res;
      //return mc.asInstanceOf<IConverter<C>>;
    } else {
      System.out.println("MoneyConverter NOT ASSIGNABLE FROM " + ctype);
      return super.getConverter(ctype);
    }
  }
}

/**
 *
 * @author peter
 */
class MoneyConverter implements IConverter<BigDecimal> {

  private Boolean blankWhenZero = false;
  private Boolean negativeShowCR = false;

  public MoneyConverter(Boolean blankWhenZero, Boolean negativeShowCR)  {
    this.blankWhenZero = blankWhenZero;
    this.negativeShowCR = negativeShowCR;
  }

  @Override public BigDecimal convertToObject(String string, Locale locale)
{
    //if (StringUtils.isBlank(string)) {
    if (string==null || string.length()==0) {
      //return BigDecimal.ZERO;
      return null;
    }
    return new BigDecimal(string);
  }

  @Override public String convertToString(BigDecimal o, Locale locale) {

    System.out.println("MoneyConverter o=" + o);

    if (o==null) {
      return "";
    }

    if (blankWhenZero && o.compareTo(BigDecimal.ZERO)==0) {
      return "";
    }

    if (negativeShowCR && o.compareTo(BigDecimal.ZERO)<0) {
      return String.format("%.2f CR", o.abs());
    }

    return String.format("%.2f", o);
  }
}



===== HomePage.html =====
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org";>
    <head>
        <meta charset="utf-8" />
        <title>Apache Wicket Quickstart</title>
        <link href='
http://fonts.googleapis.com/css?family=Yanone+Kaffeesatz:regular,bold'
rel='stylesheet' type='text/css' />
        <link rel="stylesheet" href="style.css" type="text/css"
media="screen" title="Stylesheet" />
    </head>
    <body>

    <form wicket:id="someForm">

      <div wicket:id="feedback"></div>

      <table>

        <tr>
          <td>With OnUpdate</td>
          <td>Without OnUpdate</td>
        </tr>

        <tr>
          <td><input wicket:id="withTF" type="number"></td>
          <td><input wicket:id="withoutTF" type="number"></td>
        </tr>

        <tr>
          <td><button wicket:id="withBtn">Press Me</button></td>
          <td><button wicket:id="withoutBtn">Press Me</button></td>
        </tr>

        <tr>
          <td>
            This TextField has required=True and an OnChangeAjaxBehavior<br>
            Press Button, everything works fine<br>
            Empty the text field (blank value), then press button,<br>
            field does not get updated to the value loaded from the DB
          </td>
          <td>
            This TextField has required=True but no OnChangeAjaxBehavior<br>
            Press Button, everything works fine<br>
            empty the text field, then press button updates OK.
          </td>
        </tr>


        <tr>
          <td colspan="2">
            Is this a bug or am I doing something wrong?
          </td>
        </tr>

      </table>
    </form>


    </body>
</html>




-- 
Peter Henderson

Reply via email to