Add class later request was completed with Angular loading bar - angularjs

I'm working my frontend with angular and angular-loading-bar, in the controller I put this code.
$rootScope.$on("cfpLoadingBar:completed",function(){
$(".animated").addClass("fadeIn");
});
or
$scope.$on("cfpLoadingBar:completed",function(){
$(".animated").addClass("fadeIn");
});
When the all XHR requests have returned, I want to add a clase in my section content, but the code inside event don't run.
How is the correct way to achieve it?

Firstly, check that you use appropriate event name. For example, are you sure thet its name is cfpLoadingBar:completed? Maybe its a cfpLoadingBar::completed (its a very common pattern) or something else?
Second, ensure that you have to subscribe to this event using $rootScope. Maybe you have to subscribe for it in some concrete controller witj its own $scope?
And as a big suggestion: DO NOT USE JQUERY AND ANGULAR TOGETHER IN YOU CODE, DO NOT MESS IT UP!!! Angular has a built in possibility to work also as a jquery. All that you need is to call angular.element() which returns you an element as if would use jquery. In your case you can write angular.element(".animated").addClass("fadeIn"); and it will do the same thing, but in angular way

Yeah, I use both cfpLoadingBar::completed and cfpLoadingBar:completed but don't run this event.
In the other hand I only have one controller by one section, it ran but I needed add a main controller and registered this event and propagate up the event with $broadcast in my child controller.
This is code in MainController
$scope.$on('cfpLoadingBar:completed', function(event, data) {
angular.element(".animated").addClass("fadeIn");
});
And This is code in other Child Controller
$rootScope.$broadcast('cfpLoadingBar:completed');
it is the only way to achieve, I don't know why XD
Thanks Andrew this way is better angular.element()

Related

How to use data-image and data-zoom-image attributes in angularjs

