Reputation: 2857
I have a wicket application on a page we have various forms for the same model split into separate tabs. What I need to do is whenever a tab is clicked check to see if a js variable tabDirty
is set to true or false. If it is true
I would launch a confirm
prompt if okay then reset that form and move to the clicked tab. If cancel stay on that tab with keeping current changes.
I have this js for the warning nothing fancy
function warnOnChange(){
if(tabDirty){
decision = confirm('Leave?');
if(decision){
resetTab(); //sets tabDirty back to false
} else {
return false;
}
}
}
I have a super simple wicket behavior
public class WarnChangePromptOnClickBehavior extends Behavior {
@Override
public void bind(Component component) {
component.add(JQBehaviors.mouseClick(EditMerchant.WARN_ON_CHANGE));
}
}
and that behavior is added to the 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;
}
};
Current behavior with this is that if there is no change the tabs switch no prompt. If there is a change then I get the prompt. If okay tabDirty
is reset and go to the next page clearing changes. Issue is that if I click cancel I still navigate to the next tab and lose changes. I know there is something in onClick
I need to change but it is just not registering with me.
Upvotes: 0
Views: 747
Reputation: 2857
Not sure if this is the appropriate way to do this but I solved my issue like this:
Same old js just slightly modified to return what the user chose:
function warnOnChange(){
decision = true;
if(tabDirty){
decision = confirm('Leave?');
if(decision){
resetTab();
}
}
return decision;
}
Dumped the whole behavior code although I still think it could be used just not sure at the moment...
So to make this all work on the link I override the updateAjaxAttributes
of the link with a precondition
:
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;
}
};
Upvotes: 0
Reputation: 17533
It is not that easy to intercept the JS event loop, especially when using Ajax requests.
Here is an approach that may do the job:
warnOnChange()
if dirty
then call event.preventDefault()
and event.stopImmediatePropagation()
. This will tell the browser to not follow the link / make an Ajax call. Then show the confirmation dialog as you do now.Cancel
then there is nothing more to dodirty
to false
and do jQuery(event.target).triggerHandler(event.type)
, i.e. execute the same event (click
) on the link. This time it won't be dirty and it will proceed with the Ajax call.Upvotes: 1