You sit down and start your next frontend task. Likely, that task will require you to get input from the user. Maybe you’re adding a comments section, maybe it’s a little survey, or some simple form.

Handling inputs and forms with AngularJS can be a breeze, especially since AngularJS provides a lot of tools for efficiently doing just that. You need to add validations, like making sure the user filled all the fields, and it’s just a matter of adding a required attribute to all controls and checking the form’s $valid property.

I love it when instead of writing lots of code I simply do something along the lines of:

1 <button ng-disabled= "!$ctrl.form.$valid" type= "submit" > Save </button>

(I’m not missing an ng-click there BTW, for submitting a form you should usually have ng-submit on the <form> element.)

But, what happens when you have use some custom control, instead of the browser’s builtins (e.g. input s, textarea s, select s)?

It usually looks ends up looking like this:

1 <my -custom-control value= "$ctrl.someValue" > < /my-custom-control>

And suddenly, you can’t just use required , and the form’s $valid doesn’t work, and instead of using $ctrl.form.$valid to check everything is filled you have to write code along the lines of:

1 2 3 function isValid () { return self . form . $valid && self . someValue !== '' ; }

Custom Controls Don’t Have to Suck

You don’t have to leave the comforts of Angular’s forms just because you have a custom control. You just need to make sure to wire things up properly.

It’s as easy as using ng-model to pass the value to the control, instead of some binding of yours. Here’s an example of refactoring a component to use ngModel:

1 2 3 4 5 6 angular . module ( 'app' ). component ( 'myCustomControl' , { template : '...' , bindings : { value : '=ngModel' } });

You can still use the same name the component used before, such as value above, but make sure that the external name is ngModel . Using that component looks like so:

1 < my - custom - control ng - model = "$ctrl.someValue" required >

Just by using the ng-model attribute, Angular’s ngModel directive will be used, and sprinkle its own magic. That means that it’ll register with the parent form, and add the needed validations.

For example, the required above will simply work now, and so will our original button, no need for custom code.

So please don’t write custom controls like an animal. Use Angular properly.