Search code examples
javascriptangularjsangularjs-components

How can I make a bindings property mandatory in an angularJs component


If I have the following component:

angular.module('myApp').component('myComponent', {
    templateUrl: 'myComponent.html',
    bindings: {
        myPropOne: '<',
        myPropTwo: '<'
    }
});

and later on, I instantiate the component via html without passing myPropTwo like this:

<my-component my-prop-one="vm.prop1"></my-component>

can I tell angular to fail because myPropTwo wasn't passed? Yes, I know I could do something like:

angular.module('myApp').component('myComponent', {
    templateUrl: 'myComponent.html',
    bindings: {
        myPropOne: '<',
        myPropTwo: '<'
    },
    controller: function() {
        this.$onInit = function() {
            if(this.myPropTwo  === undefined) {
                throw new Error('myPropTwo must be passed');
            }
        }
    }
});

In other words, can I make myPropTwo mandatory without having to do it manually. Is there a native way to do this?

Edit:

Seems like @FrankModica is correct. That's too bad :(... Here is an example in jsFiddle that hopefully will give some understanding based in @FrankModica answer: https://jsfiddle.net/cafesanu/5L19t3jx/2/


Solution

  • There doesn't seem to be a way to accomplish what you need without doing it manually.

    Component bindings are technically "required" automatically, and only optional if you add a question mark. But for one-way bindings, this doesn't seem to mean much. If the binding is optional and you don't supply it, that property simply won't be on your component's controller. But if the binding is required and you don't supply it, that property will be on the your component's controller as undefined.

    For example, if myPropOne is optional and you don't supply it, you won't see it when logging the controller object. If you only supply myPropTwo as "prop2", that's all you will see:

    bindings: {
        myPropOne: '<?', // optional
        myPropTwo: '<'   // required
    }
    
    controller: function () {
        this.$onInit = function () {
            console.log(this);
    
            // myPropTwo: "prop2"
    
            console.log(this.myPropOne === undefined);
            console.log(this.hasOwnProperty('myPropOne'));
    
            // true
            // false
        }
    }
    

    But if myPropOne is required and you don't supply it, the property is actually on the controller, but it is undefined. So you will see it if you log the controller object:

    bindings: {
        myPropOne: '<',  // required
        myPropTwo: '<'   // required
    }
    
    controller: function () {
        this.$onInit = function () {
            console.log(this);
    
            // myPropOne : undefined
            // myPropTwo: "prop2"
    
            console.log(this.myPropOne === undefined);
            console.log(this.hasOwnProperty('myPropOne'));
    
            // true
            // true
        }
    }
    

    The difference seems to be more obvious when using the = binding. If the binding is required, and you don't supply it but you try to assign to it in the component's controller, you will get an error. This makes sense since Angular doesn't know how to propagate the change.