how to pass argument from directive to directive - html

I have two directive and I want to pass argument from one directive to another directive.
Sample:
Directive1:-
app.directive('myDirective1', [function () {
return {
restrict : 'E',
templateUrl : 'templates/myDirective1.html',
link : function (scope, elem, attr) {
scope.items = 'myPara';
}
}]);
Directive2:-
app.directive('myDirective2', [function () {
return {
restrict : 'E',
templateUrl : 'templates/myDirective2.html',
scope : {
items : '='
}
link : function (scope, elem, attr) {
//here i want 'myPara'
}
}]);
Html:-
<my-directive1 items="items">
<my-directive2></my-directive2>
</my-directive1>
In the above example, when i change the value of scope.items in Directive1, it should be reflect on directive2 isolated scope(items). Now i can't get the value in Directive2. Can any one help me. Thanks.

Have a service that you inject in both directives..
app.service('myService',function(){ return {myPara : undefined}})
Now add this service to your both directives and use the myPara like myService.myPara = bla
because the service is a singleton you will have the same instance in both your directives.
directive1:
app.directive('myDirective1', ['myService',function (myService) {
return {
restrict : 'E',
templateUrl : 'templates/myDirective1.html',
link : function (scope, elem, attr) {
scope.items = myService.myPara;
}
}]);
directive2
app.directive('myDirective2', ['myService',function (myService) {
return {
restrict : 'E',
templateUrl : 'templates/myDirective2.html',
scope : {
items : '='
}
link : function (scope, elem, attr) {
//here i want 'myPara'
myService.myPara // Here is your myPara
}
}]);

Related

ANGULAR: link function not being called on click in custom directive

I'm in the middle of refactoring an old project to use custom directives, and I'm already running into a problem. I'm just trying to make a simple directive and build from there. I have a logger function in my directive's link function that just runs a console.log. I'm not sure what I'm missing here, and I'm sure it's something simple. Here's my directive:
'use strict';
(function() {
angular
.module('sigFig')
.directive('myDirective', myDirective);
function myDirective(sigFigFactory) {
var directive = {
restrict: 'E',
replace: 'true',
templateUrl: 'Directives/directiveTemplate.html',
link: link,
compile: compile
};
return directive;
function link(scope, element, attrs) {
scope.logger = function() {
console.log('DING!!!');
}
}
function compile(scope, element, attrs) {
console.log('I AM A COMPILE FUNCTION');
}
}
})();
The HTML template for it is just:
<button ng-click="logger()">CLICK ME</button>
And I'm calling it in my HTML like this:
<my-directive></my-directive>
The button appears and that console.log in my compile works, but the ng-click does not. What is it I'm missing? Thanks in advance!
Add scope to directive variable: scope:{},
function myDirective(sigFigFactory) {
var directive = {
scope:{},
restrict: 'E',
replace: 'true',
templateUrl: 'Directives/directiveTemplate.html',
link: link,
compile: compile
};
return directive;
I have never created an angular application without a controller. So I'm positive that that is your issue here.
Example of your code with a controller.
html:
<body ng-app='sigFig' ng-controller='ctrl'>
<my-directive></my-directive>
</body>
js:
(function() {
angular.module('sigFig', [])
.controller('ctrl', function($scope){
$scope.itemH = 'hahaha'
})
.directive('myDirective', myDirective);
function myDirective() {
return {
restrict: 'E',
template: '<button ng-click="logger()">{{item}}</button>',
link: function link(scope, element, attrs) {
scope.item = "Logger Click Me";
scope.logger = function() {
alert('logger')
}
}
};
function compile(scope, element, attrs) {
console.log('I AM A COMPILE FUNCTION');
}
}
})();

AngularJS: Setting ng-readonly variable to true inside directive does not work

I have created a custom directive for inputs.
Inside the HTML it is used like this:
<my-input class="input-text"
type="number"
ng-model="modelVariable"
ng-readonly="false" />
Now inside the directive myInput.js I have something like this:
var myInputDirective = (function() {
directives.directive('myInput', [function() {
return {
restrict: 'E',
transclude: 'element',
replace: true,
require: 'ngModel',
templateUrl: 'app/templates/common/myInput.tpl.html',
scope: {
ngModel: '=',
ngReadonly: '='
},
link: function($scope, $element, $attr, ngModelController) {
$scope.$watch('ngModel', function(newValue, oldValue) {
if (newValue != oldValue && newValue !== undefined && newValue !== null) {
$scope.ngReadonly = isReadOnly($attr.ngModel);
}
});
However, although this sets $scope.ngReadonly to true - the field is still not readonly - I am very confused as to why not.
You have to add in the view of your directive's tempalte set ng-readonly equals to the parent scope as one of the attributes of your input element.
Just like this:
return {
//..the other properties
scope: {
ngModel: '=',
ngReadonly: '=readOnly'
}
Then in the myInput.tpl.html find your input element and add this:
<input ng-readonly="readOnly">

Dynamic ui-sref in directive template Angular Js

In my angular js Application, I have a directive inside a ng-repeat. Directive has a template in which the HTML part is loaded. Inside that template I am declaring a ui-sref Router dynamically setting states!
This does not Work!
I have tried a Fiddle
Without using a Directive ui-sref works Fine. But I need it in Directive's template.
MY HTML PART
<div ng-repeat="sp in obj.PEs">
<div draw-pe proc="{{sp.peId}}"></div>
</div>
<div style="border:1px;" ui-view="properties"></div>
My Script Part
var myApp = angular.module('myApp', ["ui.router"]);
myApp.controller("testCtrl", function($scope) {
$scope.obj = {
"PEs": {
"1": {
"peId": "1",
"peName": "Exp1",
"peDisplayName": "Exp",
"peType": "Exp",
"peCategory": "PE"
},
"2": {
"peId": "2",
"peName": "RN1",
"peDisplayName": "RNull",
"peType": "RN",
"peCategory": "PE"
}
}
}
})
myApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('Exp', {
url: '/Exp/:peId',
views: {
"properties": {
template: ".<h3>I am Exp ! </h3>",
controller: function($scope, $stateParams) {
var peId = $stateParams.peId;
alert("Peid-> " + angular.toJson($scope.obj.PEs[peId]));
}
}
}
})
.state('RN', {
url: '/RN/:peId',
views: {
"properties": {
template: "<h3> I am RN ! </h3>",
controller: function($scope, $stateParams) {
var peId = $stateParams.peId;
alert("Peid-> " + angular.toJson($scope.obj.PEs[peId]));
}
}
}
})
});
myApp.directive("drawPe", function() {
return {
restrict: "AE",
template: '<div ui-sref="{{peObj.peType}}( { peId:peObj.peId } )"> <h5>{{peObj.peDisplayName}}</h5></div>',
link: function($scope, element, attrs) {
var procId = $scope.$eval(attrs.proc);
alert(procId);
// alert(angular.toJson(scope.obj.processElements[procId]))
$scope.peObj = $scope.obj.PEs[procId];
}
}
})
See the Browser Console, on clicking the output Part!
ERROR
Error: Invalid state ref '( { peId:peObj.peId } )'
What will be the best Practice to call dynamic state names inside directives Template? I Have read some previous asked question and answer, But I am not clear with the idea as I am new to Angular Js.
Any Idea/help appreciated
Thanks
You can use $compile service to compile your directive's template when your scope changes.
Your directive could look like this:
myApp.directive("drawPe", function($compile) {
return {
restrict: "AE",
tranclude: true,
scope: {
peObj: '='
},
template: ' <h5>{{peObj.peDisplayName}}</h5>',
link: function(scope, element, attrs) {
console.log(scope.peObj);
scope.$watch(
function(scope) {
// watch the 'compile' expression for changes
//return scope.$eval(attrs.compile);
},
function(value) {
$compile(element.contents())(scope);
}
);
}
}
});
And your html:
<div ng-repeat="sp in obj.PEs">
<div draw-pe pe-obj="sp" proc="{{sp.peId}}"></div>
</div>
<div style="border:1px;" ui-view="properties"></div>
Working fiddle is here.

getting a attribute value in a directive in angular js

I have a directive
configModule.directive('iMemoryDiv',function () {
return {
restrict: 'E',
scope: {},
replace: true,
templateUrl: '/memoryDiv.html',
link: function(scope, el, attrs) {
scope.iObj = scope.$parent[attrs.bIObject];
if(angular.isDefined(scope.iObj)){
getSummary(scope.iObj);
}
function getSummary(iObj){
}
}
};
}
);
and I am calling it from html by passing an object attribute
<i-memory-div b-i-object="app"></i-memory-div> //here app is declared in a respective controller
but, here directive is getting loaded before the controller where value for 'app' is getting assigned.So scope.iObj = scope.$parent[attrs.bIObject] is always giving me undefined.
How can make directive load after the app value is getting assigned ??
Isn't it easier doing it this way:
configModule.directive('iMemoryDiv',function () {
return {
restrict: 'E',
scope: {
'bIObject': '=',
'getParentObject': '&'
},
replace: true,
templateUrl: '/memoryDiv.html',
link: function(scope, el, attrs) {
scope.$watch('bIObject', function(newValue) {
if(angular.isDefined(newValue)) {
getSummary(scope.getParentObject({name: newValue}));
}
});
function getSummary(iObj){
}
}
};
}
Or do you need more from the parent scope??
You could give your directive an isolated scope and add bIObject as a scope property:
scope: {
bIObject: '=',
},
you could then put your code in the controller: rather than link:
Use $observe service in link function,like this
if(attrs. bIObject) {
attrs.$observe('bIObject', function(value) {
console.log(value);
})
}

How to eval an attribute containing {{}}

In the following directive I'd like to eval {{selectedForApproval.length}}. This worked when it wasn't a directive, but once I put that into a directive, I'm unsure how to process the binding.
HTML: <button-large color="green" ng-click="completeWork()" label="Approve Selected ({{selectedForApproval.length}})"></button-large>
Directive:
directive('buttonLarge', function () {
return {
scope: false,
replace: true,
restrict: 'E',
template: '<button type="checkbox" class="buttonL"/>',
link: function (scope, element, attrs) {
var config = {
label: "Submit",
color: "Default"
};
angular.extend(config, attrs);
element.addClass("b"+capitalize(config.color));
element.html(scope.$parent.$eval(config.label));
//capitalize first letter of string
function capitalize(s) {
return s[0].toUpperCase() + s.slice(1);
}
}
}
})
The solution was to use transclusion...
<button-large color="green" ng-click="completeWork()">Approve Selected ({{selectedForApproval.length}})</button-large>
directive('buttonLarge', function () {
return {
scope: false,
replace: true,
restrict: 'E',
transclude: true,
template: '<button type="checkbox" class="buttonL" ng-transclude/>',
link: function (scope, element, attrs) {
var config = {
color: "Default"
};
angular.extend(config, attrs);
element.addClass("b"+capitalize(config.color));
//capitalize first letter of string
function capitalize(s) {
return s[0].toUpperCase() + s.slice(1);
}
}
}
})