AngularJS $rootScope.$emit not Firing the Method - javascript

I want to fire a directive based on demand using a service. Below is the directive code.
var app = angular.module('MyModule').service('DOMService', ['$rootScope', function ($rootScope) {
this.Manipulate = function () {
$rootScope.$emit('manipulateDOM');
};
}]).directive('domDirective', ['$rootScope', function ($rootScope) {
return {
restrict: 'EA',
replace: 'false',
scope: true,
link: function (scope, elm, attrs) {
$rootScope.$on("manipulateDOM", function () {
alert("Entered......");
// element.find('#DirectiveLable').css('background-color', 'red')
// element.find('#DirectiveLable').css('height', '100')
});
},
};
}]);
My HTML like below
<div id="example">
<div id="grid"></div>
<dom-directive>
<label id="DirectiveLable">Click Here</label>
</dom-directive>
</div>
I am calling the service like below inside my Angular Controller
angular.module('MyModule').controller('CitizenRelationAccordionController', ['$scope', '$q', '$attrs', 'DOMService',
function ($scope, $q, $attrs, DOMService) {
DOMService.Manipulate();
}
]);
Issue is that eventhough DOMService is firing, it's not invoking the directive method where alert has written

I think that you missed the [] in the module declaration: here is a working example from what you wrote.
Hope this could help,
Dario

Related

$watch on array in service not working in directive

I am trying to watch when an array in a service is updated. I update this array in the service using a function in a directive based controller. Now for some reason the watch function does not get called in the link function of the second directive. Why is watch not being called in the second directive. I am trying to update the scope of a variable in the second directive so that it updates when the first directive function updates the service.
The Service
var productServices = angular.module('productServices', ['ngResource']);
productServices.factory('PlayerListS', [function() {
var playerList = [];
function getList() {
console.log(playerList);
return playerList;
}
function addToList(name) {
playerList.push(name);
}
return {
addToList :addToList,
getList: getList
}
}]);
The Directives
'use strict';
bands.directive("player",['PlayerListS', function (PlayerlistS) {
return {
restrict: 'E',
scope: {
person:'#person',
add:'&add'
},
replace: false,
templateUrl: "partials/player.html",
controller: function($scope, $element, $compile) {
$scope.playerList = ["A", "B"];
$scope.add = function(name) {
PlayerlistS.addToList(name);
PlayerlistS.getList();
}
},
link: function(scope, el, attrs) {
}
};
}]);
bands.directive("playerList", ['PlayerListS', function (PlayerlistS) {
return {
restrict: 'E',
replace: false,
template: "<p>Test</p>",
controller: function($scope, $element, $compile) {
},
link: function($scope, $el,$attrs) {
console.log('added');
var x = PlayerlistS.getList()
/*THIS IS WHERE THE WATCH IS HAPPENING*/
$scope.$watch('x', function (newVal, oldVal) {
console.log("CHANGED");
}, true);
}
};
}]);
The Controller
var bands = angular.module('bands', []);
bands.controller('ViewHousesCtrl', ['$scope', '$element', '$routeParams', '$q',
function ViewHousesCtrl($scope, $element, $routeParams, $q) {
$scope.playerLis = ["A","B","C"];
}]);
HTML
<player ng-show="true" person="RandomName" add="add()"></player>
<player-list ng-show="true" ng-repeat="a in playerLis"></player-list>
What your watcher is really doing, is trying to watch a variable called x on the directive scope. But your variable x is just a regular local variable, so your watcher doesn't trigger. So what your watcher basically translates to is this:
$scope.$watch(function(scope){
return scope['x'];
}, function (newVal, oldVal) {
console.log("CHANGED");
}, true);
You can probably see why it doesn't trigger. There is no variable $scope.x. Instead you should try watching the service directly, by specifying the watch function. Like this:
$scope.$watch(function(){
return PlayerlistS.getList();
}, function (newVal, oldVal) {
console.log("CHANGED");
}, true);
You have a spelling mistake in your HTML, it should be:
<player-list ng-show="true" ng-repeat="a in playerList"></player-list>

$scope.$apply() not calling function

