取消设置 ajaxcheckbox 时,列表视图中的 wicket 文本区域会被清除

发布于 2024-12-09 19:03:47 字数 2968 浏览 0 评论 0原文

我使用 wicket listview 为每一行创建了一个复选框和一个文本字段。

当用户选择复选框时,我可以设置相关的布尔值 成功了。

但我需要施加限制。只能有一个复选框 选择提交以下结构的表格。

文本区域复选框 文本区域复选框 文本区域复选框 文本区域复选框

当我取消设置所选的复选框时,我在文本区域中输入的文本将被删除。 据我所知,以下行用于防止此问题,但它不起作用。你有什么想法吗?

listView.setReuseItems(true); 

 

public class CheckBoxListPage extends WebPage {      
    private Form inputForm; 

    public CheckBoxListPage() 
    { 
            add(inputForm = new InputForm("inputForm")); 
    } 

    private class InputForm extends Form 
    {  
            private List<NameWrapper> data; 

            public InputForm(String name) 
            { 
                    super(name);                    
                    data = new ArrayList<NameWrapper>(); 
                    data.add(new NameWrapper("one")); 
                    data.add(new NameWrapper("two")); 
                    data.add(new NameWrapper("three")); 
                    data.add(new NameWrapper("four")); 

                    final ListView<NameWrapper> listView = new ListView<NameWrapper>("list", data) 
                    { 
                            protected void populateItem(ListItem<NameWrapper> item) { 
                                    final NameWrapper wrapper = (NameWrapper)item.getModelObject(); 
                                    item.add(new Label("name", wrapper.getName())); 
                                    final CheckBox checkBox = new CheckBox("check", new PropertyModel<Boolean>(wrapper, "selected")); 
                                    item.add(checkBox); 
                                    checkBox.add(new OnChangeAjaxBehavior() { 
                                            @Override 
                                            protected void onUpdate(AjaxRequestTarget target) {                                                                                                   
                                                    if (wrapper.getSelected()) { 
                                                            for (NameWrapper entity : data) { 
                                                                    if (!entity.equals(wrapper)) { 
                                                                            entity.setSelected(Boolean.FALSE); 
                                                                    } 
                                                            } 
                                                    } 
                                                    target.addComponent(inputForm); 
                                            }                                              
                                    }); 
                            } 
                    }; 
                listView.setReuseItems(true); 
                add(listView); 
            }             
    } 

I created one checkbox and one textfield for each line using wicket listview.

When the user selects the checkbox I am able to set the related boolean value
succesfully.

But I needed to put a restriction. Only one checkbox can be
selected to submit the form in the following structure.

Textarea checkbox
Textarea checkbox
Textarea checkbox
Textarea checkbox

The text that I typed into the textareas are removed when I unset the checkbox that I selected.
As far as I know the following line is used to prevent this problem but it doesnt work. Do you have any idea?

listView.setReuseItems(true); 

 

public class CheckBoxListPage extends WebPage {      
    private Form inputForm; 

    public CheckBoxListPage() 
    { 
            add(inputForm = new InputForm("inputForm")); 
    } 

    private class InputForm extends Form 
    {  
            private List<NameWrapper> data; 

            public InputForm(String name) 
            { 
                    super(name);                    
                    data = new ArrayList<NameWrapper>(); 
                    data.add(new NameWrapper("one")); 
                    data.add(new NameWrapper("two")); 
                    data.add(new NameWrapper("three")); 
                    data.add(new NameWrapper("four")); 

                    final ListView<NameWrapper> listView = new ListView<NameWrapper>("list", data) 
                    { 
                            protected void populateItem(ListItem<NameWrapper> item) { 
                                    final NameWrapper wrapper = (NameWrapper)item.getModelObject(); 
                                    item.add(new Label("name", wrapper.getName())); 
                                    final CheckBox checkBox = new CheckBox("check", new PropertyModel<Boolean>(wrapper, "selected")); 
                                    item.add(checkBox); 
                                    checkBox.add(new OnChangeAjaxBehavior() { 
                                            @Override 
                                            protected void onUpdate(AjaxRequestTarget target) {                                                                                                   
                                                    if (wrapper.getSelected()) { 
                                                            for (NameWrapper entity : data) { 
                                                                    if (!entity.equals(wrapper)) { 
                                                                            entity.setSelected(Boolean.FALSE); 
                                                                    } 
                                                            } 
                                                    } 
                                                    target.addComponent(inputForm); 
                                            }                                              
                                    }); 
                            } 
                    }; 
                listView.setReuseItems(true); 
                add(listView); 
            }             
    } 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

活泼老夫 2024-12-16 19:03:47

如果您在代码中包含如何构建这些文本区域,以及是否将它们添加回 AjaxRequestTarget,这将会很有帮助。

无论如何,我看到您正在尝试实现服务器端行为来制作可以在客户端执行的操作(实际上,这是客户端操作)。您最好取消选中客户端的所有其他复选框,例如使用 javascript。

您可以使您的 Component 实现 IHeaderContributor,并将复选框的 HTML id 属性输出到 Javascript。然后,每个复选框都可以有一个 onchange 事件处理程序,您可以在其中取消选中使用 document.getElementById() 选择它们的所有其他复选框。

使用这种方法,您不需要 setReuseItems(true)。如果您将 ListView 写回到 AjaxRequestTargetsetReuseItems() 将帮助您保留与 Components 相同的 Components在第一次执行 populateItem() 时实例化(即,它们将保留相同的 markupId)。一般来说,如果您需要管理ListView内组件的状态,建议使用setReuseItems(true)。在本例中,这是在客户端完成的,因此乍一看没有必要。

例如:

private class InputForm extends Form implements IHeaderContributor {

