如何在检票口使用模型?
我尝试创建以下结构的页面:
MainPage {
DateSelector {}
TabGroup {
Tab0 {...}
Tab1 {...}
Tab2 {...}
}
}
DateSelector 是一个组件(扩展面板),使用户能够选择时间跨度(startDate、endDate)。 TabGroup 扩展“AjaxTabbedPanel”。 TabGroup 中显示的选项卡应使用选定的时间跨度来显示内容。
因此,如果用户在选择器中选择一个时间跨度,则所选选项卡中的内容应该更新。
为此,我实现了 DateSelector 的用户可以覆盖以更新其内容的方法。
我感觉我的方法违反了框架。我可以以某种方式利用模型来增强实施吗?这有什么“问题”吗?选项卡是否可以与 DateSelector 共享时间跨度,以便在时间跨度发生变化时它们也会更新?没有回调?
DateSelector 的实现如下:
abstract public class TimespanSelectionPanel extends Panel {
public TimespanSelectionPanel(String id, Timespan timespan) {
super(id, new CompoundPropertyModel<Timespan>(timespan));
final DateTextField fromTextField = DateTextField.forDatePattern("from", "dd.MM.yyyy");
fromTextField.setOutputMarkupId(true);
fromTextField.add(new DatePicker());
final DateTextField toTextField = DateTextField.forDatePattern("to", "dd.MM.yyyy");
toTextField.setOutputMarkupId(true);
toTextField.add(new DatePicker());
fromTextField.add(new AjaxFormComponentUpdatingBehavior("onchange") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
}
});
toTextField.add(new AjaxFormComponentUpdatingBehavior("onchange") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
}
});
add(new AjaxLink<String>("today") {
@Override
public void onClick(AjaxRequestTarget target) {
updateComponent(fromTextField, toTextField, target, Timespan.today());
}
});
add(new AjaxLink<String>("yesterday") {
@Override
public void onClick(AjaxRequestTarget target) {
updateComponent(fromTextField, toTextField, target, Timespan.yesterday());
}
});
add(new AjaxLink<String>("lastMonth") {
@Override
public void onClick(AjaxRequestTarget target) {
updateComponent(fromTextField, toTextField, target, Timespan.lastMonth());
}
});
add(new AjaxLink<String>("actualMonth") {
@Override
public void onClick(AjaxRequestTarget target) {
Timespan timespan = adjustToTextField(fromTextField, toTextField, target, Timespan.actualMonth());
updateComponent(fromTextField, toTextField, target, timespan);
}
});
add(new AjaxLink<String>("fromTo") {
@Override
public void onClick(AjaxRequestTarget target) {
Timespan newTimespan = adjustToTextField(fromTextField, toTextField, target, fromTextField
.getModelObject(), toTextField.getModelObject());
update(target, newTimespan);
}
});
add(fromTextField);
add(toTextField);
}
private Timespan adjustToTextField(DateTextField fromTextField, DateTextField toTextField,
AjaxRequestTarget target, Timespan timespan) {
return adjustToTextField(fromTextField, toTextField, target, timespan.getFrom(), timespan.getTo());
}
private Timespan adjustToTextField(final DateTextField fromTextField, final DateTextField toTextField,
AjaxRequestTarget target, Date from, Date to) {
Date today = DateUtil.today();
if (to.after(today)) {
to = today;
toTextField.setModelObject(today);
target.addComponent(toTextField);
}
if (from.after(to)) {
from = to;
fromTextField.setModelObject(from);
target.addComponent(fromTextField);
}
return Timespan.fromTo(from, to);
}
private void updateComponent(final DateTextField fromTextField, final DateTextField toTextField,
AjaxRequestTarget target, Timespan newTimespan) {
fromTextField.setModelObject(newTimespan.getFrom());
toTextField.setModelObject(newTimespan.getTo());
target.addComponent(fromTextField);
target.addComponent(toTextField);
update(target, newTimespan);
}
abstract protected void update(AjaxRequestTarget target, Timespan timespan);
}
I try to create an page of the following structure:
MainPage {
DateSelector {}
TabGroup {
Tab0 {...}
Tab1 {...}
Tab2 {...}
}
}
DateSelector is a component (extending Panel) that enables the user to select a timespan (startDate, endDate). TabGroup extending "AjaxTabbedPanel". The tabs shown in the TabGroup should use the selected timespan to display content.
So if the user selects a timespan in the selector the content in the selected tab should update.
For this I implement a method the user of the DateSelector could override to update its contents.
I have the feeling that my approch is against the framework. Could I utilise a model in some way to enhance the implementation? What is 'wrong' with this? Can the tabs share the timespan with the DateSelector, such that they update if teh timespan change? Without the callback?
The DateSelector is implemented like this:
abstract public class TimespanSelectionPanel extends Panel {
public TimespanSelectionPanel(String id, Timespan timespan) {
super(id, new CompoundPropertyModel<Timespan>(timespan));
final DateTextField fromTextField = DateTextField.forDatePattern("from", "dd.MM.yyyy");
fromTextField.setOutputMarkupId(true);
fromTextField.add(new DatePicker());
final DateTextField toTextField = DateTextField.forDatePattern("to", "dd.MM.yyyy");
toTextField.setOutputMarkupId(true);
toTextField.add(new DatePicker());
fromTextField.add(new AjaxFormComponentUpdatingBehavior("onchange") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
}
});
toTextField.add(new AjaxFormComponentUpdatingBehavior("onchange") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
}
});
add(new AjaxLink<String>("today") {
@Override
public void onClick(AjaxRequestTarget target) {
updateComponent(fromTextField, toTextField, target, Timespan.today());
}
});
add(new AjaxLink<String>("yesterday") {
@Override
public void onClick(AjaxRequestTarget target) {
updateComponent(fromTextField, toTextField, target, Timespan.yesterday());
}
});
add(new AjaxLink<String>("lastMonth") {
@Override
public void onClick(AjaxRequestTarget target) {
updateComponent(fromTextField, toTextField, target, Timespan.lastMonth());
}
});
add(new AjaxLink<String>("actualMonth") {
@Override
public void onClick(AjaxRequestTarget target) {
Timespan timespan = adjustToTextField(fromTextField, toTextField, target, Timespan.actualMonth());
updateComponent(fromTextField, toTextField, target, timespan);
}
});
add(new AjaxLink<String>("fromTo") {
@Override
public void onClick(AjaxRequestTarget target) {
Timespan newTimespan = adjustToTextField(fromTextField, toTextField, target, fromTextField
.getModelObject(), toTextField.getModelObject());
update(target, newTimespan);
}
});
add(fromTextField);
add(toTextField);
}
private Timespan adjustToTextField(DateTextField fromTextField, DateTextField toTextField,
AjaxRequestTarget target, Timespan timespan) {
return adjustToTextField(fromTextField, toTextField, target, timespan.getFrom(), timespan.getTo());
}
private Timespan adjustToTextField(final DateTextField fromTextField, final DateTextField toTextField,
AjaxRequestTarget target, Date from, Date to) {
Date today = DateUtil.today();
if (to.after(today)) {
to = today;
toTextField.setModelObject(today);
target.addComponent(toTextField);
}
if (from.after(to)) {
from = to;
fromTextField.setModelObject(from);
target.addComponent(fromTextField);
}
return Timespan.fromTo(from, to);
}
private void updateComponent(final DateTextField fromTextField, final DateTextField toTextField,
AjaxRequestTarget target, Timespan newTimespan) {
fromTextField.setModelObject(newTimespan.getFrom());
toTextField.setModelObject(newTimespan.getTo());
target.addComponent(fromTextField);
target.addComponent(toTextField);
update(target, newTimespan);
}
abstract protected void update(AjaxRequestTarget target, Timespan timespan);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果选择器面板和选项卡面板之间的时间跨度始终同步,则它是共享模型是有意义的。
这意味着您的选项卡面板需要访问提供 TimeSpan 的模型,或者类似 ITimeSpanProvider 实现器(即时间跨度选择器组件)的东西。前者显然是 Wicket 中更好的处理方式。
因此,您的面板构造函数应该采用 TimeSpan 模型,然后由任何需要它的组件使用。这意味着您不需要将模型更新从选择器推送到选项卡面板。
根据选项卡面板的功能,TimeSpan 模型作为“主”模型可能没有意义,但这没关系 - 它只是另一个模型。如果时间跨度模型没有设置为选项卡面板中另一个组件的模型,那么您应该在适当的时候 detach() 模型等。如果它适合您的需求,您可以将这一切抽象到 TimeSpanAwarePanel 中正在做。
If the timespan is always in synch between the selector and tab panels, then it makes sense that it is a shared model.
This means your tab panels need access to a either a model that supplies a TimeSpan, or something like an ITimeSpanProvider implementor (i.e. the timespan selector component). The former is obviously the better way of doing things in Wicket.
So, your panel constructors should take a TimeSpan model, which is then used by whatever components require it. This means that you don't need to push model updates from the selector to the tab panels.
Depending on the function of your tab panels, the TimeSpan model may not make sense as the "main" model, but that's fine - it's just another model. If the timespan model isn't set as a model for another component within your tab panels, you should be nice and detach() the model when appropriate, etc. You can abstract this all out into a TimeSpanAwarePanel if it fits what you're doing.