Directives can be weird, as can Angular templates. References to undefined scope variables will fall on deaf ears and sometimes you can spend hours pulling your hair out.
Here’s the problem I was facing… Your directive looks like the following:
<my-awesome-directive entity="entity" form-label="great" service-instance="myService"></my-awesome-directive>
If I always want these scope bindings to be present, then why should I have to code defensively to check these exist and also allow another developer to make a mistake by omitting these which will ultimately be hard to debug and trace?
I’ve put together a simple library that enforces parameters on your directive’s scope to exist. There are a few ways it will check these such as must be present, present because of and one of a given list must be present.
Usage
Include the module in your app.
angular.module('myapp', ['reqParams']);
Use in a directive
angular.module('myapp').directive('myAwesomeDirective' function() {
return {
restrict: 'E',
scope: {
entity: '=',
formLabel: '@',
serviceInstance: '='
},
controller: [
'$scope', 'reqParams',
function($scope, reqParams) {
reqParams($scope).has(['entity', 'formLabel', 'serviceInstance']);
}]
};
});
Must Be Present
reqParams($scope).has('andAlsoThis');
reqParams($scope).has(['this', 'andThis']);
Now if any of these scope bindings are missing (i.e. undefined) there will be an error thrown detailing which are missing.
Deep Find
You may specify properties required on these scope bindings with a simple dot syntax (prop.deeperProp.evenDeeperProp), for example:
reqParams($scope).has('myEntity.HasRequiredProperty')
This is supported on any rule.
Present Because Of
reqParams($scope).hasWhen('ifHasThis', 'ensurePresent')
reqParams($scope).hasWhen('ifHasThis', ['ensureThis', 'andThisToo'])
This will validate serviceInstance is present if the showExtraArea scope binding is also present.
One Must Be Present
reqParams($scope).hasOne(['eitherThis', 'orThis']);
This will validate that either the showFirstArea or the showSecondArea is present. You define these on a case-by-case array basis in an outer array.
All At Once
The library provides a Fluid API so you can chain up as many of these rules as you’d like to.
reqParams($scope).has('this').hasWhen('ifHasThis, 'ensureThisToo').hasOne(['eitherThis', 'orThis']);
Check out the library on GitHub