Wicket AjaxButton 不更新 FeedbackPanel
Wicket AjaxButton does not update FeedbackPanel
如果单击 AjaxButton,我将尝试向 Wicket 中的 FeedbackPanel 发送一条成功消息。但是我收到以下错误消息:
Wicket.Ajax.Call.processComponent: Component with id [[065DFC0DD1DC51103CC5FFEE61F2AE12]] was not found while trying to perform markup update.
我已经知道,在使用 AjaxButton 并在 onSubmit
中设置目标之前,我必须在 Java 代码中输出 markupID。我也设置了 setOutputMarkupPlaceholderTag
一次,但它没有任何改变。
我还创建了一个小的测试页面,在那里我成功地将成功消息发送到 FeedbackPanel。
于是我开始调试项目,发现DefaultMarkupIdGenerator.generateMarkupId
返回的markupID确实和HTML中显示的不一样。此外,所有 FeedbackPanel 在 ajax 调用期间都会收到此 markupID。
feedbackPanelWartung12 vs. 065DFC0DD1DC51103CC5FFEE61F2AE12
更复杂的是,我的 FeedbackPanel 位于 RepeatingView 中,该 RepeatingView 包含在已经包含 FeedbackPanel(从其超类继承)的页面中的面板中。结构如下:
Java代码
我的页面
public MyPage extends MySuperPage{
//Constructors were left out
//this method is called in the onInitialize of some
//super class.
@Override
protected Component newContent() {
setFeedbackPanelFilter();
return new MyContainerPanel();
}
//this FeedbackPanel shall not recieve messages from child containers
private void setFeedbackPanelFilter() {
((FeedbackPanel) this.get("feedback"))
.setFilter( new ContainerFeedbackMessageFilter(this) {
@Override
public boolean accept(FeedbackMessage message) {
return !super.accept(message);
}
});
}
}
我的容器面板
public MyContainerPanel extends Panel {
//Constructors were left out
@Override
protected void onInitialize() {
super.onInitialize();
RepeatingView repeater = new RepeatingView("repeater");
add(repeater);
for (Object o : objects) {
String id = repeater.newChildId();
repeater.add(new MyPanel(id,o));
}
}
}
我的面板
public MyPanel extends Panel {
private Object o;
private CheckBox chkBox;
private DateTimeField startDate, endDate;
private TextField<String> message;
private Form<Object> form;
private AjaxButton button;
private Label name;
private FeedbackPanel feedbackPanel;
//Constructors were left out
@Override
protected void onInitialize() {
super.onInitialize();
initFields();
addFields();
addAjaxButton();
addAjaxFormComponentUpdatingBehavior();
if (!o.isMaintenance())
disableFields();
}
private void addAjaxButton() {
button = new AjaxButton("submit") {
@Override
public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
//do something
feedbackPanel.success("Speichern erfolgreich");
target.addChildren(AppWartungPanel.this.getPage(), FeedbackPanel.class);
}
};
form.add(button);
}
private void addAjaxFormComponentUpdatingBehavior() {
chkBox.add(new AjaxFormComponentUpdatingBehavior("onchange") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
switchVisibility();
target.add(startDate);
target.add(endDate);
target.add(message);
target.add(feedbackPanel);
}
});
}
private void switchVisibility() {
if (o.isMaintenance())
enableFields();
else
disableFields();
}
private void addFields() {
add(form);
form.add(feedbackPanel);
form.add(chkBox);
form.add(startDate);
form.add(endDate);
form.add(message);
form.add(name);
}
private void initFields() {
form = new Form<WartungDAO>("form", AppWartungPanel.this.getModel());
chkBox = new CheckBox("wartung", new PropertyModel<Boolean>(o, "wartung"));
chkBox.setOutputMarkupId(true);
startDate = new DateTimeField("startDate", new PropertyModel<Date>(o, "startDate"));
startDate.setOutputMarkupId(true);
startDate.setRequired(true);
endDate = new DateTimeField("endDate", new PropertyModel<Date>(o, "endDate"));
endDate.setOutputMarkupId(true);
endDate.setRequired(true);
message = new TextField<String>("message", new PropertyModel<String>(o, "message"));
message.setOutputMarkupId(true);
message.setRequired(true);
name = new Label("name", new PropertyModel<String>(o, "portal"));
feedbackPanel = new FeedbackPanel("feedbackPanelWartung");
feedbackPanel.setOutputMarkupId(true);
feedbackPanel.setFilter(new ContainerFeedbackMessageFilter(this));
}
private void disableFields() {
startDate.setEnabled(false);
endDate.setEnabled(false);
message.setEnabled(false);
}
private void enableFields() {
startDate.setEnabled(true);
endDate.setEnabled(true);
message.setEnabled(true);
}
}
HTML 标记
我的页面
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<body class="BG_MAIN">
<div class="grid_16 BG1_GLOBAL">
<div style="margin:10px;">
<div class="grid_3 alpha">
<wicket:container wicket:id="menu"></wicket:container>
</div>
<div class="grid_12 omega">
<div class="INHALT">
<h1 wicket:id="appHeader" style="margin-top: 0;"></h1>
<div wicket:id="wartung" />
<div wicket:id="feedback"></div>
<wicket:container wicket:id="content"></wicket:container>
</div>
</div>
</body>
</html>
我的容器面板
<html xmlns:wicket="http://wicket.apache.org">
<wicket:panel>
<div wicket:id="repeater">
</div>
</wicket:panel>
</html>
我的面板
<html xmlns:wicket="http://wicket.apache.org">
<wicket:panel>
<div style="margin-left: 25px; margin-top: 25px;">
<form wicket:id="form">
<h2 wicket:id="name"></h2>
<div wicket:id="feedbackPanelWartung"></div>
<table style="border: none;">
<tbody>
<tr>
<td style="border: none;">Wartung aktiv?</td>
<td style="border: none;">
<input wicket:id="wartung" type="checkbox" />
</td>
</tr>
<tr>
<td style="border: none;">Nachricht zum Anzeigen:</td>
<td style="border: none;">
<input wicket:id="message" type="text" size="50" />
</td>
</tr>
<tr>
<td style="border: none;">Startdatum</td>
<td style="border: none;">
<div wicket:id="startDate"></div>
</td>
</tr>
<tr>
<td style="border: none;">Enddatum</td>
<td style="border: none;">
<div wicket:id="endDate"></div>
</td>
</tr>
<tr>
<td style="border: none;"></td>
<td style="border: none;">
<input wicket:id="submit" type="submit" value="Speichern" style="float: right;" />
</td>
</tr>
</tbody>
</table>
</form>
</div>
</wicket:panel>
</html>
我只能猜测错误是由于页面的复杂性。
我还禁用了 AjaxFormComponentUpdatingBehavior
以检查它是否与 AjaxButton 混淆 - 它没有。
我还使用普通按钮实现了所有功能,以检查 ContainerFeedbackMessageFilter 和 FeedbackPanels 是否有效 - 它们确实有效。
AjaxButton 对页面来说并不重要。但是我真的很想了解,所以如果有人有另一个好主意可以尝试...
FeedbackPanel feedbackPanel = new FeedbackPanel("feedbackPanelWartung") {
@Override
public String getMarkupId() {
return "feedbackPanelWartung." + someUniqueValuePassedToThePanel;
}
};
feedbackPanel.setOutputMarkupId(true);
幸运的是,我在面板的一个模型对象中有一个唯一值。然后我覆盖了 Component.getMarkupId() 方法并简单地设置了我的 Id.
工作得很好。
我还发现,feedbackPanel.setOutputMarkupId(true);
方法与我的错误消息无关。
换句话说:即使我尝试为我的组件设置标记 ID,它也从来没有在第一时间设置,因此 ajax 组件理所当然地永远无法找到目标。
如果单击 AjaxButton,我将尝试向 Wicket 中的 FeedbackPanel 发送一条成功消息。但是我收到以下错误消息:
Wicket.Ajax.Call.processComponent: Component with id [[065DFC0DD1DC51103CC5FFEE61F2AE12]] was not found while trying to perform markup update.
我已经知道,在使用 AjaxButton 并在 onSubmit
中设置目标之前,我必须在 Java 代码中输出 markupID。我也设置了 setOutputMarkupPlaceholderTag
一次,但它没有任何改变。
我还创建了一个小的测试页面,在那里我成功地将成功消息发送到 FeedbackPanel。
于是我开始调试项目,发现DefaultMarkupIdGenerator.generateMarkupId
返回的markupID确实和HTML中显示的不一样。此外,所有 FeedbackPanel 在 ajax 调用期间都会收到此 markupID。
feedbackPanelWartung12 vs. 065DFC0DD1DC51103CC5FFEE61F2AE12
更复杂的是,我的 FeedbackPanel 位于 RepeatingView 中,该 RepeatingView 包含在已经包含 FeedbackPanel(从其超类继承)的页面中的面板中。结构如下:
Java代码
我的页面
public MyPage extends MySuperPage{
//Constructors were left out
//this method is called in the onInitialize of some
//super class.
@Override
protected Component newContent() {
setFeedbackPanelFilter();
return new MyContainerPanel();
}
//this FeedbackPanel shall not recieve messages from child containers
private void setFeedbackPanelFilter() {
((FeedbackPanel) this.get("feedback"))
.setFilter( new ContainerFeedbackMessageFilter(this) {
@Override
public boolean accept(FeedbackMessage message) {
return !super.accept(message);
}
});
}
}
我的容器面板
public MyContainerPanel extends Panel {
//Constructors were left out
@Override
protected void onInitialize() {
super.onInitialize();
RepeatingView repeater = new RepeatingView("repeater");
add(repeater);
for (Object o : objects) {
String id = repeater.newChildId();
repeater.add(new MyPanel(id,o));
}
}
}
我的面板
public MyPanel extends Panel {
private Object o;
private CheckBox chkBox;
private DateTimeField startDate, endDate;
private TextField<String> message;
private Form<Object> form;
private AjaxButton button;
private Label name;
private FeedbackPanel feedbackPanel;
//Constructors were left out
@Override
protected void onInitialize() {
super.onInitialize();
initFields();
addFields();
addAjaxButton();
addAjaxFormComponentUpdatingBehavior();
if (!o.isMaintenance())
disableFields();
}
private void addAjaxButton() {
button = new AjaxButton("submit") {
@Override
public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
//do something
feedbackPanel.success("Speichern erfolgreich");
target.addChildren(AppWartungPanel.this.getPage(), FeedbackPanel.class);
}
};
form.add(button);
}
private void addAjaxFormComponentUpdatingBehavior() {
chkBox.add(new AjaxFormComponentUpdatingBehavior("onchange") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
switchVisibility();
target.add(startDate);
target.add(endDate);
target.add(message);
target.add(feedbackPanel);
}
});
}
private void switchVisibility() {
if (o.isMaintenance())
enableFields();
else
disableFields();
}
private void addFields() {
add(form);
form.add(feedbackPanel);
form.add(chkBox);
form.add(startDate);
form.add(endDate);
form.add(message);
form.add(name);
}
private void initFields() {
form = new Form<WartungDAO>("form", AppWartungPanel.this.getModel());
chkBox = new CheckBox("wartung", new PropertyModel<Boolean>(o, "wartung"));
chkBox.setOutputMarkupId(true);
startDate = new DateTimeField("startDate", new PropertyModel<Date>(o, "startDate"));
startDate.setOutputMarkupId(true);
startDate.setRequired(true);
endDate = new DateTimeField("endDate", new PropertyModel<Date>(o, "endDate"));
endDate.setOutputMarkupId(true);
endDate.setRequired(true);
message = new TextField<String>("message", new PropertyModel<String>(o, "message"));
message.setOutputMarkupId(true);
message.setRequired(true);
name = new Label("name", new PropertyModel<String>(o, "portal"));
feedbackPanel = new FeedbackPanel("feedbackPanelWartung");
feedbackPanel.setOutputMarkupId(true);
feedbackPanel.setFilter(new ContainerFeedbackMessageFilter(this));
}
private void disableFields() {
startDate.setEnabled(false);
endDate.setEnabled(false);
message.setEnabled(false);
}
private void enableFields() {
startDate.setEnabled(true);
endDate.setEnabled(true);
message.setEnabled(true);
}
}
HTML 标记
我的页面
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<body class="BG_MAIN">
<div class="grid_16 BG1_GLOBAL">
<div style="margin:10px;">
<div class="grid_3 alpha">
<wicket:container wicket:id="menu"></wicket:container>
</div>
<div class="grid_12 omega">
<div class="INHALT">
<h1 wicket:id="appHeader" style="margin-top: 0;"></h1>
<div wicket:id="wartung" />
<div wicket:id="feedback"></div>
<wicket:container wicket:id="content"></wicket:container>
</div>
</div>
</body>
</html>
我的容器面板
<html xmlns:wicket="http://wicket.apache.org">
<wicket:panel>
<div wicket:id="repeater">
</div>
</wicket:panel>
</html>
我的面板
<html xmlns:wicket="http://wicket.apache.org">
<wicket:panel>
<div style="margin-left: 25px; margin-top: 25px;">
<form wicket:id="form">
<h2 wicket:id="name"></h2>
<div wicket:id="feedbackPanelWartung"></div>
<table style="border: none;">
<tbody>
<tr>
<td style="border: none;">Wartung aktiv?</td>
<td style="border: none;">
<input wicket:id="wartung" type="checkbox" />
</td>
</tr>
<tr>
<td style="border: none;">Nachricht zum Anzeigen:</td>
<td style="border: none;">
<input wicket:id="message" type="text" size="50" />
</td>
</tr>
<tr>
<td style="border: none;">Startdatum</td>
<td style="border: none;">
<div wicket:id="startDate"></div>
</td>
</tr>
<tr>
<td style="border: none;">Enddatum</td>
<td style="border: none;">
<div wicket:id="endDate"></div>
</td>
</tr>
<tr>
<td style="border: none;"></td>
<td style="border: none;">
<input wicket:id="submit" type="submit" value="Speichern" style="float: right;" />
</td>
</tr>
</tbody>
</table>
</form>
</div>
</wicket:panel>
</html>
我只能猜测错误是由于页面的复杂性。
我还禁用了 AjaxFormComponentUpdatingBehavior
以检查它是否与 AjaxButton 混淆 - 它没有。
我还使用普通按钮实现了所有功能,以检查 ContainerFeedbackMessageFilter 和 FeedbackPanels 是否有效 - 它们确实有效。
AjaxButton 对页面来说并不重要。但是我真的很想了解,所以如果有人有另一个好主意可以尝试...
FeedbackPanel feedbackPanel = new FeedbackPanel("feedbackPanelWartung") {
@Override
public String getMarkupId() {
return "feedbackPanelWartung." + someUniqueValuePassedToThePanel;
}
};
feedbackPanel.setOutputMarkupId(true);
幸运的是,我在面板的一个模型对象中有一个唯一值。然后我覆盖了 Component.getMarkupId() 方法并简单地设置了我的 Id.
工作得很好。
我还发现,feedbackPanel.setOutputMarkupId(true);
方法与我的错误消息无关。
换句话说:即使我尝试为我的组件设置标记 ID,它也从来没有在第一时间设置,因此 ajax 组件理所当然地永远无法找到目标。