I have a need for a custom click directive, which executes the passed code using scope.$apply().
$(elem).on('click', function(){
scope.$apply(attrs.wdClick);
});
This works fine if I pass something like wd-click="something = !something". But when I try to call a $rootScope function it does not work, however it does work when using the default ng-click.
wd-click="$root.someFunction()" //this does not call the function but ng-click does
I have tried updating the directive to make it work
$(elem).on('click', function(){
$rootScope.$apply(attrs.wdClick);
});
But this does not work either. Any ideas?
attrs.wdClick is a string, so passing it to $apply won't do anything. To call the function you can pass the string to $eval
scope.$apply(function() {
scope.$eval(attrs.wdClick)
});
You should wrap your code in function(){}
scope.$apply(function(){
attrs.wdClick() // this is some sunction I suppose
});
Would you want to call your rootscope method in an another controller? If I understand correctly, try to use this way :
angular.module('app', [])
.controller('Ctrl', function Ctrl1($scope, $rootScope) {
$rootScope.blah = 'Hello';
$scope.yah = 'World'
})
.directive('myTemplate', function() {
return {
restrict: 'E',
templateUrl: 'my-template.html',
scope: {},
controller: ["$scope", "$rootScope", function($scope, $rootScope) {
console.log($rootScope.blah);
console.log($scope.yah);
$scope.test = function(arg) {
console.log(arg);
}
}]
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="Ctrl">
<my-template></my-template>
</div>
<!-- my-template.html -->
<script type="text/ng-template" id="my-template.html">
<label ng-click="test($root.blah)">Click</label>
</script>
</div>
Also you can try on jsfiddle,
http://jsfiddle.net/mg74b/24/
Is there a reason you are trying to use attrs instead of a scope property? Also, you should use $timeout instead of $apply.
angular
.module('app', [])
.directive('myDirective', myDirective);
myDirective.$inject = ['$timeout'];
function myDirective($timeout) {
return {
restrict: 'E',
templateUrl: 'my-template.html',
scope: {
wdClick: '='
},
link: linkFn
};
function linkFn(scope, element) {
element.on('click', function () {
$timeout(scope.wdClick);
});
}
}

AngularJs, add directive attribute to scope without isolation

I created a directive which uses parent scope.
The directive should accept a attribute i.e
<my-nice-new-directive data-hide-icon="true" />
but I do not want to isolate scope. Is it possible to just add the attribute to the $scope?
Consider having fun with the $parse service.
.directive('myNiceNewDirective', function () {
return {
restrict: 'AE',
controller: function ($scope, $attrs, $parse) {
var hideIcon = $parse($attrs.hideIcon)($scope);
}
};
})
or you could just evaluate the variable data-hide-icon="{{isIconHidden}}", in which case you may want to watch it.
.directive('myNiceNewDirective', function () {
return {
restrict: 'AE',
scope: true, //this is not necessary but could be useful
controller: function ($scope, $attrs) {
$scope.$watch(function () {return $attrs.hideIcon;}, function (newValue, oldValue) {
//react to change...
});
}
};
})

Creating a custom attribute with AngularJS

I'm new to AngularJS. I'm trying to write a directive that will set the background-color of a <div> based on some scenario. Essentially, in my view, I want to be able to write this code:
<div effect-color="#2D2F2A">content here</div>
or
<div effect-color="{{effectColor}}">content here</div>
I know I need a directive. Currently, I'm doing this:
.directive('effectColor', [
function () {
return {
restrict: 'A',
controller: [
'$scope', '$element', '$attrs', '$location',
function ($scope, $element, $attrs, $location) {
// how do I get the value of effect-color here?
}
]
}
}
]);
I'm not sure how to get the value of the attribute itself. Do I need to add a scope? I just want the attribute value.
Thank you!
Here are two methods... First gets the attribute value through looking at the elements attribute value of your directive. The second gets passed the attribute value and attached to the isolated scope of your directive. Please note I have replaced your controller with a linking function. I suggest you give this article a read: https://docs.angularjs.org/guide/directive
Codepen: http://codepen.io/anon/pen/cGEex
HTML:
<div ng-app="myApp">
<div effect-color-one="#123456"></div>
<div effect-color-two="#123456"></div>
</div>
JavaScript:
angular.module('myApp', [])
.directive('effectColorOne', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
console.log('example 1: ' + attrs.effectColorOne);
}
}
}
)
.directive('effectColorTwo', function () {
return {
restrict: 'A',
scope: {
effectColorTwo: '#'
},
link:function (scope) {
console.log('example 2: ' + scope.effectColorTwo);
}
}
}
);
Another example
combining the above example and the ability to change the background colour of the element which the directive attribute resides is below:
Codepen: http://codepen.io/anon/pen/HospA
HTML:
<div ng-app="myApp">
<div effect-color="red">Hello</div>
</div>
JavaScript:
angular.module('myApp', [])
.directive('effectColor', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.css('background-color', attrs.effectColor);
}
}
}
);
You can get the value in your directive controller using $attrs parameter object
$attrs.effectColor // #2D2F2A
From the docs:
attrs is a hash object with key-value pairs of normalized attribute
names and their corresponding attribute values.
Also if you are going to modify the DOM (in your case applying background color) you should use link option.
DEMO
Seems like a duplicate of How to get attribute value of a custom tag in angularjs?
I think you need something like scope: { data: "=data" } in the definition of your directive
Please see here :http://jsfiddle.net/MP8ch/
<div ng-app="app">
<div ng-controller="firstCtrl">
<div effect-color="#fc9696">
<P>content here</P>
</div>
</div>
</div>
JS:
var app = angular.module('app', []);
app.directive('effectColor', function () {
return {
restrict: 'AE',
transclude: true,
// replace:'true',
scope: {
color: '#effectColor'
},
restrict: 'AE',
template: '<div style="background-color:{{color}}" ng-transclude></div>'
};
});
app.controller('firstCtrl', function ($scope) {
});
You can create an isolate scope and bind the attribute to it:
myApp.directive('effectColor', [
function () {
return {
restrict: 'A',
scope: {
effectColor: '='
},
link: function (scope, element, attrs) {
element.css({
color: scope.effectColor
});
},
controller: [
'$scope', '$element', '$attrs', '$location',
function ($scope, $element, $attrs, $location) {
console.log($scope.effectColor);
}]
}
}]);
http://jsfiddle.net/R7Rb6/
It's a scenario of a directive with itself as the attribute. See here that how can you actually get value in your directive.

