Changing $scope from inside $rootScope is not getting reflected - angularjs

I am trying to show one button as in this Plunker
<div ng-show="showbtn"><button class="fix btn btn-success" ng-click="top()">To the top</button></div>
On scroll event, I have made $rootScope.$emit call and it is getting triggered too, but not sure why the $scope value is not getting changed inside the mainCtrl controller $scope. Is $scope inside $rootScope is different ?

The event handler (the function passed to $rootScope.$on) runs outside of Angular's normal digest cycle so you need to tell the parent scope that something has changed. You can use $apply to do so:
$rootScope.$on('scrolled',function(event,data){
$scope.$apply(function () {
$scope.showbtn = data.message;
});
});
Here's an updated Plunker.

Related

How to update the $scope variable values with the new Values I'm getting from the Database?

I have been setting the response values every time I hit the web-service to a $scope variable on click of a button but the $scope variable is not getting updated with the new values I have to Click the button twice so that the $scope variables get updated. also I have checked, each time I hit the button the web-service is properly getting called.
controller.js
$scope.getDetails = function() {
services.getSomeDetails($scope.id).then(function(response) {
$scope.details= response.data;
}
}
view.html
<a ng-click="getDetails();">Click me!</a>
Use $scope.$apply() after your scope Variable.
services.getSomeDetails($scope.id).then(function(response) {
$scope.details= response.data;
$scope.$apply();
}
If you are using jquery click event, it will not trigger digest circle of angular. Use ng-click directive or add $scope.$digest() or $scope.$apply() after update scope variable
services.getSomeDetails($scope.id).then(function(response) {
$scope.details= response.data;
$scope.$apply()
}

Event onclick in my controller

I wrote thi code in my controllers:
$('#categoryId').on('click', function(event){
$scope.items = $scope.getUpdatedItems ();
console.log('Items ',$scope.items );
});
In my directives I have this:
....
scope.$watch('items', function(items){
console.log('Directives - Items ',items );
....
The problem is that I never enter in the $watch declared in my directives.
Somebody can help me..
Thanks
You shouldn't mixed up jQuery with AngularJS that will mess up with the digest cycle on angular. Angular did provided its own directive to handle such activity like in your case you could us ng-click directive, this will call the mentioned function inside ng-click attribute value on click on that element.
Markup
<button type="categoryId" ng-click="updateAllItems()"></button>
Code
$scope.updateAllItems = function(){
$scope.items = $scope.getUpdatedItems ();
console.log('Items ',$scope.items );
});
Above code will call updateAllItems function which resides inside controller & then $scope.items will get updated. And then you watch inside directive will get call.

Angularjs destroy is not working

http://plnkr.co/edit/UfQJU661pQR0DMY3c61t?p=preview
I got above code from AngularJs site and only thing I have added a button to delete a Div where we have controller but after delete no destroy method called as I have put alert in Directive and Controller.
element.on('$destroy', function() {
alert('destroy directive interval');
$interval.cancel(stopTime);
});
and
$scope.$on('$destroy', function() {
alert('destroy controller interval');
// Make sure that the interval is destroyed too
$scope.stopFight();
});
please suggest.
Thanks
The main thing to be noticed
When element.remove() is executed that element and all of its children will be removed from the DOM together will all event handlers attached via for example element.on.
It will not destroy the $scope associated with the element.
So you need to manually trigger scope.$destroy();
First get the scope of element:-
var scope = angular.element(document.getElementById("mainDiv")).scope();
Second remove the element from dom:-
$('#mainDiv').remove();
Third destroy scope manually:-
scope.$destroy();
Plunker
You're doing it outside of angular's context.
<button id="btn" onclick="DeleteMainDiv()">DeleteDiv</button>
So in your DeleteMainDiv() function
function DeleteMainDiv() {
alert('Controller div going to remove');
//debugger;
var scope = angular.element(document.getElementById("mainDiv")).scope();
$('#mainDiv').remove();
scope.$destroy();
}
This will trigger the destroy functionality.
But I don't see a need of it. Angular will automatically run the $destroy event handler when the route changes or directive no longer required.
DEMO

$watch on clientWidth isn't working

Inside of my directive I have this and it works only in the beginning, and whenever I resize later it never fires.
scope.$watch ->
cw: element[0].clientWidth
,(newValue, oldValue)->
if newValue.cw isnt oldValue.cw
console.log "changed"
,true
Your function looks right to me, but it's important to note that it won't fire on resize unless you manually trigger a digest on the resize event.
Without this, angular doesn't realise there's been an event that should trigger a digest, and so none happen.
Try adding this (remember to inject $window):
angular.element($window).bind('resize', ()->
scope.$apply();
)
Just like Jason Goemaat said, its because Watches are only checked on a $digest cycle
Depending on how the way your element is resized maybe this example may help you.
Here is a menu that expands it self when pressed on the arrow.
<div class="menu" ng-class="{'expanded' : main.expanded}">
<div class="menu-handler" ng-click="main.expanded = !main.expanded">
</div>
</div>
The menu is expanded by a ng-click that makes a change on the scope, in this case its a boolean var that acts as a flag. As the opening of the menu is made throught the change in the scope it calls the $digest cycle iterating through all $watch.
scope.$watch(function() {
return element[0].clientWidth;
}, function(oldValue, newValue) {
console.log(oldValue, newValue);
});
You can view the full example in this JSfiddle
https://jsfiddle.net/owenbcal/zf17s0mL/
Hope i was helpfull.
the way I know about watching this kind of values is making a function that is fired once the value changes so then I watch that function :
in the service:
this.getDataOut = function () {
return self.dataOut;
};
in the controller:
$scope.$watch(dataService.getDataOut, function() {
$scope.dataOut = dataService.dataOut;
});

angularjs: $scope update when I change a select with jQuery

I'm using a jQuery plugin to 'customize' my selects.
This plugin fires the change event of the original select when some option is selected.
The problem is that my scope doesn't change.
Here you can see a quick example... changing the select the scope changes. clicking the buttons the select changes but not the scope.
http://plnkr.co/edit/pYzqeL6jrQdTNkqwF1HG?p=preview
What am I missing?
You need to access the scope of the dropdown and then apply it as shown below:
$('button').on('click', function(){
var newVal = $(this).data('val');
$('select').val(newVal).change();
var scope = angular.element($("select")).scope();
scope.$apply(function(){
scope.selectValue = newVal;
});
});
When you click the button, angular goes out of its scope and uses jquery to manipulate the data/to perform some action, so we need to exlicitly call $scope.$apply() to reflect the changes back into the scope of the controller. And change your controller to this:
app.controller('AppCtrl', function($scope) {
$('button').on('click', function(){
$scope.selectValue=$(this).data('val');
$scope.$apply();
});
}
By the way you can use jquery event inside the angular..
Ideally in angularJS, controller should not update DOM reference directly. If you want to achieve same thing, you should expose one method over $scope and use "ng-click" directive.
If you want to achieve same using jQuery, it should go into directive as
$scope.$apply()
to update the scope.
In your jQuery put auto trigger e.g
$('#input').click(function(){
$('#input').val('1');
$('#input').trigger('input'); //add this line this will bind $scope Variable
});
It's best not to mix DOM manipulation with Angular. Try the following for your button HTML:
<button class="setVal" ng-click="selectValue=1">Set 1</button>
<button class="setVal" ng-click="selectValue=2">Set 2</button>
<button class="setVal" ng-click="selectValue=3">Set 3</button>
I tried the above in your Plunker and it worked.

Resources