Search code examples
angularjsangular-directive

How to bring data from parent directive to child directive in angular


I have 2 directives as "chart" and "datapoint". Here the chart directive is the parent of the datapoint directive. I am trying to bring some data from parent directive to the children, but it throws an error.

Here is my directives:

"user strict";

angular.module("chartDirective", [])
    .directive('chart', function () {
        return {
                replace:true,
                transclude : true,
                templateUrl : '/views/directiveViews/svg.html',
                controller : function ($scope, $element, $attr) {
                    this.name="Afzil"; //setting up name.
                }
            }
    })

    .directive('datapoint', function () {
        return {
            replace : true,
            require :'^chart',
            template : '<circle cx="20" cy="20" ng-attr-r="{{radius}}" ng-attr-stroke-width="{{strokeWidth}}" fill="#FFF" stroke="#5B90BF" />',
            link : function (scope, element, attr, controller) {
                scope.radius = 4;
                scope.strokeWidth = 3;
                console.log(controller); //trying to console.
            }
        }
    })

The error I am getting is:

https://docs.angularjs.org/error/$injector/unpr?p0=$attrProvider%20%3C-%20$attr

But using this link, I am not able to find a solution. Any one know what the problem is?


Solution

  • It is because you are trying to pass $attr into your controller. There is no $attr. In the link function $attr is the third argument that gives you access to the attributes of the directive.

    From the angular directives guide:

    Savvy readers may be wondering what the difference is between link and controller. The basic difference is that controller can expose an API, and link functions can interact with controllers using require.

    Best Practice: use controller when you want to expose an API to other directives. Otherwise use link.

    Here is a demonstration on how to pass attribute values from the parent controller (using require) to the child directive.

    Plunker Demo

    app.directive('chart', function () {
            return {
                    replace:true,
                    scope: true,
                    controller : function ($scope, $element, $attrs) {
                        this.name="Afzil"; //setting up name.
                        this.myAttrVal = $attrs.myAttr;
                    }
                }
        })
    
        .directive('datapoint', function () {
            return {
                replace : true,
                scope: true,
                require :'^chart',
                template : '<div>{{valFromChart}}</div>',
                link : function (scope, element, attr, chart) {
                    scope.radius = 4;
                    scope.strokeWidth = 3;
                    scope.valFromChart = chart.myAttrVal;
                    console.log('from chart: ' + chart.myAttrVal); //trying to console.
                }
            }
        })
    

    In the datapoint directive, we pass some arbitrary value as an alias for the controller we have require'ed. We can then access anything attached to that controller.