XF 2.3 Cancelling form submit by `e.preventDefault()` is not working

BredyAK

Member
I'm trying to create a plugin. I want to use js to cancel a form submit by following code:
JavaScript:
XF.on(form, 'ajax-submit:before', XF.proxy(this, 'beforeSubmit'));
// ...
function beforeSubmit(e) {
    console.log('beforeSubmit:', this.submitting);
    e.preventDefault();
    this.submitting = true;
}

Expected: When I click the submit button, it won't submit and console logs beforeSubmit: false.

Actually: Console shows beforeSubmit: false, but then it was submitted.

XenForo version: 2.3.7
 
try
Code:
 e.stoppropagation()
as well
I'm trying to change e.preventDefault() to e.stopPropagation() (or e.stopImmediatePropagation()), but it still won't interrupt the submit.
(e is a SubmitEvent, and e.cancellable == true)

It should be work, I think, as it cancelled the event bubbling... but actually not.
 
In XenForo 2.3, the ajax-submit:before event uses a CustomEvent where the prevention mechanism isn't just e.preventDefault(). You need to set a flag on the event's detail object.
Code:
function beforeSubmit(e) {
    console.log('beforeSubmit:', this.submitting);
    e.preventDefault();
    e.preventSubmit = true;
    this.submitting = true;
}

If that doesn't work, try accessing through the detail property:

Code:
function beforeSubmit(e) {
    console.log('beforeSubmit:', this.submitting);
    e.preventDefault();
    if (e.detail) {
        e.detail.preventSubmit = true;
    }
    this.submitting = true;
}

The XenForo Form handler checks for this preventSubmit flag in addition to (or instead of) the standard defaultPrevented property when determining whether to proceed with the AJAX submission.
 
In XenForo 2.3, the ajax-submit:before event uses a CustomEvent where the prevention mechanism isn't just e.preventDefault(). You need to set a flag on the event's detail object.
Code:
function beforeSubmit(e) {
    console.log('beforeSubmit:', this.submitting);
    e.preventDefault();
    e.preventSubmit = true;
    this.submitting = true;
}

If that doesn't work, try accessing through the detail property:

Code:
function beforeSubmit(e) {
    console.log('beforeSubmit:', this.submitting);
    e.preventDefault();
    if (e.detail) {
        e.detail.preventSubmit = true;
    }
    this.submitting = true;
}

The XenForo Form handler checks for this preventSubmit flag in addition to (or instead of) the standard defaultPrevented property when determining whether to proceed with the AJAX submission.

Thank you, but it still not working..

It seems defaultPrevented == true, but still an XHR to the backend and shows the error message box from backend.

I have:
JavaScript:
function beforeSubmit(e) {
    console.log('beforeSubmit:', e);
    if (!this.submitting) {
        e.preventDefault();
        e.preventSubmit = true;
        if (e.detail) {
            e.detail.preventSubmit = true;
        }
        this.submitting = true;
        this.create()
        console.log('Stopped ', e);
   }
}

e of beforeSubmit:
Code:
isTrusted: true
bubbles: true
cancelBubble: false
cancelable: true
composed: false
currentTarget: null
defaultPrevented: true
eventPhase: 0
returnValue: false
srcElement: form.block
submitter: button#js-signUpButton.button.button--primary
target: form.block
timeStamp: 13756.299999952316
type: "submit"
[[Prototype]]: SubmitEvent

e of Stopped:
Code:
isTrusted: true
preventSubmit: true
bubbles: true
cancelBubble: false
cancelable: true
composed: false
currentTarget: null
defaultPrevented: true
eventPhase: 0
returnValue: false
srcElement: form.block
submitter: button#js-signUpButton.button.button--primary
target: form.block
timeStamp: 12920.900000035763
type: "submit"
[[Prototype]]: SubmitEvent
 
The Solution:

You need to listen for ajax-submit:before (not the native submit event) and set preventSubmit = true directly on that event object:
Code:
XF.on(this.target, 'ajax-submit:before', (e) => {
    if (!this.submitting) {
        e.preventSubmit = true;
        this.submitting = true;
        this.create();
    }
});

The XF_CustomEvent class (line 10944) extends native Event and copies all options directly onto itself as properties. So when you set e.preventSubmit = true in your handler, it modifies the same object that XenForo checks after the event completes.

Are you currently listening for the native submit event instead of ajax-submit:before? That would explain why your preventSubmit flag isn't working - you're setting it on the wrong event object.
 
The Solution:

You need to listen for ajax-submit:before (not the native submit event) and set preventSubmit = true directly on that event object:
Code:
XF.on(this.target, 'ajax-submit:before', (e) => {
    if (!this.submitting) {
        e.preventSubmit = true;
        this.submitting = true;
        this.create();
    }
});

The XF_CustomEvent class (line 10944) extends native Event and copies all options directly onto itself as properties. So when you set e.preventSubmit = true in your handler, it modifies the same object that XenForo checks after the event completes.

Are you currently listening for the native submit event instead of ajax-submit:before? That would explain why your preventSubmit flag isn't working - you're setting it on the wrong event object.
Yes, I'm listening ajax-submit:before.
I have no idea to track why it is SubmitEvent, XHR is from minified core-complied.js
 
The Solution:

You need to listen for ajax-submit:before (not the native submit event) and set preventSubmit = true directly on that event object:
Code:
XF.on(this.target, 'ajax-submit:before', (e) => {
    if (!this.submitting) {
        e.preventSubmit = true;
        this.submitting = true;
        this.create();
    }
});

The XF_CustomEvent class (line 10944) extends native Event and copies all options directly onto itself as properties. So when you set e.preventSubmit = true in your handler, it modifies the same object that XenForo checks after the event completes.

Are you currently listening for the native submit event instead of ajax-submit:before? That would explain why your preventSubmit flag isn't working - you're setting it on the wrong event object.

It works after I reinstalled my xenforo dev server.. (why?)

Thanks a lot anyway.
 
Back
Top Bottom