I need to add elevateZoom image slider to my Angular application. Following is my html code.
<img id="zoom_03"
ng-src='{{galaryImages[0].w320}}'
data-zoom-image='{{galaryImages[0].original}}'/>
Here
{{galaryImages[0].original}}
and
{{galaryImages[0].w320}}
is being loading dynamically using Ajax call from controller. ng-src is working successfully. but since i have used data-zoom-image as larger image it is executing before controller fetch the results because of that elevateZoom script is not working properly because zoom-image is assign to angular expression which is {{galaryImages[0].original}}. What is the solution to overcome this issue? are there any way to handle attributes like data-zoom-image as angular handling ng-src? or any other solution.
Thanks
Without knowing what elevateZoom is really, I can suggest you do either 1 of 2 things. The first is create a custom directive to handle this. The second is use ng-attr.
With ng-attr, you can do something like
ng-attr-ng-src='{{galaryImages[0].w320}}'
ng-attr-data-zoom-image='{{galaryImages[0].original}}'
I'm not sure how elevateZoom, if it's just taking a snapshot of your variables, then you will have to do something else. If it's built for angular and binds to the variables, then it should work.
If you want it to wait, you can do soethimng like toggling a boolean like
<img id="zoom_03" ng-if="isLoaded"
Where you set is loaded to false by default, then when your ajax call is done you set it to true
.complete(function() {
//apply your logic
$scope.isLoaded = true;
ng-if will take it off the dom completely, and will evaluate when you bring it back on by setting isLoaded to true.
Note: either way you do this I still recommend you bring this into an angular directive, it looks like this is a jquery plug in. The best thing to do is to put it in a directive and apply the logic through the directive, or find one already built for angular. You will find it very difficult to use jquery logic into angular if you don't have a directive. For instance this plug in might be firing on document.ready to look for the custom vars, in which case the ng-if wont work.

jQuery element initialization in Angular

I'm learning AngularJs and I'm playing with a third party Javascript component.
At a certain point the control is initialized as follows:
$(document).ready(function () {
$('#SomeId').initialize();
});
Is there a way to convert this to something more Angularish? I don't want to manipulate the DOM from the controller, but I'm not sure how to initialize this.
This code is not necessarily wrong as is. What you want to be careful about is javascript outside of the angular context (jQuery callbacks/plugins etc) manipulating $scope values because those functions will not trigger an angular digest loop, and will result in a disconnect between the DOM and the $scope.
Here is some more information about this cycle and what you need to know about it: http://jimhoskins.com/2012/12/17/angularjs-and-apply.html
Here is a common use case with jQuery (and also why you should try to use angular services (ie: $http) instead:
// When you manipulate the $scope with a non-angular callback,
// you have to run $scope.$apply() to tell angular about the
// change in order to repaint the DOM
$.get( "/getUser", function( data ) {
$scope.user = data; // set $scope data in callback
$scope.$apply(); // run digest so anything in the DOM binded to the {{user}} model gets updated
});
Generally you don't need to manipulate the DOM like this with Angular...so you really don't need jQuery. Using an Angular "directive" is the declarative, encapsulated way to do it in Angular. There are a ton of 3rd party components out there for you to use that have been built properly with directives: I would recommend using these rather than trying to convert a jQuery plugin (which is really just adding the jQuery bloat for things that you already have access to with Angular). A good place to start looking for Angular directives that you can use is http://ngmodules.org/

$on Not Communicating With $Scope When Used With ng-include

Basically, I am unable to update my controller information when I listen for the $on event if I loaded my html dynamically using ng-include. Plunker example.
If you click once, you'll see the view keeps the original $scope.name. If you click again it will update.
I put a setTimeout on the broadcast to make sure the ng-include was loaded. You can set that to as long as you want, and will never be able to update the $scope on the first try (at least in my example).
Thoughts?
EDIT:
I'm using <ng-include="template"></ng-template>
As an area I can load alternate content in. If there is a better way to do this, please let me know.
setTimeout() is a function out of the control of AngularJS, so AngularJS will not automatically run a digest after the callback runs. That means, your $rootScope.$broadcast() was run, but AngularJS didn't realize that. The next time when you use $rootScope.template = '....';, a digest runs, and the view was updated to the previous run's model.
To solve the problem, you will need to manually call $scope.$apply() at the end of your setTimeout() callback, or use the Angular-wrapped version of setTimeout(), which is $timeout(), that will automatically run a digest afterwards.
Please refer to the docs for more details about digest/apply:
It works for me if you use $timeout instead of setTimeout. Which you should be using for angular applications.
$timeout(function(){
$rootScope.$broadcast('BROADCAST', param);
}, 1000);
There is definitely something wrong with your design if you are trying to do something like this though. Perhaps someone could suggest an alternate solution if you better explained what you are trying to achieve. As you cannot possibly know how long the timeout should be.
A few things:
1) First, do not define the $scope.template in the broadcast function. The ngInclude will not have a file to display until that value is set; so from it makes sense--in my mind--that the template would not be able to make changes before it and the controller are loaded.
2) You never actually apply Controller C2 to the ngInclude. You can do that like:
<ng-include src="template" ng-controller="c2"></ng-include>
Once I do these two things, the code works and updates the first time without the use of the setTimeout() at all.
Plunker

AngularJs and 2-way binding. scope.$apply()

everybody!
Here is my not working and not complete sample for demonstrating purposes.
In few words, suppose that I have some control and some control event (select tv node), in this event I change some scope variable, say $scope.test and I expect it to change (it's value on html page). But in provided sample code it doesn't change unless I use scope.$apply() method (commented), when scope.$apply() is used then everything works as expected.
So, my question is more about applicability of use of scope.$apply() method.
There are a lot of articles related to this and most of them suggest that apply() method shouldn't be used unless you are developing angular directives
or some advanced binding scenarious. That's why I'm a little bit confused with my relatively simple case.
Thanks in advance.
The rule is that you call $scope.$apply() whenever you change some state that Angular has to respond to outside of Angular's framework, eg an event handled by jQuery (or in your case Kendo) event handlers.
Moreover the $scope should not be available in your select: handler because the handler is Kendo, $scope is Angular. (Indeed your example throws Cannot set property 'test' of undefined when clicking on a label.)

AngularJS $scope doesn't render after being updated

I have a controller that listens on $scope.$on, which will show a popup window when triggered. It works 100% of the time from a couple other controllers' $rootScope.$broadcast methods. But one of them won't work ever.
The controller gets the event, and sets the $scope variable needed, but the page doesn't update, even if I fire $scope.$eval(). Then, if I go to another route, the $scope will finally render, and the modal will pop up on top of that route. I can't tell if I've found a bug in angularjs, or I'm missing something fundamental.
You are probably changing the $scope outside of the angular $digest(). Try replacing code making changes with $scope.$apply(function(){ code making changes }). With this the dirty-check should run and update all.
I would recommend using:
$scope.$evalAsync(function() { // scope changes here });
This way you won't run into problems like trying to call apply when there's a digest already in progress.

Resources