将行为添加到 Wicket 选项卡

Add behavior to Wicket Tab

我在页面上有一个 wicket 应用程序,我们将同一模型的各种表单分成不同的选项卡。我需要做的是每当单击选项卡时检查 js 变量 tabDirty 是否设置为 true 或 false。如果它是 true 我会启动 confirm 提示,如果没问题,然后重置该表单并移至单击的选项卡。如果取消,请留在该选项卡上并保持当前更改。

我有这个 js 用于警告,没什么特别的

function warnOnChange(){
    if(tabDirty){
        decision = confirm('Leave?');
        if(decision){
            resetTab(); //sets tabDirty back to false
        } else {
            return false;
        }
    }
}

我有一个超级简单的 wicket 行为

public class WarnChangePromptOnClickBehavior extends Behavior {

    @Override
    public void bind(Component component) {
        component.add(JQBehaviors.mouseClick(EditMerchant.WARN_ON_CHANGE));
    }
}

并且该行为已添加到 AjaxFallBackLink

AjaxTabbedPanel<CustomAjaxTab> tabbedPanel = new AjaxTabbedPanel<CustomAjaxTab>("tabbedPanel", tabList, new Model<>(0)) {

    private static final long serialVersionUID = 1L;

    @Override
    protected WebMarkupContainer newLink(final String linkId, final int index) {
        AjaxFallbackLink<Void> link = new AjaxFallbackLink<Void>(linkId) {

            private static final long serialVersionUID = 1L;

            @Override
            public void onClick(final AjaxRequestTarget target) {
                TabbedPanel<CustomAjaxTab> selectedTab = setSelectedTab(index);
                CustomAjaxTab tab = tabList.get(index);
                if (target != null) {

                    tab.getPanel(linkId);

                    target.add(selectedTab);
                }
                onAjaxUpdate(target);
            }
        };

        link.add(new WarnChangePromptOnClickBehavior());
        return link;
    }

};  

当前的行为是,如果没有更改选项卡切换没有提示。如果有变化,我会得到提示。如果没问题 tabDirty 重置并转到下一页清除更改。问题是,如果我单击取消,我仍会导航到下一个选项卡并丢失更改。我知道 onClick 中有些东西我需要更改,但它只是没有向我注册。

拦截JS事件循环并不容易,尤其是在使用Ajax请求时。

这里有一种方法可以完成这项工作:

  1. warnOnChange()中如果dirty则调用event.preventDefault()event.stopImmediatePropagation()。这将告诉浏览器不要跟随 link / 进行 Ajax 调用。然后像现在一样显示确认对话框。
  2. 如果用户按下 Cancel 则无事可做
  3. 如果使用确认则将dirty设置为false并执行jQuery(event.target).triggerHandler(event.type),即在link上执行相同的事件(click)。这次它不会变脏,它将继续 Ajax 调用。

不确定这样做是否合适,但我这样解决了我的问题:

相同的旧 js 只是稍微修改为 return 用户选择的内容:

function warnOnChange(){
    decision = true;
    if(tabDirty){
        decision = confirm('Leave?');
        if(decision){
            resetTab();
        }
    }
    return decision;
}

放弃了整个行为代码,虽然我仍然认为它可以使用,只是目前不确定...

所以为了让这一切在 link 上工作,我用 precondition:

覆盖了 link 的 updateAjaxAttributes
AjaxTabbedPanel<CustomAjaxTab> tabbedPanel = new AjaxTabbedPanel<CustomAjaxTab>("tabbedPanel", tabList, new Model<>(0)) {

private static final long serialVersionUID = 1L;

@Override
protected WebMarkupContainer newLink(final String linkId, final int index) {
    AjaxFallbackLink<Void> link = new AjaxFallbackLink<Void>(linkId) {

        private static final long serialVersionUID = 1L;

        @Override
        protected void updateAjaxAttributes( AjaxRequestAttributes attributes ) {
            super.updateAjaxAttributes( attributes );

            AjaxCallListener ajaxCallListener = new AjaxCallListener();
            //very important to use the "return" if not then nothing happens with the response
            ajaxCallListener.onPrecondition("return " + WARN_ON_CHANGE);

            attributes.getAjaxCallListeners().add( ajaxCallListener );
        }

        @Override
        public void onClick(final AjaxRequestTarget target) {
            TabbedPanel<CustomAjaxTab> selectedTab = setSelectedTab(index);
            CustomAjaxTab tab = tabList.get(index);
            if (target != null) {

                tab.getPanel(linkId);

                target.add(selectedTab);
            }
            onAjaxUpdate(target);
        }
    };

    link.add(new WarnChangePromptOnClickBehavior());
    return link;
}
};