2012-04-26 55 views
2

所以这不是一个很普遍的问题,但我希望有些人可以给我一些关于体系结构的指导,以便我可以构建下列可重用的检票组件。构建可重复使用的检票组件

这里是skitch草图:

https://skitch.com/cmagnollay/8sn2s/multitextform

我知道,伟大的图画吧?所以本质上,这个表单组件(我认为这是正确的类)将被用来在表单上添加用户定义的输入数量。当用户点击TextInputField旁边的 - 按钮时,它将删除该inputField。当他们按下+按钮时,会添加一个新的空白字段。很显然,当用户单击按钮时,组件需要使用AJAX来更新组件,但我的问题是如何构造这个组件。这是一堂课吗?两个(一个用于整个组件,一个用于使用 - 按钮的inputfield),我应该使用什么类来执行此操作?我希望该对象尽可能通用以促进重用。以下是我迄今为止:

public class MultiTextInput<T> extends FormComponent<List<T>> 
{ 
    private static final long serialVersionUID = 1L; 

    private final String removeInputButtonName = "removeInputButton"; 
    private final String addInputButtonIdName = "addInputButton"; 

    private int numInputs = 1; 
    private List<TextField<T>> inputFieldList = new ArrayList<TextField<T>>(); 

    public MultiTextInput(String id, IModel<T> model) 
    { 
     super(id); 

     inputFieldList.add(new TextField<T>("input1", model)); 

     add(inputFieldList.get(0)); 
     addAddInputFieldMarkup(); 
    } 

    /** 
    * Adds an "add" button. 
    */ 
    private void addAddInputFieldMarkup() 
    { 
     Button addInputButton = new Button(this.addInputButtonIdName + numInputs); 
     addInputButton.add(new AjaxFormComponentUpdatingBehavior("onclick"){ 

      private static final long serialVersionUID = 1L; 

      @Override 
      protected void onUpdate(AjaxRequestTarget target) 
      { 
       numInputs++; 

       inputFieldList.add(new TextField<T>("input" + numInputs)); 

       target.add(MultiTextInput.this); 
      } 

     }); 
    } 

    /** 
    * Adds a "remove" button. 
    */ 
    private void addRemoveInputFieldMarkup() 
    { 
     Button removeInputButton = new Button(this.removeInputButtonName + numInputs); 
     removeInputButton.add(new AjaxFormComponentUpdatingBehavior("onclick"){ 

      private static final long serialVersionUID = 1L; 

      @Override 
      protected void onUpdate(AjaxRequestTarget arg0) 
      { 
       // TODO Auto-generated method stub 

      } 

     }); 
    } 


} 

正如我所说的,我只是想习惯于考虑做出Wicket组件。我在面向对象方面有很多经验,但并不特别关注门票。感谢您的帮助和指导!

回答

1

我猜最简单的方法来实现所需的行为将是使用列表支持的ListView。只需按下添加/删除按钮即可重新加载。

下面是一个代码涂鸦(未测试)

public abstract class MultiTextPanel<T> extends Panel { 

public MultiTextPanel(String id, IModel<ArrayList<T>> model) { 
    super(id, model); 

    final Form<ArrayList<T>> multiTextForm = new Form<ArrayList<T>>("multiTextForm", model); 
    add(multiTextForm); 

    final ListView<T> listView = new ListView<T>("listView", model) { 

     @Override 
     protected void populateItem(final ListItem<T> item) { 
      // TODO Auto-generated method stub 
      TextField<T> textField = new TextField<T>("textField", item.getModel()); 
      add(textField); 

      AjaxSubmitLink removeButton = new AjaxSubmitLink("removeButton", multiTextForm) { 

       @Override 
       protected void onSubmit(AjaxRequestTarget target, Form<?> form) { 
        multiTextForm.getModelObject().remove(item.getModelObject()); 
        target.addComponent(multiTextForm); 
       } 

       @Override 
       protected void onError(AjaxRequestTarget target, Form<?> form) { 
        //errors should be ignored, we shoudlnt validate in our form, so this shouldnt happen anyway 
        multiTextForm.getModelObject().remove(item.getModelObject()); 
        target.addComponent(multiTextForm); 
       } 

      };    
      add(removeButton); 

     } 

    }; 
    add(listView); 

    AjaxSubmitLink addButton = new AjaxSubmitLink("addButton", multiTextForm) { 

     @Override 
     protected void onError(AjaxRequestTarget target, Form<?> form) { 
      //errors should be ignored, we shoudlnt validate in our form, so this shouldnt happen anyway 
      multiTextForm.getModelObject().add(createNewT()); 
      target.addComponent(multiTextForm); 
     } 

     @Override 
     protected void onSubmit(AjaxRequestTarget target, Form form) { 
      multiTextForm.getModelObject().add(createNewT()); 
      target.addComponent(multiTextForm); 
     } 
    }; 
    add(addButton); 



} 

public abstract T createNewT();} 

基本的HTML:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.sourceforge.net/" xml:lang="en" lang="en"> 
<wicket:panel> 
    <form wicket:id="multiTextForm"> 
     <wicket:container wicket:id="listView"> 
      <input type="text" wicket:id="textField" /> 
      <a wicket:id="removeButton">-</a> 
     </wicket:container> 
    </form> 
    <a wicket:id="addButton">+</a> 
</wicket:panel> 

我这个做的唯一特殊的是把一种形式围绕ListView,因此我们只需在我们创建的Panel内提交(在此阶段最有可能不需要验证,并且应该以保存屏幕的形式进行验证)。

这个实现的缺点是你总会重新加载完整的表单,因此会产生大量的开销。只有1行被添加/删除,但n( -/+)1被重新渲染。

+0

这实际上应该是一个更大形式的输入组件。这就是为什么我认为我应该使用formcomponent作为超类。对不起,如果我不清楚我的问题,但让我看看listview文档。感谢您的回应! – thatidiotguy 2012-04-26 21:11:00

+0

嗯,我只是不明白为什么你会想要通过创建一个新的FormComponent的麻烦,如果你可以轻松实现与ListView相同的行为。但你可以看看FormComponentPanel(http://wicket.apache.org/apidocs/1.5/org/apache/wicket/markup/html/form/FormComponentPanel.html) – 2012-04-26 21:20:39

+0

啊我明白你的意思了。你的意思是我所寻找的行为与列表视图非常相似,甚至不值得它自己的对象。我会在早晨第一时间尝试编码。感谢您的努力和建议! – thatidiotguy 2012-04-26 21:50:02