I would like to pass an argument from an html directive to a controller
Example:
Directive:
angular.module('app')
.directive('helloWorld', function () {
return {
replace: false,
restrict: 'AE',
templateUrl: "./views/templates/helloWorld.html"
}
});
helloWorld.html:
<body ng-app="app" >
<div ng-controller="HelloWorldCtrl">
{{ welcome }}
</div>
hello.html:
<body ng-app="app">
<hello-world/>
</body>
HelloWorldCtrl:
angular.module('app')
.controller('HomeWorldCtrl', function ($scope, ) {
$scope.welcome = "Welcome"
};
})
Can I specify a parameter in hello.html e.g.
<hello-world param="param1"/>
That is being passed into the controller?
So in the HomeWorldCtrl I can check the value of the parameter?
Are there any better alternatives to achieve this?
Thanks,
app.directive('helloWorld', function(){
return {
restrict:'E',
scope: {
param: '#'
},
template:'<div class="param"><h2>{{param}}</h3></div>'
};
});
// you have options to choose from
//= is two-way binding
//# simply reads the value (one-way binding)
//& is used to bind functions
<hello-world="someParam"></hello-world>
// for the scope definition:
scope: {
title: '#helloWorld'
}
The usage in the template will remain the same
<hello-world param="someParam"></hello-world>
If you isn't use isolated scope (scope: {someparam: ""}), then you may use any $scope properties in the directive template without changing anything:
$scope.param = "new param value";
..
return {
..
,template: "<param>{{param}}</param>"
Thanks!
directive
return {
replace: false,
restrict: 'AE',
templateUrl: "./views/templates/PatientSearchEdit.html",
scope: {
param: '#'
}
}
controller
console.log($scope.param);
Logs indeed the value specified.
Thanks you very much!
Related
I am learning how to create custom directives.
My service looks like that:
myApp.service('myService',function(){
this.myFunction=function(myParam){
// do something
}
});
Here is my directive:
myApp.directive('myDirective',function(myService){
return {
restrict: 'E',
scope: {
param: '=myParam',
},
template: '<button ng-click="myService.myFunction(param)">Do action</button>',
}
});
In HTML, when I use <my-directive my-param="something"></my-directive> it properly renders as a button. However when I click it, myService.myFunction, doesn't get executed.
I suppose I am doing something wrong. Can someone give me a direction?
I guess this has something to do with the directive's scope.
The service wont be available directly inside the template. You'll have to use a function attached to the directive's scope and call the service function from within this function.
myApp.directive('myDirective',function(myService){
return {
restrict: 'E',
scope: {
param: '=myParam',
},
template: '<button ng-click="callService(param)">Do action</button>',
link: function(scope, element, attrs) {
scope.callService = function() {
myService.myFunction();
}
}
}
});
It doesn't work because in your example a directive doesn't actually know what is myService. You have to explicitly inject it e.g.:
myApp.directive('myDirective', ['myService', function(myService){ ... }]);
See also this question or this question.
You should use a controller to do all DOM-modifications.
See this plunkr: https://plnkr.co/edit/HbfD1EzS0av5BG6NgtIv?p=preview
.directive('myFirstDirective', [function() {
return {
'restrict': 'E',
'controller': 'MyFirstController',
'controllerAs': 'myFirstCtrl',
'template': '<h1>First directive</h1><input type="text" ng-model="myFirstCtrl.value">'
};
}
You can inject the service in the controller and then call that function inside your template:
Inject myService into controller:
myApp.controller("ctrl", function($scope, myService) {
$scope.doService = function(myParam) {
return myService.myFunction(myParam);
};
});
Call doService method of the controller inside your template:
myApp.directive('myDirective',function(){
return {
restrict: 'E',
scope: {
param: '=myParam',
},
template: '<button ng-click="doService(param)">Do action</button>',
}
});
I got a problem by passing a function to a directive ( familiar to this post: AngularJS - pass function to directive but i can´t get it working)
Here is my Code:
Directive:
.directive('testdirective', function(){
return{
restrict: 'E',
scope: {
onClick: '&'
},
controller: 'TestController',
controllerAs: 'tc',
bindToController: true,
template: '<div><button ng-click="onClick()">What UP</button></div>',
replace: true
}
})
Controller:
TestController.$inject = ["$scope"];
function TestController($scope) {
$scope.testFunction = function(){
alert("I´m the alert of the TestContoller");
};
$scope.test = 'test';
}
HTML:
<div>
<testdirective on-click="testFunction()"></testdirective>
</div>
What I want sounds very simple, I just want to pass the function to the directive and execute it with the ng-click on the button.
For me my code looks exactly like this fiddle
but mine is not working :/
Would be awesome if someone got some hints for me.
EDIT
My directive will need his own controller !
Later the function to be passed in will come from another controller !!!
The fiddle is not the same as your code.
You have set the controller of your directive to be "TestController". I assume what you wanted to do was:
.directive('testdirective', function(){
return{
restrict: 'E',
scope: {
onClick: '&'
},
template: '<div><button ng-click="onClick()">What UP</button></div>',
replace: true
}
});
and in your HTML,
<div ng-controller="TestController">
<testdirective on-click="testFunction()"></testdirective>
</div>
EDIT: Based on OP's comment
app.directive('testdirective', function(){
return{
restrict: 'E',
scope: {
onClick: '&'
},
template: '<div><button ng-click="tc.onClick()">What UP</button></div>',
replace: true,
controller: 'TestController',
controllerAs: 'tc',
bindToController: true
}
});
app.controller('TestController', function ($scope) {
console.log($scope);
}) ;
app.controller('AnotherController', function ($scope) {
$scope.testFunction = function(){
alert("I´m the alert of the TestContoller");
};
$scope.test = 'test';
});
And, your HTML
<div ng-controller="AnotherController">
<testdirective on-click="testFunction()"></testdirective>
</div>
You are telling the directive to bindToController. So within the directive's template, onClick is bound to the controller and not the scope. So, you access the onclick via the controller as tc.onClick() in the directive's template.
You may want to pass a method as a reference:
1.Pass the function as a reference and not a call:
<div>
<testdirective on-click="testFunction"></testdirective>
</div>
2.Update the directive:
.directive('testdirective', function(){
return{
restrict: 'E',
scope: {
onClick: '='
},
template: '<div><button ng-click="onClick()">What UP</button></div>',
replace: true
}
});
JSFIDDLE.
Well, in your testdirective,you defined controller TestController.
The testFunction() that you try to calling via onClick directive scope parameter is defined in controller TestController which is directive controller.
So, rather than calling via onClick you can call directly like
template: '<div><button ng-click="testFunction()">What UP</button></div>'.
Its very confusing ,you defining controller in directive and again referring it's one function via same directive's scope parameter which look like recursive.
If you want to call via directive scope parameter then you should do belowe changes.
for e.g.
JS :
<div ng-controller="TestController" ng-app="dr">
<testdirective on-click="testFunction()"></testdirective>
</div>
app.directive('testdirective', function() {
return{
restrict: 'E',
scope: {
onClick: '&'
},
template: '<div><button ng-click="onClick()">What UP</button></div>',
replace: true
}
});
Directivie:
.directive('testdirective', function(){
return{
restrict: 'E',
scope: {
onClick: '=onClick'
},
controller: 'TestController',
controllerAs: 'tc',
bindToController: true,
template: '<div><button ng-click="onClick()">What UP</button></div>',
replace: true
}
})
use '=' instead of '&' so you can fetch the html function in your directive. and you can simply pass onClick parameter through HTML
HTML:
<div>
<testdirective on-click="testFunction()"></testdirective>
</div>
I'm having an issue with injecting/inheriting a scope from a controller to a directive. Importantly, the module is not separated into its own var.
angular.module('articles').controller('ArticlesController', ['$scope, ...
]).directive('comments', ['$scope' ... //does not work!
You don't inject the scope into a directive as a dependency. Should be like this:
.directive([function() {
return {
"link": function($scope, $element, $attrs) {
//code here
}
}
}]);
The best way is to think about directives as black boxes. You provide it with some data and it updates/displays it. You can read all required info about directives here and declare directive's inputs and outputs like this:
.directive('myDirective', function() {
return {
restrict: 'E',
scope: {
myParameter: '=' //this declares directive's interface (2 way binded)
},
link: function (scope, element) {
console.log(scope.myParameter);
}
};
});
and then you can use this directive as:
<my-directive my-parameter='variable_declared_in_controller'></my-directive>
I just bypassed $scope entirely with a couple of other scopes:
.directive('comments', ['$stateParams', '$location', 'Articles',
function ( $stateParams, $location, Articles) {
if ($stateParams.articleId != null){
var article = Articles.get({
articleId: $stateParams.articleId
});
var comments = {articleId: article.articleId, created: Date.now, comment:"Hello, World!", user: "admin" };
return{
restrict: "A",
scope: true,
template: "<div></div>"
};
}
}
]);
I want to change a $scope variable from inside an isolated directive, how is this possible?
I have tried using the '#, =, &' syntax in the directive scope but cannot get it to work.
This is my simplified code
JS
app.controller('testCtrl', function($scope) {
$scope.hello = 'hello';
}
app.directive('testDirective', function() {
return {
restrict: 'E',
template: '<div>{{text}}</div>',
scope: {},
link: function(scope, element) {
scope.text = 'this is my text';
scope.hello = 'hello world!';
}
};
});
HTML
<body>
{{ hello }}
<test-directive />
</body>
This is the output i want
hello world!
this is my text
You can set a require option on the directive and specify a parent controller. This will pass the controller to your link function as the last argument:
app.directive('testDirective', function() {
return {
restrict: 'E',
template: '<div>{{text}}</div>',
require: '^testCtrl',
scope: {},
link: function(scope, element, attrs, testCtrl) {
scope.text = 'this is my text';
testCtrl.setHello('hello world!');
}
};
});
Note you have to create this testCtrl.setHello() method on your controller. This is because you get the controller itself, not its injected scope:
app.controller('testCtrl', function($scope) {
$scope.hello = 'hello';
this.setHello = function(newHello) {
$scope.hello = newHello;
}
}
Also, if you don't really care about strictly enforcing the controller dependency, you can directly access scope.$parent.$parent.hello from your directive.
In HTML, the directive must be in snake-case:
<test-directive />
In your script, the directive must be defined in camel case:
app.directive('testDirective', function() {
});
Also, add the ngController directive:
<body ng-controller="testCtrl>
</body>
Here's what was missing:
ng-controller was not defined
# means passing the attribute as a string, = means binding the property to a property from the parent's scope (which is what we need here) and & means passing in a function from the parents scope to be called later.
when the directive is called "testDirective" it looks in the HTML as follows:<test-directive></test-directive> as camel cases in JS need to be
seperated by "-" in HTML.
<body ng-controller="testCtrl">
{{ hello }}
<test-directive hello-from-parent="hello"></test-directive>
</body>
app.directive('testDirective', function() {
return {
restrict: 'E',
scope: {
hello: "=helloFromParent"
},
template: '<div>{{text}}</div>',
link: function(scope, element, attrs) {
scope.text = 'this is my text';
scope.hello = 'hello world';
}
}
});
I set up a working plnkr here
Updating as there is some confusion as to what I am asking. I would like to use a directive to inject a variable into the controller used by that directive. I realize I can use the $scope for that, but I don't find that an intuitive solution.
Essentially I want my controller to have the proposal variable injected into it.
My intended usage:
<blah-directive proposal="proposal"></blah-directive>
The directive (so far):
app.directive('blahDirective', function () {
return {
restrict: 'E'
, transclude: true
, replace: true
, scope: {
proposal: '='
}
, templateUrl: 'blahTemp.html'
, controller: blahController
};
});
blahTemp.html
<form class="form-horizontal" role="form" name="myBidForm">
**{{ proposal }}**
</form>
this is displaying the value proposal variable in the $scope fine, but it is not what I want. Essentially I would like to define my controller like:
var blahController = function($scope, SomeOtherResource, proposal) {
}
If you want to inject locals into a controller use $controller.
Here is an example (plunker):
app.directive('blahDirective', function ($controller) {
return {
restrict: 'E',
scope: {
proposal : "="
},
transclude: true,
replace: true,
templateUrl: 'blahTemp.html',
link : function (scope, elm, attrs){
scope.proposal = {};
var locals = {
$scope: scope ,
proposal: scope.proposal
};
$controller('blahController', locals);
}
};
});