how to use a function which returns value to ng-model using angularjs?

I wan to call a function which returns value and I want to use that value as ng-model.
the returned value from function should be displayed in a dialog.
I see my dialog empty - No Data.
here is my code:
my-dialog is a directive to show dialog which accepts templateurl and ng-model.
<my-dialog my-dlg-template-url="/app/ScheduleDlg.html" ng-model="ViewSchedule">
<button ng-click="openDialog()">Schedule</button>
</my-dialog>
here is the function to be called in ng-model.
$scope.ViewSchedule = function () {
console.log('ViewSchedule function call');
.....
return obj.Schedule();
};
here is the directive:
return {
require: 'ngModel',
replace: true,
transclude: false,
priority: 100,
restrict: 'E',
scope: true,
link: function ($scope, $element, $attrs, $ctrl) {
var getDialogTemplate = $attrs.myDlgTemplateUrl;
$scope.openDialog = function (confirmationAction) {
var modalInstance = $modal.open({
backdrop: 'static',
templateUrl: getDialogTemplate,
controller: "myDialogCtrl",
resolve: {
dialogData: function () {
return {
dlgData: $attrs.ngModel
};
}
}
});
modalInstance.result.then(function () {
return confirmationAction();
});
};
}
};
}])
.controller('myDialogCtrl', ['$scope', '$modal', '$modalInstance', 'dialogData', function ($scope, $modal, $modalInstance, dialogData) {
$scope.dialogData = dialogData.dlgData;
$scope.onOk = function () {
$modalInstance.close();
};
$scope.onCancel = function () {
$modalInstance.dismiss('cancel');
};
}])
Here is the dialog template :
<tr ng-repeat="item in dialogData">
<td>{{item.$index}}</td>
<td>{{item.StartDate}}</td>
<td>{{item.EndDate}}</td>
</tr>
ng-model establishes a 2 way data binding only needed if you are planning to alter the model if not a simple scope definition with one way binding or a reference bound would do it
you currently have
scope:true
you can do
scope:{
watchfor:'#result'
}
and inside the directive set a watcher
scope.$watch('watchfor',function(val){})
in your direcitve declaration you could have.
<my-dialog my-dlg-template-url="/app/ScheduleDlg.html" result="ViewSchedule()"> </my-dialog>
and set this in your directive template
<button ng-click="openDialog()">Schedule</button>
unless you want it linked to your parent scope.

Categories