为什么我的 Wicket 面板在更改默认模型后不重新渲染?

发布于 2024-10-31 15:37:09 字数 857 浏览 2 评论 0原文

当带有 MessagePanel 的页面首次呈现时,消息和批准链接会完美呈现。当我单击批准链接时,所有业务逻辑都按预期工作,getNextMessage() 方法返回适当的对象,但消息面板不会在浏览器中的页面上更新。即消息体Label不更新。

JPAEntityModel 扩展了 LoadableDetachableModel。

我缺少什么?我该如何解决它?

public class MessagePanel(String id, IModel<Message> messageModel) extends Panel {
  super(id, messageModel);
  add(new Label("messageText", new PropertyModel<Message>(getModelObject(), Message.BODY_FIELD)));
  add(new IndicatingAjaxFallbackLink<User>("approveLink", new JPAEntityModel<User> (getActiveUser())) {
    @Override
    public void onClick(AjaxRequestTarget target) {
      Message nextMessage = getNextMessage();
      MessagePanel.this.setDefaultModel(new JPAEntityModel<Message>(nextMessage));
      target.add(MessagePanel.this);
    }
});
  setOutputMarkupId(true);
}

When the page with the MessagePanel first renders, the message and the approve link render perfectly. When I click the approve link, all the business logic works as desired, the getNextMessage() method returns the appropriate object, but the message panel does not update on the page in the browser. That is, the message body Label does not update.

JPAEntityModel extends LoadableDetachableModel.

What am I missing? And how do I fix it?

public class MessagePanel(String id, IModel<Message> messageModel) extends Panel {
  super(id, messageModel);
  add(new Label("messageText", new PropertyModel<Message>(getModelObject(), Message.BODY_FIELD)));
  add(new IndicatingAjaxFallbackLink<User>("approveLink", new JPAEntityModel<User> (getActiveUser())) {
    @Override
    public void onClick(AjaxRequestTarget target) {
      Message nextMessage = getNextMessage();
      MessagePanel.this.setDefaultModel(new JPAEntityModel<Message>(nextMessage));
      target.add(MessagePanel.this);
    }
});
  setOutputMarkupId(true);
}

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

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

发布评论

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

评论(3

巷雨优美回忆 2024-11-07 15:37:09

这是因为你没有正确使用模型。

该行获取面板模型对象的值(在构建过程中设置),并使用它来创建组件模型。

add(new Label("messageText", new PropertyModel<Message>(getModelObject(), Message.BODY_FIELD)));

更糟糕的是,当您单击链接时,面板会被赋予一个新模型:

MessagePanel.this.setDefaultModel(new JPAEntityModel<Message>(nextMessage));

但这显然不会影响标签的模型,因为它已经设置为引用原始值。

因此,您需要更改两件事才能使其发挥作用。首先,您的标签模型应该直接使用您的面板模型:(

new Model<Message>() {
  @Override
  public Message getObject() {
    return MessagePanel.this.getModelObject().getMessage(); //or something similar
  }
}

注意:上面的代码不一定是最佳解决方案,但它是一个演示如何动态使用模型的可行解决方案。)

理想情况下,您不应该替换单击链接时的模型,只需更改模型对象即可。如果您需要自定义模型类 (JPAEntityModel),则无论如何您都不应该在面板构造函数中接受预先构造的模型,而只接受第一个消息对象。原因是当前的实现并不从一开始就强制使用 JPAEntityModel,仅在第一次单击链接后才强制使用。

It is because you're not using the model properly.

This line takes the value of the panel's model object, as it is set during construction, and uses it to create the component model.

add(new Label("messageText", new PropertyModel<Message>(getModelObject(), Message.BODY_FIELD)));

To make matters worse, when you click the link, the panel is given a new model:

MessagePanel.this.setDefaultModel(new JPAEntityModel<Message>(nextMessage));

But this obviously doesn't affect the model of the label, as it is already set to refer to the original value.

So there are two things you need to change to make it work. First off, your label model should use your panel model directly:

new Model<Message>() {
  @Override
  public Message getObject() {
    return MessagePanel.this.getModelObject().getMessage(); //or something similar
  }
}

(Note: the code above isn't necessarily the best solution, but it is a working solution that demonstrates how models can be used dynamically.)

And ideally you shouldn't replace the model when you click the link, just change the model object. If you need a custom model class (JPAEntityModel), you shouldn't be accepting a pre-constructed model in the panel constructor anyway, just the first message object. The reason being the current implementation doesn't enforce the use of JPAEntityModel from the start, only after the first click of the link.

-黛色若梦 2024-11-07 15:37:09

您可以在将其添加到目标之前尝试调用 MessagePanel.this.modelChanged() 吗?

Can you try calling MessagePanel.this.modelChanged() before adding it to the target?

驱逐舰岛风号 2024-11-07 15:37:09

您必须在 MessagePanel 中使用 setOutputMarkupId(true) 调用。面板需要有一个标记标识符才能更新浏览器中的标记 DOM。

You must use call setOutputMarkupId(true) within you MessagePanel. The panel needs to have a markup identifier to be able to update the markup DOM in the browser.

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