java - 取消设置 ajaxcheckbox 时, ListView 中的 wicket 文本区域会被清除

标签 java listview wicket

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

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

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

Textarea checkbox Textarea checkbox Textarea checkbox Textarea checkbox

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

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); 
            }             
    } 

最佳答案

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

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

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

使用这种方法,您将不需要 setReuseItems(true)。如果您将 ListView 写回到 AjaxRequestTargetsetReuseItems() 将帮助您保留在第一次执行 populateItem() 时实例化的相同 Components(即,它们将保留相同的 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 来达到此目的。

关于java - 取消设置 ajaxcheckbox 时, ListView 中的 wicket 文本区域会被清除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7754236/

相关文章:

java - Azure 上带有命令行参数的 Spring Boot 应用程序

java - Hive GenericUDF 错误 - RuntimeException typeInfo 不能为 null

java - Wicket 中的 SetResponsePage

android - 选择 ListView 的行而不是项目

java - Wicket TextField<BigDecimal> 默认显示 4 位小数,但允许(轻松)编辑精确值

java - 在页面的 onConfigure 方法中访问更新的 PageParameters

java - 用于 RESTful GUI 应用程序的最先进的 Java Web 框架?

java - 使用 UTF-8 字符对特殊字符进行编码

android - 使用自定义 ArrayAdapter 在 Android 屏幕旋转时失去颜色的 ListView 中的选定项目

android - 空列表框显示在 ListView 中