Sponsored By Kids In Touch

Preventing AngularJS From Hijacking Forms


UPDATE : I've found a solution! See bottom of post or continue reading if you like to hear me whine!
UPDATE 2 : This doesn't actually work.....

I've written before (here and here about how I hate that AngularJS hijacks forms. Yes, I whine a lot.

I've posted on Twitter and seen posts on StackOverflow about trying to disable Angular's hijacking of forms. Unfortunately, there does not seem to be a simple way to tell AngularJS to keep it's paws off a form. I've suggested on Twitter to have a "ng-keep-your-effing-paws-off-my-form" directive.

So, in more frustration with this issue, I've done some more digging. The best option I have come up with is to actually comment out the "form" and "ngForm" directives in AngularJS source code. Like this:

angularModule('ng', ['ngLocale'], ['$provide',
function ngModule($provide) {
  $provide.provider('$compile', $CompileProvider).
    directive({
        a: htmlAnchorDirective,
        input: inputDirective,
        textarea: inputDirective,
//            form: formDirective,
        script: scriptDirective,
        select: selectDirective,
        style: styleDirective,
        option: optionDirective,
        ngBind: ngBindDirective,
        ngBindHtml: ngBindHtmlDirective,
        ngBindTemplate: ngBindTemplateDirective,
        ngClass: ngClassDirective,
        ngClassEven: ngClassEvenDirective,
        ngClassOdd: ngClassOddDirective,
        ngCsp: ngCspDirective,
        ngCloak: ngCloakDirective,
        ngController: ngControllerDirective,
//            ngForm: ngFormDirective,
        ngHide: ngHideDirective,
        ngIf: ngIfDirective,
        ngInclude: ngIncludeDirective,

The problem with this is that it is nuclear. It's an across the board removal of any form assistance from Angular for an entire project or app.

I'd really love a simple "ng-no-form" directive that I can put on a form that I will manage in my own way.

Is there any way to do this?

Please let me know on Twitter as I don't have any commenting capabilities on Ghost right now.

UPDATE : Here is a solution:

So, I got tired of my whiny moaning above and decided to try to tackle this issue once and for all. I got rid of the stupid commented out "form" and "ngForm" directives above. Then, I started trying to play with the actual directive definition. I was trying to see if I could detect an attribute on the form and skip the form directive if requested.

var formDirectiveFactory = function(isNgForm) {
  return ['$timeout', function($timeout) {
    var formDirective = {
      name: 'form',
      restrict: 'E',
      controller: FormController,
      compile: function() {
        return {
          pre: function(scope, formElement, attr, controller) {
            if( attr.skipangular === 'true') {
                console.warn(' NO ANGULAR ');
                return;
            }

Guess what? That actually worked. With the compile function just returning true, Angular doesn't attach all of the functionality and modelControllers to the form. Progress! However, while typing in JetBrains, "ng-non-bindable" popped up for code completion.. Hummm? What is that?

It turns out that ng-non-bindable is EXACTLY what I've been looking for all along. I can now define a form with the ng-non-bindable attribute and voila! AngularJS keeps it's paws off my form. Thanks JetBrains!

Across the board non-hijacking:

<form name="inviteContactForm" ng-non-bindable>

Single field hijacking prevention:

<input type="email" ng-non-bindable ....>

UPDATE 2 : Unfortunately, this does not actually work.

Argh. Putting ng-non-bindable in the form element means ALL of the stuff inside the form is ignored. So, if you have a:

<input ng-model="user.name"/>

you get no binding of the user name into the field. Crap.