How to trigger form submit programmatically in AngularJS?

From Angular's documentation it follows that ngSubmit is a preferred way of submitting a form. All pending operations are immediately finished and $submitted flag is set as well. Whereas listening to ngClick event does not have the same effect.

Now I need to submit a form with hotkeys having all the goodies of ngSumbit approach. Hence I need some way to trigger standard submit workflow.

I tried submit() on DOM form and it worked, but angular's form object attached to scope contains no references to DOM form, thus I need to access it through jqLite:

var frm = angular.element('#frmId');
frm.submit();

I didn't like this solution for accessing DOM in controller code so I created a directive:

function wuSubmit() {
    return {
        require: 'form',
        restrict: 'A',
        link: function(scope, element, attributes) {
            var scope = element.scope();
            if (attributes.name && scope[attributes.name]) {
                scope[attributes.name].$submit = function() {
                    element[0].submit();
                };
            }
        }
    };
}

which extends form object with $submit method.

Both variants do not work for yet unknown reason. form.submit() tries to send data, default action is not prevented.


Update 1
It turns out that Angular listens to click events of elements having type="input".
Eventually I decided to trigger click event for that element:

wuSubmit.$inject = ['$timeout'];
function wuSubmit($timeout) {
    return {
        require: 'form',
        restrict: 'A',
        link: function (scope, element, attributes) {
            var submitElement = element.find('[type="submit"]').first();

            if (attributes.name && scope[attributes.name]) {

                scope[attributes.name].$submit = submit;
            }

            function submit() {
                $timeout(function() {
                    submitElement.trigger('click');
                });
            }
        }
    };
}

Is there any out of the box solution for this functionality?

You can modify your directive code a bit like:

function wuSubmit() {
    return {
        require: 'form',
        restrict: 'A',
        link: function(scope, element, attributes) {
            var scope = element.scope();
            if (attributes.name && scope[attributes.name]) {
                scope[attributes.name].$submit = function() {
                    // Parse the handler of submit & execute that.
                    var fn = $parse(attr.ngSubmit);
                    $scope.$apply(function() {
                        fn($scope, {$event: e});
                    });
                };
            }
        }
    };
}

Here you don't have to add wu-submit everywhere. ng-submit will work.

Hope this helps!

Hide a proper submit button for your form and call click event on it, that way you get all the mumbo jumbo, validation, angular stuff.