angularjsdata-bindingisolate-scope

bind directive action to parent controller AngularJS


I have a directive for profile update and I want to trigger update action from the parent scope. Here what look like my code:

main.js

angular.module('app')
.directive('profile',{
    scope: {
        updateFromDirective: "="
    },
    template: '<form><input ng-model="name"/></form>',
    controller: function(){
        this.updateFromDirective = function(){
            /* update here */
        };
    }
})
.controller('Ctrl', function(){
    this.updateFromController = function(){
        if(condition){
            /* how do I call updateFromDirective here ??? */
        }
    };
});

index.html

<div ng-controller="Ctrl">
    <profile updateFromDirective="updateFromController"></profile>
    <button ng-click="updateFromController()">Update</button>
</div>

Solution

  • Pass your function reference to the directive using '&' if you are passing like this updateFromController() else use '=' for updateFromController (both will work)

    Now in your case

    Note: I'm assuming that you don't want to use $scope since you have your functions in controllers with this

    To call a controller function from the directive you need to pass it as callback and can call that callback like below

    angular.module('app',[])
    .controller('Ctrl', function(){
        this.updateFromController = function(){
             alert('In Contrller')
        };
    }).directive('profile',function(){
       return{
        scope:{
          controllercallback: "&"
        },
        template:'<input ng-model="name"/><br/><button ng-click="ctrl.updateFromDirective()">Update</button>',
        controller:function(){
          this.updateFromDirective=function(){
            alert('In Directive')
            this.controllercallback();
          }
        },
        bindToController: true,
        controllerAs:'ctrl'
      }
    
    })
    

    Your html should look like below

     <div ng-controller="Ctrl as vm">
     <profile controllercallback="vm.updateFromController()"></profile>
    

    But here your button is in the directive itself.

    If you don't want your button to be part of your directive you can use publish/subscriber model given by angular like below

    angular.module('app',[])
    .controller('Ctrl', function($scope){
        this.updateFromController = function(){
             $scope.broadcast('calldirective');
        };
    }).directive('profile',function(){
       return{
        template:'<input ng-model="name"/>',
        controller:function($scope){
           $scope.$on('calldirective', function() {
             alert('In Directive')
           }); 
    
        }
    
    
    
    }
    
    })