如何在不在 Wicket 中添加组件的情况下修改属性?

how can i modify attributes without adding the component in Wicket?

我必须向组件添加 class。我无法通过 ajax 添加组件,因为这是输入问题。我的代码是:

private ListView<Opzioni> setListOpzioni(boolean b) {

    return new ListView<Opzioni>("list_opzioni", opzioniDao.findAll()) {

        @Override
        protected void populateItem(ListItem<Opzioni> item) {
            erroriAssociatiAlTextField = new HashMap<>();
            List<Opzioni> opzioniCron = opzioniDao.getOpzioniFormatore();

            final Opzioni o = item.getModelObject();

            final WebMarkupContainer errorContainer = new WebMarkupContainer("errorContainer");
            errorContainer.setOutputMarkupId(true);
            errorContainer.setOutputMarkupPlaceholderTag(true);

            Boolean isSelected = false;
            Boolean isAzienda = o.getAzienda() != null ? o.getAzienda().equals(getAziendaLogged()) : false;
            if (isAdminFormatore(getUserLogged())) {
                isSelected = o.getControlFormatore() || isAzienda;
            } else {
                isSelected = isAzienda;
            }

            Boolean visibile = isSa || isSelected;

            Label name_op = new Label("name_op", o.getName());
            item.add(name_op.setVisible(visibile));

            TextField val_op = new TextField("val_op", new PropertyModel(o, "val"));
            val_op.add(new OnChangeAjaxBehavior() {
                @Override
                protected void onUpdate(AjaxRequestTarget art) {
                    if (opzioniCron.contains(o)) {
                        controllaStringa(o);
                    }
                    if (valoriScorretti == true) {
                        contatore++;
                    } else {
                         contatore = 0;
                    }
                    if (contatore > 0) {
                         ciSonoErrori = true;
                         String error = "Valori inseriti nel box " + o.getName() + " non corretti";

                    if (!erroriAssociatiAlTextField.containsKey(o)) {
                         erroriAssociatiAlTextField.put(o, error);
                    }

                    for (Map.Entry<Opzioni, String> map : erroriAssociatiAlTextField.entrySet()) {
                        val_op.error(map.getValue());
                    }
                    art.add(errorContainer.setVisible(true));
                    refreshFp(art);
                    art.add(save_btn.setVisible(false));
                    } else {
                        ciSonoErrori = false;

                        if (!erroriAssociatiAlTextField.isEmpty()) {

                            art.add(save_btn.setVisible(false));

                            if (erroriAssociatiAlTextField.containsKey(o)) {
                                    erroriAssociatiAlTextField.remove(o);

                            }

                            for (Map.Entry<Opzioni, String> map : erroriAssociatiAlTextField.entrySet()) {
                                 val_op.error(map.getValue());
                            }
                        }
                        if (erroriAssociatiAlTextField.isEmpty()) {
                            art.add(save_btn.setVisible(true));
                        }
                        art.add(errorContainer.setVisible(false));

                        refreshFp(art);

                        }
                    }
                });
                item.add(val_op.setEnabled(b).setVisible(visibile));


                item.add(errorContainer.setVisible(false));

                if (visibile) {
                    o.setModificato(true);
                } else {
                    o.setModificato(false);
                }
            }
        };
    }

使用此代码,每次用户在字段中插入一个字母时,光标都会转到第一个位置,并且无法使用它。是否有替代模式来动态添加 class?

With this code every time a user insert a letter inside the field the cursor go to the first position and it's impossible to use it.

那是因为您正在使用 OnChangeAjaxBehavior。 此行为会在每次用户输入后检查 FormComponent 是否验证正确,如果验证正确,它将调用 onUpdate 方法。

对于没有添加 IValidator 的 TextField,这意味着每次输入后都会调用 onUpdate。如果您随后通过 AjaxRequestTarget 重新打印 TextField,您将获得输入字段的行为,您可以像当前一样在其中键入 "backwards"。

how can i modify attributes without adding the component in Wicket?

如果您希望更改在浏览器中可见,则需要在某个时候使用 ajax 更新组件。没办法了。

你可能不得不重新考虑你的做法,因为你目前所做的事情没有多大意义。

目前您有一个 TextField,当用户输入有效内容时,您将 css class "field-error" 添加到 html 输入。

  1. 难道不应该反过来,当用户输入无效的内容时应该添加“字段错误”吗?
  2. 您真的要在用户输入内容时验证并执行 ajax 更新吗?为什么不在 form/textfield 实际提交时或用户在字段中完成输入时验证输入?

编辑

您可以使用 AjaxRequestTarget 发送 jQuery 命令以将 css class 添加到输入,而不是使用 AjaxRequestTarget 更新输入:

val_op.setOutputMarkupId(true);
val_op.add(new OnChangeAjaxBehavior() {
     @Override
     protected void onUpdate(AjaxRequestTarget art) {
          art.appendJavaScript("$('#"+val_op.getMarkupId()+"').addClass('field-error');");
    }
}

而不是通过 ajax 更新整个输入,这只会发送一个 jQuery Javascript 以在 AjaxResponse 中执行。然后,您可以在链接的页面中调用 Javascript,并在客户端添加 css class。

您唯一需要的是输入的 ID,以便 jquery 可以找到它。因此 setOutputMarkupId 必须设置为 true,然后您可以通过调用 getMarkupId() 获取 wicket 创建的 ID,并将其插入到 javascript 命令中。

正如我已经说过的,您在 onUpdate 方法中添加错误-class 对我来说似乎很奇怪。在我看来,正确的方法是在 onError 方法中添加错误 class(当输入无效时调用)并在 onUpdate 中删除它(当输入有效时)。

val_op.setOutputMarkupId(true);
val_op.add(new OnChangeAjaxBehavior() {
     @Override
     protected void onUpdate(AjaxRequestTarget art) {
          art.appendJavaScript("$('#"+val_op.getMarkupId()+"').removeClass('field-error');");
    }

     @Override
     protected void onError(AjaxRequestTarget art, RuntimeException e) {
          art.appendJavaScript("$('#"+val_op.getMarkupId()+"').addClass('field-error');");
    }
}