I'm writing a custom <pagination>
directive, which will return elements responsible for changing the current page and pagination settings (e.g. how many items will be displayed per page). The directive has isolated scope (to make it more reusable).
Inside the directive template I need to call functions like changePage()
or changePaginationSettings()
. The only way to pass a function inside the isolated scope I've found so far is define the function in the controller.
mainController.js
module.controller("mainController", function($scope) {
$scope.changePage = function() { ... };
});
and then pass it to directive as an attribute:
pagination.js
module.directive("pagination", function() {
return {
restrict: "E",
scope: {
changePage: "="
},
templateUrl: "templates/pagination.html"
}
}
pagination.html
<pagination change-page="changePage">
This looks very ugly to me, because it's splitting related code into 2 unrelated files. That is changePage()
function should be defined in the pagination.js file, not in mainController.js.
I'd think something like that should be possible:
pagination.js
module.directive("pagination", function() {
function changePage() { ... };
return {
restrict: "E",
scope: {
changePage: changePage
},
templateUrl: "templates/pagination.html"
}
}
But such code is producing a (meaningless to me) error: Error: definition.match is not a function
.
Is there a way to achieve that? I mean to pass a function defined in the same file inside an isolated scope of directive.
I've read AngularJS Directive Docs but they don't even list what are legal values in scope
object of a directive, only give some "=", "&" and "@" examples.
These prefixes are used to bind the parent scope's methods and properties to the directive scope. There are 3 types of prefixes in AngularJS: '@' – Text binding / one-way binding. '=' – Direct model binding / two-way binding.
Isolated scope directive is a scope that does not inherit from the parent and exist on its own. Scenario: Lets create a very simple directive which will show the object from the parent controller.
First thing first, to wire up and call a function in the parent scope from the isolated scope, you use the “&” symbol in the directive property definition.
Shared scope: directive and controllers share the scope and the data. We cannot pass data explicitly to the directive. 2. Inherited scope: directive inherits the scope of the controller.
The only legal values for an isolated scope object definition are strings which begin with &
, @
, or =
. (You can also follow these symbols with the name of the property on the parent scope should you want the property name to differ within the directive.1) In this instance you want to use the =
symbol as this indicates that Angular should "bind changePage
on the directive scope to changePage
on the parent scope". Take a look at this answer for more details.
You're right that it is ugly having to pass this function in via an attribute on the directive, however this is the nature of having an isolated scope. You might consider having the changePage
and other related methods in a service, as you can then inject this as a dependency.
Edit
Without an isolate scope you could do the following:
module.directive("pagination", function() {
return {
restrict: "E",
templateUrl: "templates/pagination.html",
link: function(scope, elem, attrs) {
// scope.changePage is available from the directive's parent $scope
}
}
}
1 Example: { 'nameInDirective': '=nameOnParent' }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With