angularJS attribute based directive - pass isolated scope - angularjs

I have written directives before that have an isolated scope but they are element directives
If i write a directive that is attribute based, how can i pass the isolated scope to it?
Thanks

You can do this in exactly the same way as you did with element directive, i.e. attach further attributes that pass in the properties to the isolated scope.
HTML:
<div greeting-directive my-greeting="'hello'" greet-who="'world'"></div>
JS:
angular.module("myApp").directive("greetingDirective", function(){
return {
restrict: 'A',
scope: {
myGreeting: "=",
greetWho : "="
},
template: '<p>{{ myGreeting }}, {{ greetWho }}</p>'
}
});
Sample Plunk

It is very similar to isolate scope for Element directives. Consider this example:
myApp.directive('test', function () {
return {
restrict: 'A',
scope: {test: '='},
link: function (scope, element) {
scope.$watch('test', function () {
console.log(scope.test)
});
}
};
});
I'm using the direcitve name as a scope variable.
<div test="ctrl.val">some stuff</div>
However if I didn't want to leverage the directive name like this:
myApp.directive('notTest', function () {
return {
restrict: 'A',
scope: {test: '='},
link: function (scope, element) {
scope.$watch('test', function () {
console.log(scope.test)
});
}
};
});
Then html might look like this:
<div not-test test="ctrl.val">some stuff</div>

Related

Get directions childs tags AngularJS

i made this directive that i call in my html like
<my-datepicker />
what i want to do now, is to expend it, so that i can do something like this
<my-datepicker >
<my-day>{{date}}</my-day>
<my-month>{{moth}}</my-month>
<my-year>{{year}}</my-year>
</my-datepicker>
resulting in my-datepicker directive can get the child elements.
how can you do this? do you need to make the childs like standanlone directive, an how can you get the value from them in the parent(my-datepicker) directive
You can access parent directive controller like this:
app.directive('myDay', function () {
return {
restrict: 'E',
require: '^myDatepicker',
link: function (scope, element, attrs, parentCtrl) {
parentCtrl.doSomething();
}
};
});
In parent:
app.directive('myDatepicker', function () {
return {
restrict: 'E',
controller: function () {
this.doSomething = function () {
alert('Do something in parent');
};
}
};
});
I think the best way to extend your directive is by passing parameters (date month ec... ) as attributes.
Your html should be somethig like this
<my-datepicker day="day" month="month" year="year"/>
Inside your directive you should be able to retrieve those variables by declaring them in the scope.
function myDatepicker() {
var directive = {
templateUrl: 'yourtemplate.html',
restrict: 'E',
link: link,
scope: {
date: '=',
month: '=',
year: '='
}
}
return directive;
function link(scope, element, attrs) {
// use here scope.date scope.month and scope.year
}
};

How to bind content of tag into into directive's scope?

Say I have a directive like such:
<my-directive>This is my entry!</my-directive>
How can I bind the content of the element into my directive's scope?
myApp.directive('myDirective', function () {
return {
scope : {
entry : "" //what goes here to bind "This is my entry" to scope.entry?
},
restrict: "E",
template: "<textarea>{{entry}}</textarea>"
link: function (scope, elm, attr) {
}
};
});
I think there's much simpler solution to the ones already given. As far as I understand, you want to bind contents of an element to scope during initialization of directive.
Given this html:
<textarea bind-content ng-model="entry">This is my entry!</textarea>
Define bind-content as follows:
directive('bindContent', function() {
return {
require: 'ngModel',
link: function ($scope, $element, $attrs, ngModelCtrl) {
ngModelCtrl.$setViewValue($element.text());
}
}
})
Here's a demo.
I may have found a solution. It relies on the transclude function of directives. It works, but I need to better understand transclusion before being sure this is the right way.
myApp.directive('myDirective', function() {
return {
scope: {
},
restrict: 'E',
replace: false,
template: '<form>' +
'<textarea ng-model="entry"></textarea>' +
'<button ng-click="submit()">Submit</button>' +
'</form>',
transclude : true,
compile : function(element,attr,transclude){
return function (scope, iElement, iAttrs) {
transclude(scope, function(originalElement){
scope.entry = originalElement.text(); // this is where you have reference to the original element.
});
scope.submit = function(){
console.log('update entry');
}
}
}
};
});
You will want to add a template config to your directive.
myApp.directive('myDirective', function () {
return {
scope : {
entry : "=" //what goes here to bind "This is my entry" to scope.entry?
},
template: "<div>{{ entry }}</div>", //**YOU DIDN'T HAVE A TEMPLATE**
restrict: "E",
link: function (scope, elm, attr) {
//You don't need to do anything here yet
}
};
});
myApp.controller('fooController', function($scope){
$scope.foo = "BLAH BLAH BLAH!";
});
And then use your directive like this:
<div ng-controller="fooController">
<!-- sets directive "entry" to "foo" from parent scope-->
<my-directive entry="foo"></my-directive>
</div>
And angular will turn that into:
<div>THIS IS MY ENTRY</div>
Assuming that you have angular setup correctly and are including this JS file onto your page.
EDIT
It sounds like you want to do something like the following:
<my-directive="foo"></my-directive>
This isn't possible with ELEMENT directives. It is, however, with attribute directives. Check the following.
myApp.directive('myDirective', function () {
return {
template: "<div>{{ entry }}</div>", //**YOU DIDN'T HAVE A TEMPLATE**
restrict: "A",
scope : {
entry : "=myDirective" //what goes here to bind "This is my entry" to scope.entry?
},
link: function (scope, elm, attr) {
//You don't need to do anything here yet
}
};
});
Then use it like this:
<div my-directive="foo"></div>
This will alias the value passed to my-directive onto a scope variable called entry. Unfortunately, there is no way to do this with an element-restricted directive. What is preventing it from happening isn't Angular, it is the html5 guidelines that make what you are wanting to do impossible. You will have to use an attribute directive instead of an element directive.

