Hi @all,

i try to use an AjaxFormLoop to implement a dynamic filter component.
U can interactively add or remove new single filter to a filter form.

Every single filter row has a select to specify the column.
This select replace the input field for the filter expression depending on
the column type with an ajax zone update.

If i try to place a DateField in this scenario i got an parse error after i
click
on the calendar icon of the added DateField, see here

http://postimg.org/image/c57601flj/

It looks like the DateField.js use the hidden "t:formdata input" of the
DateField for reading and writing, which is as far as i understood wrong.


Any ideas, how i can fix this issue???

Kind regards


simple code to (hopefully) reproduce the error:

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.tapestry5.Block;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.annotations.InjectComponent;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.corelib.components.Zone;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.SelectModelFactory;
import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;


public class TestAjaxFormLoopWithDateField {


  public enum TempType {
    TEXT,
    DATE
  }

  public class Filter {

    private int id;
    private Date date;
    private TempType type;
    private String value;

    public Filter() {
    }

    public Filter(int id, Date date, TempType type) {
      this.setId(id);
      this.setDate(date);
      this.setType(type);
    }

    /**
     * @return the date
     */
    public Date getDate() {
      return date;
    }

    /**
     * @param date
     *          the date to set
     */
    public void setDate(Date date) {
      this.date = date;
    }

    /**
     * @return the id
     */
    public int getId() {
      return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(int id) {
      this.id = id;
    }

    /**
     * @return the type
     */
    public TempType getType() {
      return type;
    }

    /**
     * @param type the type to set
     */
    public void setType(TempType type) {
      this.type = type;
    }

    /**
     * @return the value
     */
    public String getValue() {
      return value;
    }

    /**
     * @param value the value to set
     */
    public void setValue(String value) {
      this.value = value;
    }
  }

  // useful services

  @Inject
  private Request request;

  @Inject
  private AjaxResponseRenderer ajaxResponseRenderer;

  /*
   * Screen fields
   */

  @Property
  @Persist
  private List<Filter> filters;

  @Property
  private Filter curFilterBean;

  @InjectComponent
  private Zone inputFieldZone;

  @Inject
  private SelectModelFactory selectModelFactory;

  @Inject
  private Block stringValueBlock, dateValueBlock;

  void setupRender() {
    filters = new ArrayList<TestAjaxFormLoopWithDateField.Filter>();
    if (filters.isEmpty())
      filters.add(new Filter(1, null, TempType.TEXT));
  }

  public ValueEncoder<Filter> getFilterEncoder() {
    return new ValueEncoder<Filter>() {

      @Override
      public Filter toValue(String clientValue) {
        return filters.get(Integer.parseInt(clientValue));
      }

      @Override
      public String toClient(Filter value) {
        return String.valueOf(filters.indexOf(value));
      }
    };
  }

  /**
   * Get unique client side id for zone of input field for
   * {@link #curFilterBean}.
   *
   * @return {@code non-empty} unique client side id
   */
  public String getFieldZoneId() {
    return "inputField" + getFilterEncoder().toClient(curFilterBean);
  }

  /**
   * Get block for type of {@link #curFilterBean}.
   *
   * @return {@code not null} block
   */
  public Block getCase() {

    Block result = stringValueBlock;

    if (curFilterBean != null && curFilterBean.getType() != null) {
      switch (curFilterBean.getType()) {
      case DATE:
        result = dateValueBlock;
        break;
      }
    }

    return result;
  }

  /**
   * Create new {@link Filter} and add it to the list.
   *
   * @return {@code not null} {@link Filter}
   */
  Filter onAddRow() {
    Filter fbean = new Filter();
    fbean.setId(this.filters.size());
    filters.add(fbean);

    return fbean;
  }

  /**
   *
   * @param newType
   * @param filterBeanId
   */
  void onValueChangedFromTypeSelect(TempType newType, int filterBeanId) {

    for (Filter curFilterBean : filters) {
      if (curFilterBean.getId() == filterBeanId) {
        this.curFilterBean = curFilterBean;
        break;
      }
    }

    if (request.isXHR()) {
      ajaxResponseRenderer.addRender(inputFieldZone);
    }
  }
}




<html t:type="mintLayout"
  title="test AjaxFormLoop"
  xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd";
  xmlns:p="tapestry:parameter">

    <t:form>
      <t:ajaxformloop t:id="searchRefine" t:source="filters"
t:value="curFilterBean" t:encoder="filterEncoder" >
        <t:if test="curFilterBean">
          <div class="row">
            <div class="col-xs-5">
              <t:select t:id="typeSelect" t:value="curFilterBean.type"
t:zone="prop:fieldZoneId"
                  t:context="curFilterBean.id" />
            </div>
            <div class="col-xs-5">
                <t:zone t:id="inputFieldZone" id="prop:fieldZoneId">
                  <t:delegate to="case"/>
                </t:zone>
            </div>
            <div class="col-xs-2">
                <t:removerowlink>
                  <p class="form-control-static">remove</p>
                </t:removerowlink>
            </div>
          </div>
        </t:if>

        <p:addRow>
          <t:addrowlink>Add</t:addrowlink>
        </p:addRow>
      </t:ajaxformloop>
    </t:form>

    <t:block t:id="stringValueBlock">
      <input t:type="textField" t:value="curFilterBean.value" />
    </t:block>

    <t:block t:id="dateValueBlock">
      <t:DateField t:value="curFilterBean.date" />
    </t:block>

</html>

Reply via email to