Angular directive dont works inside a 'controller as' - angularjs

I have a single controller
module.controller('MyCtrl', function() {
this.message = 'Hello';
this.method = function() {
return this.message;
};
});
module.directive('MyDirective', function() {
return {
restrict: 'A',
scope: {
argument: '=',
method: '&'
},
link: function(scope, el, attrs) {
console.log(scope.argument); //undefined!
scope.method(); // undefined
}
};
});
the template
<div data-ng-controller="MyCtrl as ctrl">
<p data-ng-bind="ctrl.message"></p> <!-- Works! -->
<p data-ng-bind="ctrl.method()"></p> <!-- Works too! -->
<div data-my-directive data-method="ctrl.method" data-argument="ctrl.message">
</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});
}
}
}
}
})

Trigger a function inside a directive by watching a variable

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>

Send data from controller to directive

I want to send that to my directive but I want that data to stay updated if the data in the controller changes.
// Controller
angular
.module('app')
.controller('IndexController', IndexController)
IndexController.$inject = [];
function IndexController() {
var vm = this;
vm.name = 'John';
newName = function() {
vm.name = 'Brian';
}
newName();
}
// Directive
angular
.module('app')
.directive('userName', userName);
userName.$inject = ['$document'];
function userName($document) {
var directive = {
restrict: 'EA',
template: '<div id="user"></div>',
replace: true,
scope: {
name: '='
},
link: function(scope, elem, attrs) {
console.log(scope.data);
}
}
return directive;
}
this is how I use the directive. the problem is that it always returns the first name and not the new name after the change in the controller.
<div ng-controller="indexController">
<user-name name="indexController.name">
</div>
thank you.
Try this, you just have to inject $scope into your Indexcontroller
angular
.module('app', [])
.controller('IndexController', function($scope) {
var vm = this;
vm.name = 'John';
vm.newName = function() {
vm.name = 'Brian';
console.log(vm.name);
}
//vm.newName();
})
.directive('userName', ['$document', function() {
var directive = {
restrict: 'E',
template: '<div id="user"></div>',
replace: true,
scope: {
name: '='
},
link: function(scope, elem, attrs) {
console.log(scope.name);
}
}
return directive;
}])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="IndexController as vm">
<user-name name="vm.name"></user-name>
<button ng-click="vm.newName()">Click</button>
</div>
Without using as in controller, you cannot use controller.prop inside the scope.
Inside the controlleryou need to call the method using its $scope or this.
Check the below code.
angular
.module('app', [])
.controller('IndexController', function($scope) {
$scope.name = 'John';
$scope.newName = function() {
$scope.name = 'Brian';
}
$scope.newName();
})
.directive('userName', ['$document', function() {
var directive = {
restrict: 'E',
template: '<div id="user"></div>',
replace: true,
scope: {
name: '='
},
link: function(scope, elem, attrs) {
console.log(scope.name);
}
}
return directive;
}])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="IndexController">
<user-name name="name"></user-name>
</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

angularJS: watch async data in directive

I'm trying to watch a async data in my directive, here is my JS code:
(function(angular) {
var myApp = angular.module('testTree', []);
myApp.config(function($httpProvider) {
$httpProvider.defaults.headers.get = {};
$httpProvider.defaults.headers.get["Content-Type"] = "application/json";
});
myApp.factory('DataService', function($http) {
return { getData: function(prmParentId, prmParentSrc) {
var data = $.param({ 'parentId': prmParentId, 'parentSrc': prmParentSrc });
return $http.get("Temp.aspx/GetData", { params: { parentId: prmParentId, parentSrc: prmParentSrc }, data: '' }).
success(function(result) {
return result.d;
});
}
}
});
myApp.controller('myController', myController);
function myController($scope, DataService) {
$scope.treeNodes = [];
$scope.init = function() {
DataService.getData(0, 0).then(function(promise) {
$scope.treeNodes = promise.data.d;
});
}
$scope.focusNode = function() {
console.log("kuku2");
}
}
myApp.directive('nodes', function() {
return {
restrict: "E",
replace: true,
scope: {
nodes: '=',
clickFn: '&'
},
template: "<ul><node ng-repeat='node in nodes' node='node' click-fn='clickFn()'></node></ul>",
link: function(scope, element, attrs) {
scope.$watch('treeNodes', function(newVal, oldVal) {
console.log(scope.treeNodes);
}, true);
}
}
});
myApp.directive('node', function($compile) {
return {
restrict: "E",
replace: true,
scope: {
node: '=',
clickFn: '&'
},
template: "<li><span ng-click='clickFn()(node)'>{{node.ObjectName}}</span></li>",
link: function(scope, element, attrs) {
if (angular.isArray(scope.node.Children)) {
element.append("<nodes nodes='node.Children' click-fn='clickFn()'></nodes>");
$compile('<nodes nodes="node.Children" click-fn="clickFn()"></nodes>')(scope, function(cloned, scope) {
element.append(cloned);
});
}
}
}
});
})(angular);
And this is my HTML:
<div ng-app="testTree">
<div ng-controller="myController">
<div ng-init="init()">
<nodes node="treeNodes" click-fn="focusNode"></nodes>
</div>
</div>
</div>
The console in the directive's watch is always "undefined". What am I doing wrong here?
thanks.
Pass treeNodes as nodes in your directive. So you need to watch nodes.
scope.$watch('nodes', function(newVal, oldVal) {
console.log($scope.nodes);
}, true);
<div ng-app="testTree">
<div ng-controller="myController">
<div ng-init="init()">
<nodes nodes="treeNodes" click-fn="focusNode"></nodes>
</div>
</div>
</div>

Resources