Block form submit after XMLHttpRequest


#1

Hi all,

I’m having this issue where I have to call a validation REST-service when submitting a custom form.
If the response is true, I can go ahead with the submit of the form. If the result of the call is false, I have to call evt.submitPrevented = true; and stop the form submit.

It’s basically not working because it’s impossible to call the service in a blocking/synchronous fashion.
The thing is, I cannot do the validation in a service-task as the user should be informed immediately.

So I’m having this now;

camForm.on('submit', function(evt) {
	var payload = {
	    'popId': $scope.popId,
	    'popWoId': $scope.popWoId,
	    'context': {
	        'companyId': $scope.selectedCompany.id,
	        'buildingId': $scope.selectedBuilding.id,
	        'userId': $scope.selectedUser.id,
	        'contractType': $scope.contractType
	    }
	};

	$http.post('/process-rest/validate-workorder', JSON.stringify(payload), {'responseType':'application/json'})
        .then(function (resp) {
            var success = resp.status === 200;
            if (!success) {
                // Obviously, too late and form will have been submitted
				evt.submitPrevented = true;
            }

        })
        .catch(function(err) {
         	evt.submitPrevented = true;

            if(window.console && err) {
                console.error('err: ' + err.message);
            }
        });
});

Another thing I thought of doing was first calling evt.submitPrevented = true; and later, when I get my success response, submit the form programatically. But I have basically no idea how to do it in a proper way :stuck_out_tongue:

Any help is welcome.


#2

Anyone from the Camunda team perhaps? Anyone? No one? :sweat:


#3

found a workaround, can be close.


#4

@nvanbelle What was the workaround?


#5

Some workarounds have been discussed here: Async $http.post request validation


#6

For this to work I have used a hidden field and programatically set it valid or invalid. The validity function was called on certain field changes. You could also use a debounce.

<input type="text" ng-show="false" name="woValid" ng-model="woValid"/>

         $scope.woValidityFn = (function() {
                var previousSN = '',
                    previousCommId = '';

                return function($event) {
                            if ($scope.serialNumber !== previousSN
                                || $scope.communicationId !== previousCommId) {

                                doValidationCall()
                                    .then(function (isValid) {
                                        $scope.userForm.woValid.$setValidity("required", isValid);
                                    })
                                    .catch(function (err) {
                                        $scope.userForm.woValid.$setValidity("required", false);

                                        if (window.console && err) {
                                            console.error('err: ' + err.message);
                                        }
                                    });

                                previousSN = $scope.serialNumber;
                                previousComm = $scope.communicationId;
                            }
                        }
                    }

                    function doValidationCall() {
                        var payload = {
                            'popId': $scope.popId,
                            'popWoId': $scope.popWoId,
                            'orderNumber': $scope.orderNumber,
                            'context': {
                                'companyId': $scope.selectedCompany.id,
                                'buildingId': $scope.selectedBuilding.id,
                                'userId': $scope.selectedUser.id,
                                'contractType': $scope.contractType
                            },
                            'product': {
                                'serialNumber': $scope.productSN,
                                'communicationId': $scope.communicationId
                            }
                        };

                        return $http.post('/process-rest/validate-workorder', JSON.stringify(payload), {responseType:'application/json'})
                            .then(function (resp) {
                                  return resp.status === 200;
                            })
                            .catch(function(err) {
                                  return false;
                            })
                    }
                };
            })();

#7

@nvanbelle you can also implement server side validation on the form submission: Form Server Validations: Generic Form Validator using Javascript

This can allow you to perform the server side system-to-system check against the submitted data.