    private List<String> checkboxIds = new ArrayList();
    //...
        protected void populateItem(ListItem<NameWrapper> item) { 
            // PropertyModel can be used on Models, too, 
            // not necessarily modelObejcts.
            IModel checkboxModel = new PropertyModel<Boolean>(item.getModel(), "selected"));
            final CheckBox checkBox = new CheckBox("check", checkboxModel);                                 
            checkBox.setOutputMarkupId(true);

            // If checkboxMarkupId is null at this point, 
            // you can always set it this way
            // checkBox.setMarkupId("check" + item.getIndex());

            String checkboxMarkupId = checkBox.getMarkupId();
            checkboxIds.add(checkboxMarkupId);            
            item.add(checkBox); 
            String js = "deselectChecks('" + checkboxMarkupId + "');";
            checkbox.add(new SimpleAttributeModifier("onchange", js));
        }
    //...
    public void renderHead(IHeaderResponse response) {
        String jsArrDecl = "var checkIds = [";
        for (String checkId : checkboxIds){
            jsArrDecl += "'" + checkId + "', ";
        }
        jsArrDecl = jsArrDecl.substring(0, jsArrDecl.length()-1);
        jsArrDecl += "];";
        response.renderOnDomReadyJavascript(jsArrDecl);
    }
}

Javascript:

function deselectChecks(selected){
     for each (var checkId in checkIds) {
          if (checkId != selected){
              document.getElementById(checkId).checked = false;
          }
     }
}

您可以将 onchange="deselectChecks(this.id);" 附加到 HTML 文件中的复选框,或者在 Java 中使用 SimpleAttributeModifier 添加它班级。

与往常一样,您还应该在服务器端实现此限制/行为,以防止没有 javascript 的用户绕过它。我建议使用 FormValidator 来达到此目的。

It would be helpful if you included in the code how are you building those textareas, and if you're adding them back to the AjaxRequestTarget.

Anyway, I see you're trying to implement a server-side behavior to make something you could do client-side (actually, it's a client-side operation). You'd be far better unchecking all other checkboxes client-side, for instance, with javascript.

You can make your Component implement IHeaderContributor, and output the checkboxes' HTML id attributes to Javascript. Then, every checkbox can have an onchange event handler in which you can uncheck all other checkboxes selecting them with document.getElementById().

With this approach, you wouldn't need setReuseItems(true). In case you write the ListView back to the AjaxRequestTarget, setReuseItems() would help you keep the same Components that were instantiated in the first execution of populateItem() (i.e, they would keep the same markupId's). In general, if you need to manage state of components inside the ListView, it's recommendable to use setReuseItems(true). In this case this is done client-side, so it's not necessary at first glance.

For instance:

private class InputForm extends Form implements IHeaderContributor {

    private List<String> checkboxIds = new ArrayList();
    //...
        protected void populateItem(ListItem<NameWrapper> item) { 
            // PropertyModel can be used on Models, too, 
            // not necessarily modelObejcts.
            IModel checkboxModel = new PropertyModel<Boolean>(item.getModel(), "selected"));
            final CheckBox checkBox = new CheckBox("check", checkboxModel);                                 
            checkBox.setOutputMarkupId(true);

            // If checkboxMarkupId is null at this point, 
            // you can always set it this way
            // checkBox.setMarkupId("check" + item.getIndex());

            String checkboxMarkupId = checkBox.getMarkupId();
            checkboxIds.add(checkboxMarkupId);            
            item.add(checkBox); 
            String js = "deselectChecks('" + checkboxMarkupId + "');";
            checkbox.add(new SimpleAttributeModifier("onchange", js));
        }
    //...
    public void renderHead(IHeaderResponse response) {
        String jsArrDecl = "var checkIds = [";
        for (String checkId : checkboxIds){
            jsArrDecl += "'" + checkId + "', ";
        }
        jsArrDecl = jsArrDecl.substring(0, jsArrDecl.length()-1);
        jsArrDecl += "];";
        response.renderOnDomReadyJavascript(jsArrDecl);
    }
}

Javascript:

function deselectChecks(selected){
     for each (var checkId in checkIds) {
          if (checkId != selected){
              document.getElementById(checkId).checked = false;
          }
     }
}

You can append onchange="deselectChecks(this.id);" to the checkboxes in the HTML file, or add it with a SimpleAttributeModifier in the Java class.

As always, you should also implement this restriction/behavior server-side to prevent users without javascript to bypass it. I'd suggest a FormValidator to that effect.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文