Trigger a function inside a directive by watching a variable - angularjs

Assume I have the following directive:
angular.module("myModule", [])
.directive('myDirective', function ($timeout) {
return {
restrict: 'EA',
scope: {
value: '=',
valueIsValid: '='
},
link: function (scope, element, attrs) {
scope.returnValueIsValid = function() {
// return valueIsValid = true or false
};
}
}
});
invoked the following way:
<div my-directive value="value" value-is-valid="valueIsValid"></div>
The value variable is input to the directive, where the directive should return if value is valid or not in the valueIsValid variable. Is there a way to trigger the validation function by just watching valueIsValid ?

I assume valueIsValid will be true when value>0
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl',function($scope, $timeout) {
});
myApp.directive('myDirective', function ($timeout) {
return {
restrict: 'EA',
scope: {
value: '=',
valueIsValid: '='
},
link: function (scope, element, attrs) {
scope.$watch("value",function(a,b){
if(a && a != 0){
scope.valueIsValid =true;
}else{
scope.valueIsValid =false;
}
})
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<input type="number" value="0" ng-model="value"/>
<div my-directive value="value" value-is-valid="valueIsValid"></div>
value is valid:- {{valueIsValid}}
</div>

Related

Calling function of controller from directive when using isolated scope?

I want to call a function of Controller from Directive, It is for validation. But i'm a bit confused about how to call it from Directive when i'm using isolated scope. Here is the code of directive:-
App.directive('test',function(){
return{
require: "ngModel",
scope:{
a:"=",
b:"=",
c:'=',
d:'='
},
link: function(scope, element, attributes,modelVal )
{
modelVal.$validators.test= function(val)
{
return false;
//isolated scope values will make if condition true or false.
if(scope.a=="true"){
//I need to call a function of controller here. But how can
//i call that function from directive? this is my problem
}
}
scope.$watch("a", function()
{
modelVal.$validate();
});
}//end of link function;
}//end of return;
});//end of directive;
Function is in my controller, i think i don't need to write the controller code. In my html , I'm calling this directive as:
<test a="1" b="2" c="3" d="4" ng-model="abc"></test>
What changes i need to do in my directive to call the controller function which is $scope.testFunction()?
var module = angular.module('myModule', []);
module.controller('TestController', function($scope){
$scope.text = 'test';
// Will be invoked from 'test' directive
$scope.alertMe = function(text){
alert(text);
};
});
module.directive('test', function(){
return {
restrict: 'E',
template: '<input ng-model="text" ng-change="onChange(text)" />',
scope: {
text: '='
},
link: function(scope, elem, attr){
scope.onChange = function(text){
// Invoking parent controller function
scope.$parent.alertMe(text);
}
}
}
})
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="myModule" ng-controller="TestController">
<test text="text"></test>
</div>
</body>
</html>
I have given a sample, try like this.
Controller:
module.controller('TestController', function($scope){
$scope.onTextChange = function(text){
alert(text);
};
})
HTML:
<test my-func="onTextChange(text)"></test>
Directive:
module.directive('test', function(){
return {
restrict: 'E',
template: '<input ng-model="text" ng-change="onChange(text)" />',
scope: {
myFunc: '&'
},
link: function(scope, elem, attr){
scope.onChange = function(text){
if(typeof scope.myFunc === 'function'){
// Calling the parent controller function
scope.myFunc({text: text});
}
}
}
}
})

angular nested directive pass value from child

I have the following code, but I couldn't make to work, I want to pass a simple string to "parent" directive from "child" directive. Here is http://jsfiddle.net/fpax1hx7/
HTML:
<div ng-app=myApp>
<div ng-controller=MyCtrl>
<directive1></directive1>
</div>
</div>
JavaScript:
'use strict';
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', function ($scope) { }])
.directive('directive1', function () {
return {
restrict: 'E',
scope: { stringtest: '=' },
template: '<directive2 stringtest="stringTest"></directive2>',
link: function (scope, element, attrs) {
console.log(scope.stringTest);
}
}
})
.directive('directive2', function () {
return {
restrict: 'E',
scope: { stringTest: '=' },
link: function (scope, element, attrs) {
scope.stringtest="This is a Test";
}
}
}]);
There was a typo. You are using stringtest instead of stringTest and you are not passing any model to directive1
'use strict';
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', function($scope) {
console.log('from controller');
}])
.directive('directive1', function() {
return {
restrict: 'E',
scope: {
stringTest: '='
},
template: '<directive2 string-test="stringTest"></directive2>',
link: function(scope, element, attrs) {
console.log('from directive1');
console.log('string test from directive 1:' + scope.stringTest);
scope.$watch('stringTest', function(nv, ov) {
if (nv !== ov) {
console.log('string test from directive 1 after directive2 scope binded:' + scope.stringTest);
}
});
}
}
})
.directive('directive2', function() {
return {
restrict: 'E',
scope: {
stringTest: '='
},
link: {
pre: function(scope) {
scope.stringTest = "This is a Test";
},
post: function(scope, element, attrs) {
console.log('from directive2');
}
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app=myApp>
<div ng-controller=MyCtrl>
<directive1 string-test="sample"></directive1>
{{sample}}
</div>
</div>

Angular directive calling another directive not working

In this plunk I have directive dir1 calling a method in directive dir2 as described here.
The problem is that the control object (scope.dir2Ctl) is empty in dir1 and I get TypeError: scope.dir2Ctl.call2 is not a function. Any ideas how to fix this?
HTML
<body ng-app="myModule" ng-controller="ctl">
<dir1 x1="1"></dir1>
</body>
Javascript
angular.module("myModule", [])
.controller('ctl', function($scope) {})
.directive('dir1', function ($timeout) {
return {
restrict: 'EA',
scope: {
x1: '='
},
template: '<p>x2 should be 2 = {{x2}} </p>' +
'<dir2 control="dir2Ctl"></dir2>',
link: function (scope, element, attrs) {
scope.dir2Ctl = {};
$timeout(function(){
console.log(scope.dir2Ctl)
scope.x2 = scope.dir2Ctl.call2();
},1000);
}
}
})
.directive('dir2', function () {
return {
restrict: 'EA',
scope: {
control: '='
},
template: '<p>some text in dir2</p>',
link: function (scope, element, attrs) {
scope.control = scope.control || {};
scope.control.call2 = function(){
return 2;
};
}
}
});

Check if controller has passed optional function down to *child* directive

I have a scenario as follows:
Controller A >> Directive "parent" >> Directive "child"
Controller B >> Directive "parent" >> Directive "child"
Both directives have isolated scopes, and I cannot use transclusion.
Controller A defines a function that is passed down to the child directive (using the "&?" notation in both directives).
<div parent fx="doFx()"></div>
Controller B does NOT specify that function.
<div parent></div>
The parent directive simply passes down the function to the child directive.
<div child fx="doFx()"></div>
How can I check in the child directive (without accessing the parent's scope) whether or not the controller did in fact pass a function?
Thanks in advance for any pointers!
Well it is possible with third argument passed to linking function.
angular.module('app', []);
angular.module('app').controller('Example', function () {
this.fn1 = function () {
return true;
};
});
angular.module('app').directive('someDir', function () {
return {
restrict: 'E',
template: '{{isPassed}}',
scope: {
fx: '&'
},
link: function (scope, element, attrs) {
scope.isPassed = attrs['fx'] !== undefined && attrs['fx'].length > 0;
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.js"></script>
<div ng-app="app" ng-controller="Example as Ex">
A: <some-dir></some-dir> <br>
B: <some-dir fx></some-dir><br>
C: <some-dir fx="Ex.fn1"></some-dir>
</div>
edit:
You can also use specific return value.
const PASSED = 'PASSED';
angular.module('app', []);
angular.module('app').controller('Example', function() {
this.fn1 = function() {
return PASSED;
};
});
angular.module('app').directive('parent', function () {
return {
restrict: 'E',
template: '<child fx="fx()"></child>',
scope: {
fx: '&'
}
};
});
angular.module('app').directive('child', function () {
return {
restrict: 'E',
template: '{{isPassed}}',
scope: {
fx: '&'
},
link: function (scope) {
scope.isPassed = scope.fx() === PASSED;
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.js"></script>
<div ng-app="app" ng-controller="Example as Ex">
A: <parent></parent><br>
B: <parent fx="Ex.fn1()"></parent><br>
</div>
But in my opinion best solution would be to use first attrs to check if fx is passed and explicitly pass isPassed to child directive.
angular.module('app', []);
angular.module('app').controller('Example', function() {
this.fn1 = function() {};
});
angular.module('app').directive('parent', function () {
return {
restrict: 'E',
template: '<child fx="fx()" is-passed="isPassed"></child>',
scope: {
fx: '&'
},
link: function (scope, element, attrs) {
scope.isPassed = attrs['fx'] !== undefined && attrs['fx'].length > 0;
}
};
});
angular.module('app').directive('child', function ($timeout) {
return {
restrict: 'E',
template: '{{isPassed}}',
scope: {
fx: '&',
isPassed: '<'
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.js"></script>
<div ng-app="app" ng-controller="Example as Ex">
A: <parent></parent><br>
B: <parent fx="Ex.fn1()"></parent><br>
</div>

What is the scope of templates bindings in a directive without a controller

Here is a simple angular application. It shows/hides a text based on user clicking a button.
<div ng-controller="exampleController as ctrl">
<example></example>
</div>
app.controller('exampleController', function () {});
app.directive('example', function () {
return {
restrict: 'E',
template: '<p ng-show=\"showMe\">Text to show</p><button ng-click=\"clickMe()\">Click me</button>',
scope: {},
link: function (scope) {
scope.clickMe = function () {
scope.showMe = !scope.showMe;
};
}
};
});
When I remove the controller it doesn't work. Note that the directive creates an isolate scope, so my understanding is that it doesn't depend on the controllers scope.
<div>
<example></example>
</div>
app.directive('example', function () {
return {
restrict: 'E',
template: '<p ng-show=\"showMe\">Text to show</p><button ng-click=\"clickMe()\">Click me</button>',
scope: {},
link: function (scope) {
scope.clickMe = function () {
scope.showMe = !scope.showMe;
};
}
};
});
What is wrong here?
But anyways you should have ng-app
<body ng-app="demo">
<div>
<example></example>
</div>
</body>
var app = angular.module("demo", [])
app.directive('example', function () {
return {
restrict: 'E',
template: '<p ng-show=\"showMe\">Text to show</p><button ng-click=\"clickMe()\">Click me</button>',
scope: {},
link: function (scope) {
scope.clickMe = function () {
scope.showMe = !scope.showMe;
};
}
};
});
Fiddle

Resources