在 Wicket 中检索表单的动态添加输入的值 [英] Retrieve values of dynamically added inputs of a form in Wicket

查看:25
本文介绍了在 Wicket 中检索表单的动态添加输入的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个 Wicket WebPage,它动态地构建具有多种不同输入类型的表单.可以添加文本文件、复选框和下拉列表.通过 ListView 和不同的 Panel 为每种类型添加不同的输入.表单的创建有效,但现在我不知道如何访问 onSubmit() 方法中输入的值.

I am building a Wicket WebPage that dynamically builds a form with multiple different input types. It is possible to add textfileds, checkboxes and dropdownlists. The different inputs are added via a ListView and different Panels for each type. The creation of the form works, but now I do not know how I can access the entered values in the onSubmit() method.

这是我页面的构造函数:

This the constructor of my page:

public AddJobPage(final PageParameters params) {
    super(params);

    final Workable w = WorkableManager.getInstance().findWorkableByName(params.get("workableName").toString());
    final List<FormElement> formElements = w.getParameterFormDescriptor();
    final ListView<FormElement> listView = new ListView<FormElement>("inputs", formElements) {

        @Override
        protected void populateItem(final ListItem<FormElement> item) {
            switch (item.getModelObject().getType()) {
            case TEXT:
                item.add(new TextFieldPanel("formElement", item.getModel()));
                break;
            case DROPDOWN:
                item.add(new DropDownPanel("formElement", item.getModel()));
                break;
            case CHECKBOX:
                item.add(new CheckBoxPanel("formElement", item.getModel()));
                break;
            default:
                break;
            }
        }
    };

    listView.setReuseItems(true);

    final Form<Void> parameterForm = new Form<Void>("parameterForm") {

        @Override
        protected final void onSubmit() {
            // What comes here?
        }

    };

    parameterForm.add(listView);
    add(parameterForm);
}

TextFieldPanel 定义如下:

public class TextFieldPanel extends Panel {

    public TextFieldPanel(final String id, final IModel<FormElement> model) {
        super(id, model);

        final FormElement el = model.getObject();
        final Label label = new Label("label", el.getLabel());
        final TextField<String> textfield = new TextField<>("textfield", Model.of(""));

        label.add(new AttributeModifier("for", el.getParamName()));
        textfield.add(new AttributeModifier("name", el.getParamName()));
        textfield.add(new AttributeModifier("id", el.getParamName()));

        add(label);
        add(textfield);
    }
}

FormElement 只是描述应该创建什么类型的输入.那么如何获取提交的值及其名称(来自 HTML 属性)?最后我想得到一个Map,其中键是名称,值是输入的值.

FormElement just describes what type of input should be created. So how do I get the submitted values together with their names (from the HTML-attribute)? In the end I want to get a Map<String, String>, where the key is the name and the value the entered value.

推荐答案

我相信您没有正确使用表单.

I believe you are not using the form correctly.

您缺少的要点是您应该尽可能多地使用模型.这是因为组件几乎总是期望使用某种数据,而这些数据通常取自模型.例如,TextField 的模型将是文本字段存储其输入的地方.对于 Label,它将是它从中获取显示值的地方.

The main point you're missing is that you should use models as much as you can. That's because components are pretty much always expected to work with some kind of data, and that data is usually taken from the model. So for example, a TextField's model will be the place where the text field stores it's input. For a Label, it'll be where it gets its display value from.

您在那里所做的是:您忽略了自动处理输入的 TextField 功能并尝试自己执行此操作.这是功能的重复,这不好.

What you are doing there, is this: you are ignoring the functionality of TextField which automatically handles input and trying to do this yourself. It's duplication of functionality, and that's not good.

您应该在那里做的是使用模型.首先,您应该在表单组件上使用模型,然后在 onSubmit 中您可以获取这些组件的模型以获取它们的输入.

What you should be doing there instead, is using models. To begin with, you should use models on your form components and then in onSubmit you could get the models of those components to get their input.

但是,如果您使用多个表单组件,则该方法不可行,因为您必须为 onSubmit() 中的每个组件检索模型的值.

However, that method is not feasible if you are using more than one form component, as you would have to retrieve the value of the model for each of those in onSubmit().

这是我们提出的解决方案的地方.

This is where we get to my proposed solution.

主要思想:在您的表单上使用一个模型,并将该模型传递给您的所有表单组件.然后,当提交表单时,wicket 会自动处理来自这些表单组件的输入并更新模型.由于该模型是表单的模型,因此在 onSubmit 中,您只需一个方法调用即可访问所有数据:

Main idea: use a model on your form, and pass that model to all of your form components. Then when the form is submitted, wicket automatically handles the input from those form components and updates the model. Since that model is the model of the form, in the onSubmit you can access all of the data in just one method call:

