I have a directive which I use in multiple places, however in one of the directives I need to match a value to show certain elements. The following doesn't work for me.
<my-directive attr="my.value"></my-directive>
And within the directive
<div ng-show="attr == 'my.value'"> Hello world </div>
Directive:
'use strict';
module.exports = Directive;
function Directive(){
return {
restrict: 'E',
templateUrl: 'directive.html',
scope: {
attr: '='
}
}
}
What am I doing wrong?
Can you pls try "#" for binding the value in directive it works for me
'use strict';
module.exports = Directive;
function Directive(){
return {
restrict: 'E',
templateUrl: 'directive.html',
scope: {
attr: '#'
}
}
}
The expression you use checks if attr scope is equal to the string 'my.value'.
If you want to check if it's equal to the value of my.value you got to use it this way.
<div ng-show="attr == my.value"> Hello world </div>
You have to do something like this
https://jsfiddle.net/pdhm98s3/6/
<div ng-app="miniapp">
<div ng-controller="myController">
<my-directive attr="my.value"></my-directive>
</div>
</div>
var app = angular.module('miniapp', []);
app.directive("myDirective", function() {
return {
"restrict": "E",
"replace": true,
"scope": {
"myValue": "=attr"
},
"template": '<div ng-show="myValue"> Hello world </div>'
}
})
app.controller("myController", function($scope) {
$scope.my = {
"value": 1
}
})
Test it by changing the value to 1 and 0 in the controller
Related
I have a directive that controls a personalized multiselect. Sometimes from the main controller I'd like to clear all multiselects. I have the multiselect value filling a "filter" bidirectional variable, and I am able to remove content from there, but when doing that I also have to change some styles and other content. In other words: I have to call a method belonging to the directive from a button belonging to the controller. Is that even posible with this data structure?:
(By the way, I found other questions and examples but their directives didn't have their own scope.)
function MultiselectDirective($http, $sce) {
return {
restrict: 'E',
replace: true,
templateUrl: 'temp.html',
scope: {
filter: "=",
name: "#",
url: "#"
},
link: function(scope, element, attrs){
//do stuff
scope.function_i_need_to_call = function(){
//updates directtive template styles
}
}
}
}
The best solution and the angular way - use event.
Live example on jsfiddle.
angular.module('ExampleApp', [])
.controller('ExampleOneController', function($scope) {
$scope.raise = function(val){
$scope.$broadcast('raise.event',val);
};
})
.controller('ExampleTwoController', function($scope) {
$scope.raise = function(val){
$scope.$broadcast('raise.event',val);
};
})
.directive('simple', function() {
return {
restrict: 'A',
scope: {
},
link: function(scope) {
scope.$on('raise.event',function(event,val){
console.log('i`m from '+val);
});
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="ExampleApp">
<div ng-controller="ExampleOneController">
<h3>
ExampleOneController
</h3>
<form name="ExampleForm" id="ExampleForm">
<button ng-click="raise(1)" simple>
Raise 1
</button>
</form>
</div>
<div ng-controller="ExampleTwoController">
<h3>
ExampleTwoController
</h3>
<form name="ExampleForm" id="ExampleForm">
<button ng-click="raise(2)" simple>
Raise 2
</button>
</form>
</div>
</body>
I think better solution to link from controller to directives is this one:
// in directive
return {
scope: {
controller: "=",
},
controller: function($scope){
$scope.mode = $scope.controller.mode;
$scope.controller.function_i_need_to_call = function(){}
$scope.controller.currentState = state;
}
}
// in controller
function testCtrl($scope){
// config directive
$scope.multiselectDirectiveController = {
mode: 'test',
};
// call directive methods
$scope.multiselectDirectiveController.function_i_need_to_call();
// get directive property
$scope.multiselectDirectiveController.currentState;
}
// in template
<Multiselect-directive controller="multiselectDirectiveController"></Multiselect-directive>
I trying to make a directive which accepting an attribute and hook it to the isolated scope, but the attribute value is not showing.
angular.module('app', [])
.controller('torrentController', [function() {
this.recommended = ['...'],
this.otherArray = ['...']
}])
.directive('torrentsTable', [function() {
return {
restrict: 'E',
templateUrl: 'templates/directives/torrentsTable.html',
scope: {
index: '='
},
controller: 'torrentController as torrentCtrl'
};
}]);
The idea is to use this directive to show different list of torrents with this syntax:
<torrents-table index="recommended"></torrents-table>
<torrents-table index="someOtherIndex"></torrents-table>
I wish this 2 almost same lines to show different "list" with results.
templates/directives/torrentsTable.html
<!-- I also tried with ng-repeat="torrent in torrentCtrl.recommended" -->
<!-- And is working as I excepted (It's shows the recommended array) -->
<div layout="row" ng-repeat="torrent in torrentCtrl[index]">
<div flex>Name: {{torrent.name}}</div>
<div flex>{{index}}</div>
</div>
{{index}} is not showing, and it's value is not showing.
While I actually make hardcoded ng-repeat arguments - it repeating but {{index}} is empty.
What I am doing wrong?
Your problem: how you pass key.
You use in directive:
scope: {
index: '='
},
so you should pass to directive expression, that evaluated to $scope property. So if you not inject scope - you pass undefined.
You can fix this two ways:
1) pass string instead something else
<torrents-table index="'recommended'"></torrents-table>
<torrents-table index="'someOtherIndex'"></torrents-table>
2) change directive definition to
scope: {
index: '#'
},
sample you can see in snippet below.
angular.module('app', [])
.controller('torrentController', [function() {
this.recommended = [1,2,3,4,5];
this.someOtherIndex = ['a','b','c','d','e'];
}])
.directive('torrentsTable', [function() {
return {
restrict: 'E',
template: '<div flex>{{index}}</div>'+
'<div layout="row" ng-repeat="torrent in torrentCtrl[index]">'+
' <div flex>Name: {{torrent}}</div>'+
'</div>',
scope: {
index: '='
},
controller: 'torrentController as torrentCtrl'
};
}])
.directive('torrentsTable2', [function() {
return {
restrict: 'E',
template: '<div flex>{{index}}</div>'+
'<div layout="row" ng-repeat="torrent in torrentCtrl[index]">'+
' <div flex>Name: {{torrent}}</div>'+
'</div>',
scope: {
index: '#'
},
controller: 'torrentController as torrentCtrl'
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<div ng-app='app'>
<torrents-table index="'recommended'"></torrents-table>
<torrents-table index="'someOtherIndex'"></torrents-table>
<hr/>
<torrents-table2 index="recommended"></torrents-table2>
<torrents-table2 index="someOtherIndex"></torrents-table2>
</div>
I am wondering how to implement the scope inherit between directives.
For example:
<html ng-app="app">
<head>
<title>TEST DRAG</title>
</head>
<body ng-controller="main">
<dragcont>
<dragitem></dragitem>
</dragcont>
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script type="text/javascript">
(function(){
var app = angular.module("app", []);
app.controller("main", function($scope){
$scope.name = "Hello";
})
.directive("dragcont", function(){
return {
restrict: "AE",
scope: {
},
controller: function($scope){
$scope.name = "dragcont";
},
link: function(scope, EL, attrs){
}
}
})
.directive("dragitem", function(){
return {
restrict: "AE",
controller: function($scope){
console.log($scope.name);
},
link: function(scope, EL, attrs){
}
}
})
})()
</script>
</body>
</html>
When I run this, it always prints Hello. It seems that dragitem can inherit the scope from main controller, but what if I want it to inherit from dragcont?
Isolate scope is used to "isolate" the inner workings of a directive from its usage. As such, the scope neither inherits from its parent, nor can be inherited from by the child directives and expressions.
So, for the isolate foo directive:
.directive("foo", function(){
return {
scope: {},
link: function(scope){
scope.inner = "hidden from outside";
}
}
})
the child directives and expression will not inherit its isolate scope.
<foo>
<span>{{inner}} will be undefined</span>
</foo>
Using a template:
On the other hand, a template of a directive foo is known to the author of the directive, and so it does use the isolate scope. The following would have worked, if foo had a template:
scope: {},
template: '<span>{{inner}}</span>',
link: function(scope){
scope.inner = "hidden from outside";
}
Using manual "transclusion":
Occasionally, it makes sense to allow the user of the directive to specify a custom template. The author of the directive may also want to expose special "magic" variables to use in the custom template, not unlike $index, $first, etc.. of ng-repeat.
This can be done with a manual transclusion:
scope: {},
transclude: true,
template: '<div>{{header}}</div>\
<placeholder></placeholder>',
link: function(scope, element, attrs, ctrls, transclude){
scope.header = "I am foo"; // still only visible in the template
// create a new scope, that inherits from parent, but a child of isolate scope
var anotherScope = scope.$parent.$new(false, scope);
anotherScope.$magic = "magic";
// transclude/link against anotherScope
transclude(anotherScope, function(clonedContents){
element.find("placeholder").replaceWith(clonedContents);
}
}
Now, you can have access to $magic variable inside the transcluded contents and to the outer scope (assuming it has $scope.name = "John")
<foo>
<div>I can see {{name}} and {{$magic}}</div>
</foo>
The resulting DOM will be:
<foo>
<div>I am foo</div>
<div>I can see John and magic</div>
</foo>
It looks like you are still missing some work to be able to make a directive inherit from another.
I think this code will help you:
http://codepen.io/anon/pen/EaPNqp?editors=101
Also, you might want to read:
http://david-barreto.com/directive-inheritance-in-angularjs/
CODE:
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
$scope.data1 = "1";
$scope.data2 = "2";
})​var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
$scope.data1 = "1";
$scope.data2 = "2";
})
.directive('myWrapper', function() {
return {
restrict: 'E'
, transclude: true
, scope: true
, template: '<h1>{{ title }}</h1><ng-transclude></ng- transclude><h2>Finished wrapping</h2>'
, controller: function($scope, $element, $attrs){
$scope.title = $attrs.title;
$scope.passdown = $attrs.passdown;
}
};
})
.directive('myInner1', function() {
return {
restrict: 'E'
, require: 'myWrapper'
, template: 'The data passed down to me is {{ passdown }}'
};
})
.directive('myInner2', function() {
return {
restrict: 'E'
, require: 'myWrapper'
, template: 'The data passed down to me is {{ passdown }}'
};
});
.directive('myWrapper', function() {
return {
restrict: 'E'
, transclude: true
, scope: true
, template: '<h1>{{ title }}</h1><ng-transclude></ng- transclude><h2>Finished wrapping</h2>'
, controller: function($scope, $element, $attrs){
$scope.title = $attrs.title;
$scope.passdown = $attrs.passdown;
}
};
})
.directive('myInner1', function() {
return {
restrict: 'E'
, require: 'myWrapper'
, template: 'The data passed down to me is {{ passdown }}'
};
})
.directive('myInner2', function() {
return {
restrict: 'E'
, require: 'myWrapper'
, template: 'The data passed down to me is {{ passdown }}'
};
});
which is found very useful. Make sure you read the comments below the article as well.
Pay attention to the "require" property.
Regards.
i read Angularjs documentation .thereare examples for defining directives without passing a value.for example:
angular.module('docsTemplateUrlDirective', [])
.controller('Controller', ['$scope', function($scope) {
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
}])
.directive('myCustomer', function() {
return {
templateUrl: 'my-customer.html'
};
});
and HTML is
<div ng-controller="Controller">
<div my-customer></div>
</div>
but i want to create a directive like ng-model in which an attribute get passed.for example
<div ng-controller="Controller">
<div my-customer="Hello"></div>
</div>
i want to retrieve this hello in my directive definition link function.How to achieve that ??
You can pass as many as attributes and can access them directly using third argument in link function. Here you go:
.directive('myCustomer', function() {
return {
templateUrl: 'my-customer.html',
link: function(scope, element, attr) {
console.log('Attribute:', attr.myCustomer, attr.otherData);
}
};
});
<div my-customer="hello" other-data="foo"></div>
Just scroll a lil more in docs (Angular Directives) where you got above code, you will get how to get your answer attr of directive
.directive('myCustomer', function() {
return {
templateUrl: function(elem, attr){
...
//attr will be having the value
return attr;
}
};
If you want to use isolated scope, then you can do this:
.directive('myCustomer', function() {
return {
scope: {
myCustomer : '=' //If expected value is an object use '='. If it is just text, use '#'
}
templateUrl: 'my-customer.html',
link: function(scope, ele, attr){
console.log(scope.myCustomer);
}
};
});
If you don't want to use isolated scope, then
.directive('myCustomer', function($parse) {
return {
templateUrl: 'my-customer.html',
scope: true,
link: function(scope, ele, attr){
// if expected value is object
var hello = $parse(attr.myCustomer)(scope);
// if expected value is just text
var hello = attr.myCustomer;
}
};
});
I have a directive, form where the rest of the html is given. The directive is given below
THis is the html for directive
<div test
input="{{guage.input}}"
>
</div>
angular.module('test', [])
.directive('test', function () {
"use strict";
return {
restrict: 'A',
scope: {
input: '='
},
templateUrl: 'gauge/gauge.tpl.html',
replace: true
});
The below is the html loaded after the directive compilation.
<div ng-controller="Testing">
<div>
<div id="{{guageid}}" class="gauge ng-isolate-scope" ng-model="gauge.input" data-service="/api/getDataResult/core-mon-status" guageid="fleet_online" description="Fraction of fleet online" unit="%" test="{{gauge.test}}" input="{{gauge.input}}" gauge="">
</div>
</div>
</div>
Now I have a parent controller above this dom element name is Testing.
From my controller if I change the {{guage.input}} its not displaying.
This is my controller
app.controller('Testing',['$scope','newdataLoad','$timeout',function($scope, newdataLoad, $timeout){
$scope.gauge = {};
$scope.gauge.input = 0;
});
What is the problem with my scope here.
As your scope defines the input with = you dont need the expression brackets.
<div test input="guage.input">
Using expression brackets will break the 2-way binding.
Optimization:
You can completely move you controller into the directive and still make use of the dependency injection
"use strict";
angular.module('test', []).directive('test', function () {
return {
restrict: 'A',
scope: {
input: '='
},
templateUrl: 'gauge/gauge.tpl.html',
replace: true,
controller: function($scope, newdataLoad, $timeout){
$scope.gauge = {};
$scope.gauge.input = 0;
}
}
});
The template code then :
<div>
<div id="{{guageid}}" class="gauge ng-isolate-scope" ng-model="gauge.input" data-service="/api/getDataResult/core-mon-status" guageid="fleet_online" description="Fraction of fleet online" unit="%" test="{{gauge.test}}" input="{{gauge.input}}" gauge="">
</div>
</div>
Remove curlies:
<div test input="guage.input">
</div>