how to pass variable from controller to directive using click event in angularjs

i am using directive concept in angularjs to pass data varible from controller to directive.i am writing one html page and controller,directive in angularjs.
test.html:
<div ng-controller="myController"
data-angular-treeview="true"
data-tree-model="roleList"
data-node-id="roleId"
data-tree-id="mytree"
data-node-label="roleName"
data-node-children="children"
data-ng-click="selectNode(currentNode)"
>
</div>
testcontroller.js:
(function(){
app.controller('myController', function($scope,$http,TreeService){
$scope.selectNode=function(val)
{
$scope.nodeval=val.roleName;
alert("select:"+$scope.nodeval);
};
});
})();
testdirective.js:
app.directive('tree1', function($rootScope) {
function compile(scope, element, attributes) {
return {
post:function(scope, iElement, iAttrs) {
iElement.bind('click', function() {
alert("click: "+scope.node);
});
}
};
}
return {
compile: compile,
scope: {
},
restrict: 'AE',
};
});
here i am getting selected node name in testcontroller.js but i want to pass that nodename in my directive so please suggest me how to this.
Thanks
What i would do is define inside the directive isolated scope an attribute like this:
scope: {
node: '='
}
And inside the view controller have a node initialized as $scope.node = {}; and with the click event change the value of the local $scope.node to the node you are interested in, and as the directive recieved the reference to the $scope.node attribute inside the view controller, it would automatically update itself
<div test-directive node-value="node"></div>
isolate scope directive:
directive('testDirective', function(){
return {
restrict: 'EA',
scope: {
nodeValue: '='
},
link: function(scope, element, attrs){
console.log(scope.nodeValue);
}
}
Access controller scope:
directive('testDirective', function(){
return {
restrict: 'EA',
link: function(scope, element, attrs){
console.log(scope.$eval(attrs['nodeValue']));
}
}

How can I get my directive to access the controllers scope

I have a setup like this:
<controller>
<directive>
in my controller that has a function that returns an html string. How can I get my directive to render this by accessing the controllers scope?
Or maybe I should just put the controller in the directive?
app.controller('controller', ['$scope', 'DataService', function ($scope, DataService) {
$scope.parseJson = function () {
//returns the html
};
}]);
directive
app.directive('Output', function () {
return {
restrict: 'A',
replace: true,
template: '<need html from controller>',
link: function(scope, element, attr) {
//render
//scope.parseJson();
}
};
});
You should use the isolated scope: '&' option
app.directive('output', ['$sce', function ($sce) {
return {
restrict: 'A',
replace: true,
template: "<div ng-bind-html='parsed'></div>",
scope:{
output: "&"
},
link: function(scope){
scope.parsed = $sce.trustAsHtml(scope.output());
}
};
}]);
Template:
<div output="parseJson()"></div>
The directive and the controller should be sharing the scope already. Don't bother using a template for the directive, just get the HTML string in you linking function (you already have the method call in there) and modify the element directly using element.html(). Take a look at the element docs for more info.
app.directive('Output', function ($compile) {
return {
restrict: 'A',
link: function(scope, element, attr) {
var templateString = scope.parseJson();
var compiledTemplate = $compile(templateString)(scope);
compiledTemplate.appendTo("TheElementYouWishtoAppendYourDirectiveTo");
}
};
});

Passing variable to Angular Directive

If I have a directive myDir and I call it within ng-repeat like so
<my-dir myindex="{{$index}}"></my-dir>
How can I access myindex? I get actual string {{$index}} when I use attrs.myindex within postLink function. When I inspect html, it actually says myindex="2".
Try
<my-dir myindex="$index"></my-dir>
Then
app.directive('myDir', function () {
return {
restrict: 'E',
scope: {
myindex: '='
},
template:'<div>{{myindex}}</div>',
link: function(scope, element, attrs){
scope.myindex = attrs.myindex;
console.log('test', scope.myindex)
}
};
})
Demo: Plunker

Resources