0

I'm trying to call $scope function in AngularJS Directive in following way

JS

    var app = angular.module('app', []);
    app.controller('customDirEx', ['$scope', function ($scope) {
    $scope.users = [
        {
            name: 'ABC',
            rno: '100'
        },
        {
            name: 'DEF',
            rno: '200'
        }
    ];

    $scope.onChangeFoo = function() {
        console.log('test');
    }

    $scope.dataChange = function() {
        console.log('test abc', $scope);
        $scope.onInitEle();
    }

    $scope.dataChange();
}]);

app.directive('studentInfo', function(){
    var directive = {};

    directive.scope = {
        user: '=user',
        onInitEle: '='
    };
    directive.restrict = 'EA';
    directive.template = '<div>Name: {{user.name}}<br>R.NO: {{user.rno}}</div>';

    return directive;
});

HTML

<body ng-app="app">
        <div ng-controller="customDirEx">            
            <student-info ng-repeat="user in users" user="user" on-init-ele="onChangeFoo"></student-info>            
        </div>
    </body>

$scope.onInitEle is not a function - this is the error I'm getting

The purpose of calling onClickEle instead of onChangeFoo here is too reuse the JS at multiple places so that I can call onChangeBar when required.

11
  • possible duplicate of stackoverflow.com/questions/20047489/… Commented Feb 15, 2018 at 14:15
  • You have to pass a function with '&', not '='. Commented Feb 15, 2018 at 14:18
  • @Zooly Before posting question I tried that too but no use Commented Feb 15, 2018 at 14:20
  • Please see this answer, it should perfectly match with your need stackoverflow.com/a/18378602/4781975 Commented Feb 15, 2018 at 14:21
  • 2
    You should be using angularjs components instead of a directive. It has way more handy api for what you try to achieve. Commented Feb 15, 2018 at 14:35

2 Answers 2

1

First you have to replace "onClickEle: '='" with "onClickEle: '&'" The use of & means you are passing reference.

The second mistake is you didn't call it from your template. So, I have changed your template code as:

directive.template = '<div ng-click="onClickEle()"> Name: {{user.name}}<br>R.NO: {{user.rno}}</div>';

The third mistake is: you are calling $scope.onClickEle(); in controller, however onClickEle() not defined in controller, its under directive. So, controller unable to find the method.

The forth mistake is you are passing on-click-ele="onChangeFoo" in the direcive, the correct syntax will be:

on-click-ele="onChangeFoo()"

The working updated code given below:

var app = angular.module('app', []);
    app.controller('customDirEx', ['$scope', function ($scope) {
    $scope.users = [
        {
            name: 'ABC',
            rno: '100'
        },
        {
            name: 'DEF',
            rno: '200'
        }
    ];

    $scope.onChangeFoo = function() {
        console.log('test....');
    }

    $scope.dataChange = function() {
        console.log('test abc', $scope);
        //$scope.onClickEle();
    }

    $scope.dataChange();
}]);

app.directive('studentInfo', function(){
    var directive = {};

    directive.scope = {
        user: '=user',
        onClickEle: '&'
    };
    directive.restrict = 'EA';
    directive.template = '<div ng-click="onClickEle()"> Name: {{user.name}}<br>R.NO: {{user.rno}}</div>';

    return directive;
});
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="app">
        <div ng-controller="customDirEx">            
            <student-info ng-repeat="user in users" user="user" on-click-ele="onChangeFoo()"></student-info>            
        </div>
</body>
</html>

Sign up to request clarification or add additional context in comments.

3 Comments

@Ahmed thanks for your efforts but it doesn't fulfill my requirements. I think you had confused with 'onClickEle()', sorry for that. I had replaced 'onClickEle()' with 'onInitEle()', I think it makes sense now.
@Mahesh.D, you cannot call directive function from controller. Directive can call the controller function, if you pass using & attribute, its point number 3.
@Ahmed if possible can you check my answer
1

Somehow I can manage this by creating separate controller for directive but don't know the theory behind, it would be very helpful if someone explains clearly.

JS

var app = angular.module('app', []);
app.controller('customDirEx', ['$scope', function ($scope) {
    $scope.users = [
        {
            name: 'ABC',
            rno: '100'
        },
        {
            name: 'DEF',
            rno: '200'
        }
    ];

    $scope.onChangeFoo = function() {
        console.log('test');
    }        
}]);

app.controller('StudentCtrl', ['$scope', function($scope){
    $scope.onInitEle();    
}]);

app.directive('studentInfo', function(){
    var directive = {};

    directive.scope = {
        user: '=user',
        onInitEle: '='
    };
    directive.restrict = 'EA';
    directive.template = '<div>Name: {{user.name}}<br>R.NO: {{user.rno}}</div>';
    directive.controller = 'StudentCtrl';

    return directive;
});

HTML

<body ng-app="app">
     <div ng-controller="customDirEx">            
            <student-info ng-repeat="user in users" user="user" on-init-ele="onChangeFoo"></student-info>            
     </div>
</body>

Working JSFiddle

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.