How do I bind a controller to a directive in AngularJS?

Let's say I have the following structure HTML

:

<div ng-app="testApp">
    <div ng-controller="controller1">
        {{controller1}}
    </div>
    <div ng-controller="controller2">
        {{controller2}}
    </div>
    <div ng-controller="controller3">
        {{controller3}}

        <test-directive></test-directive>
    </div>
</div>

      

There ng-controller="controller3"

is a custom directive inside .

The directive is as follows:

ang.directive("testDirective", function() {
    return {
        restrict: 'AE',
        link: function (scope, elem, attrs) {
            console.log(scope);
        },
        template: "<h3>I return $scope.controller3</h3>"
    }
});

      

Now $scope

contains data from ng-controller="controller3"

. How can I bind a custom controller to it? So instead the directive passes its parent controller, I want to also pass, for example controller1, its data.

I need to pass any controller because the directive depends on the data inside the given controller.

I cannot replace <test-directive>

inside the required controller

Here you can play with

var ang = angular.module('testApp', []);

ang.controller("controller1", controller1);
function controller1($scope) {
	$scope.controller1 = "controller1";
}

ang.controller("controller2", controller2);
function controller2($scope) {
	$scope.controller2 = "controller2";
}

ang.controller("controller3", controller3);
function controller3($scope) {
	$scope.controller3 = "controller3";
}

ang.directive("testDirective", function() {
	return {
		restrict: 'AE',
		link: function (scope, elem, attrs) {
			console.log(scope);
		},
    template: "<h3>I return $scope.controller3</h3>"
	}
});
      

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js"></script>
<div ng-app="testApp">
	<div ng-controller="controller1">
		{{controller1}}
	</div>
	<div ng-controller="controller2">
		{{controller2}}
	</div>
	<div ng-controller="controller3">
		{{controller3}}
		
		<test-directive></test-directive>
	</div>
</div>
      

Run codeHide result



Real case scenario:

I made a pagination directive . You can call the directive by placing it <ng-pagination></ng-pagination>

anywhere on the page.

The directive creates pagination from the given dataset. However, a dataset can contain anything. It doesn't depend on values, etc.

There is only one requirement for a directive ... It looks inside the controller if it has a $scope

called $scope.result

. $scope.result

populated with data from the API call.

Then pagination is recreated object

with 10 results per page.

I have a problem: ng-controller

can be anywhere on the page can also <ng-pagination></ng-pagination>

.

What I want to archive looks something like this:
I assign a data attribute to [ng-pagination]

. Called: data-controller

. Then you can pass the controller name to it. The directive then has access to all data within that controller.

It will look like this:
<ng-pagination data-controller="controller1" show-next="true" ...></ng-pagination>


UPDATE

I found out that you can assign a controller by following these steps:

ang.directive("directive", function() {
    return {
        controller: "[CONTROLLER NAME]"
    }
});

      

Although it is possible it is possible:

ang.directive("directive", function() {
    return {
        controller: "{{controller}}",
        link: function (scope, elem, attrs) {
            $scope.controller = "[CONTROLLER NAME]"
        }
    }
});

      

However, this gives me an error:

Error: ng: areq Bad argument The
argument '{{controller}}' is not a function, got undefined

+3


source to share


1 answer


I was playing with controller

as shown in my update and reading this guide . I came up with a solution below

So how can you pass anyone controller

to directive

?

  • First you need to highlight scope

    withscope: {}

  • Set the controller property inside the directive with controller: "@"

    . Now you can assign values ​​to it with the following step
  • Set the property name: "controller"

    . I will explain how to use this below.

I was told isolating

that the area is necessary, but it works, however.

If you post now directive

, you can now assign any controller to it by doing the following:

<ng-pagination data-controller="[CONTROLLER NAME]>



The property name name

doesn't matter. So if you want to call it, assign-any

you can pass it attribute

by setting the property name

as name: assignAny

.

var ang = angular.module('testApp', []);

ang.controller("controller1", controller1);
function controller1($scope) {
	$scope.controller1 = "Yay, im now part of the directive!!!";
}

ang.controller("controller2", controller2);
function controller2($scope) {
	$scope.controller2 = "controller2";
}

ang.controller("controller3", controller3);
function controller3($scope) {
	$scope.controller3 = "controller3";
}

ang.directive("testDirective", function() {
	return {
		restrict: 'AE',
		link: function (scope, elem, attrs) {
      scope.controller = attrs.controller;
			console.log(scope);
		},
    template: "<h3>I return {{controller}}</h3>",
    controller: "@",
    name: "controller",
	}
});
      

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js"></script>
<div ng-app="testApp">
	<div ng-controller="controller1">
		{{controller1}}
	</div>
	<div ng-controller="controller2">
		{{controller2}}
	</div>
	<div ng-controller="controller3">
		{{controller3}}
		
		<test-directive data-controller="controller1"></test-directive>
	</div>
</div>
      

Run codeHide result


I recommend reading this guide for a well explained tutorial on how to work with directives.

Part one and part two

+1


source







All Articles