Object data = this.getModelObject();

当然,值不一定是Object,但我以它为例.

Of course, the value doesn't have to be an Object, but I'm using it as an example.

然而,在你的场景中还有一个困难;这是表单组件的动态数量.实现起来其实并不难,但是如果你想确定价值来自哪里,这取决于你的要求.我假设您没有,因为我认为这只是一些需求收集并继续进行该假设.

However, there is also one difficulty in your scenario; that is the dynamic number of form components. It is not actually difficult to achieve, but it depends on your requirements if you want to identify where the value came from. I assume that you don't, since I would imagine it's just some requirement gathering and proceed with that assumption.

从这里开始,您可以通过两种方式处理此问题:使用 ValueMap 模型,或使用具有可变大小的集合的自定义模型对象.我不太喜欢 ValueMap,所以我将跳过对此的解释,但是一旦您了解模型如何与表单一起工作,您应该能够解决它.

There are 2 ways you can handle this from here on: use a ValueMap model, or use a custom model object with collections, which will be variable size. I don't like ValueMap much, so I'm going to skip the explanation on that, but once you understand how models work with forms you should be able to work it out.

所以第二种方式.第一步是为您的表单创建一个模型对象.我将假设您只有一种类型的动态输入,因为添加其他类型的过程是相同的.因此,假设在您的页面上,您将拥有可变数量的 TextField 输入元素.

So the second way. The first step would be to create a model object for your form. I will assume that you will only have one type of dynamic input, because it's the same process for adding others. So let's say on your page you will have a variable number of TextField input elements.

 public class FormModel {
     private List<String> textFieldData = new ArrayList<>();

     public void setTextFieldData(List<String> textFieldData){
          this.textFieldData = textFieldData;
     }

     public List<String> getTextFieldData(){
          return textFieldData;
     }
 } 

然后当你创建表单时,指定一个模型作为表单的模型:

Then when you're creating your form, assign a model of this as the model of the form:

final Form<FormModel> parameterForm = new Form<FormModel>("parameterForm", Model.of(new FormModel());

现在是更复杂的部分.您使用的每个 TextField 都必须写入该集合并从中接收数据.我这样做的方法是分配一个唯一的整数 ID,它将作为它在集合上的索引,以确保它们中的每一个都不会覆盖其他输入.接下来,我们利用 wicket 的力量,为每个文本字段创建一个 PropertyModel,它将指向该集合中的一个元素,例如:

Now for the more complex part. Each TextField you use will have to write to that collection and receive data from it. My way of doing it would be to assign a unique integer ID which will be its index on the collection to ensure that each of them will not override the others input. Next, we employ wicket's power and we create a PropertyModel for each text field, which would point to an element in that collection, so something like:

 final TextField<String> textfield = new TextField<>("textfield", new PropertyModel(formModel, "textFieldData." + id));

其中 ID 是分配给此文本字段的唯一 ID,也是该集合的索引.

Where ID is the unique ID assigned to this textfield that is also the index on that collection.

以这种方式创建所有文本字段后,当表单成功验证并调用 onSubmit 时,表单模型将自动更新为文本字段的输入.在这种情况下,您只需在表单中使用 getModelObject() 即可检索写入所有值的 FormModel 类的对象.

Once you create all of your text fields this way, when the form is successfully validated and onSubmit is called, the model of the form will be updated with the input of the textfields automatically. In which case you can just use getModelObject() in your form to retrieve the object of FormModel class where all of the values are written.

我知道这需要考虑很多,实际上我可能在您尝试实现的目标上是错误的.但我相信,如果您打算继续使用 wicket,那么了解模型的工作原理将是最好的选择.模型是 Wicket 不可或缺的一部分,一旦您学会使用它们,它们就会很棒.我建议阅读这篇关于模型如何工作的文章,希望您将能够理解我要解释的内容.祝你一切顺利!

I understand this is a lot to take in, and I might actually be wrong in what you're trying to achieve. But I believe learning how the models work will be the best route to take if you plan to continue using wicket; Models are an integral part of Wicket and they are great once you learn to use them. I suggest reading this piece about how models work and hopefully you'll be able to wrap your head around what I'm trying to explain. All the best of luck to you!

还有一件事;在您的代码中,您分配一个 AttributeModifier 来设置 TextField 上的 ID 属性.这通常是不可取的;您应该改为使用 getMarkupID() 并在其他组件中使用默认标记 ID,而不是将您自己的标记 ID 分配给文本字段.

One more thing; in your code you assign an AttributeModifier that sets the ID attribute on your TextField. That generally is not advisable; you should instead use getMarkupID() and use the default markup ID in other components, rather than assigning your own to the textfield.

这篇关于在 Wicket 中检索表单的动态添加输入的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