Angular - $apply already in progress - angularjs

I have a general angular question:
I got the same error as here:
https://github.com/angular-ui/bootstrap/issues/516.
Can this error ("$apply already in progress ") be a problem in my app? In my tests It seems that this error has no effects on my application. Every task inside still works.
Is it unproblematic to go with this error into the productive system?
Thank you very much.

This usually happens when you try to run $scope.$apply and there is already one $apply in progress. A workaround that always prevents this error for me is to use $timeout instead of $scope.$apply.

You stuck into this issue as your code try to trigger digest cycle before one got completed and that you are facing only in IE probably because of slow nature of IE. so my idea is to use $scope.$evalAsync
$scope.$evalAsync(function () {
console.log('I am done.');
});
OR
$scope.$evalAsync(angular.noop);
I hope this work for you.
Thanks

Related

Waiting for the click event in PhantomJS 2 with Jasmine 2.x and AngularJS

I am trying to test an Angular directive that uses the click event and getting nowhere. I can get the event to fire just fine, but PhantomJS2 just takes forever to make the event happen and I can't figure out a way to get Jasmine to wait for it to happen before running the assertion. I've searched quite a bit and the most common response is this: How to wait for a click() event to load in phantomjs before continuing?. Sadly, that guy hasn't figured it out either, and I'm not waiting for a page to load, just for the click event to finally register. I'm hoping that someone else has and just didn't see that question or didn't want to start a reply on such an old question. For reference, the directive in question selects the text within an input tag if there is none already selected. I've tried every permutation of timeouts that I can think of, but nothing works. The last attempt involved using the done() function from Jasmine, but still no luck.
//the default value in the input is "unchanged"
it('should not select anything if there is already a selection in the element', function(done) {
element[0].setSelectionRange(2, element[0].value.length);
element.triggerHandler('click');
scope.$digest();
expect(theWindow.getSelection().toString()).toEqual('changed');
done();
});
All reasonable suggestions will be considered. I'd be ecstatic if someone had a link to a solution that I somehow didn't find with my Google-foo.
Note: I got the idea about using setTimeout from here: https://newspaint.wordpress.com/2013/03/19/how-to-click-on-a-div-or-span-using-phantomjs/

Non-angular page opened with click - angular not defined using ignoreSynchronization or waiting for Angular without

After a lot of research, and tinkering, I can't seem to actually get my Protractor test to do anything else other than have an Angular related error, even though I am using browser to avoid Angular being detected at all.
The test involves an Angular app, opening a dropdown in it, and clicking on the link for the console; the console opens a non-Angular admin page in a separate window.
So based on the many informative SO posts I found, I first used this...
browser.driver.getAllWindowHandles().then(function(handles) {
browser.driver.switchTo().window(handles[1]).then(function() {
//expect for new window here
});
});
Which appeared to work, as I could get to the window through repl pretty easily.
The issue is when either of the following were added...
browser.driver.getAllWindowHandles().then(function(handles) {
browser.driver.switchTo().window(handles[1]).then(function() {
expect(browser.getLocationAbsUrl()).toContain('/console/login.jsp');
expect(browser.driver.findElement(By.css('th.login')).getText()).toEqual('Login');
});
});
One expect check the URL and the other checks for the header element on the page, which is a table header. When I run this, I get the following:
Error while waiting for Protractor to sync with the page: "angular could not be found on the window"
When I decide to use browser.ignoreSynchronization = true, both in the function, or in a beforeEach, with or without a following afterEach setting it to false, I get the following:
JavascriptError: angular is not defined
I can't seem to get any "useful" errors to help me debug it, and trying it in repl does not help, as I get the same issue.
To be comprehensive, trying my URL expect without getting the second window will give me the root, and the other will fail.
Just doing one or the other will cause the same problem.
Changing to regular syntax (element(by.css...)) does not change things.
So much for my first question...
It appears that my use of browser.getLocationAbsUrl() is meant to be used for an Angular page, and was causing my issue...
Essentially, even though I believed I was using pure Webdriver calls, that call still required Angular on the page to work...
As stated in another post, the use of browser.driver.getCurrentUrl() is a non-Angular call using Webdriver, and fixed the problem. Thus, the final code is the following...
browser.sleep(1000); //to wait for the page to load
browser.driver.getAllWindowHandles().then(function(handles) {
browser.driver.switchTo().window(handles[1]).then(function() {
expect(browser.driver.getCurrentUrl()).toContain('/console/login.jsp');
expect(browser.driver.findElement(By.css('th.login')).getText()).toEqual('Login');
});
});
This works without setting ignoreSynchronization, BTW.
I realized it would probably be something relatively simple to fix it, just didn't expect I'd get it that quickly (I intended on submitting the question last night, but posted it this morning instead).
In any case, I hope this will at least be a good reference for anyone else facing the same issue.
Seems like getLocationAbsUrl is angular abs url.
Try using the native driver getCurrentUrl instead.
-- expect(browser.getLocationAbsUrl()).toContain('/console/login.jsp');
++ expect(browser.driver.getCurrentUrl() ...

Protractors waitForAngular and angularfire/firebase

From my understanding, waitForAngular is executed on each step, and it waits for any kind of angular rendering and/or $http calls before proceeding to the next step.
My problem I am having is, I'm using Angularfire/Firebase as my backend, and in my tests when I click on a button for example - the waitForAngular is executed too fast, and then next step has occured before firebase has come back with a result.
Does anyone know a simple way to extend waitForAngular to also wait for any Angularfire call?. That would solve my problem and I could get rid of all of these dreaded sleep calls.
If you're using something like this
element(by.css('.btn')).click()
ptor.waitForAngular();
//execute something after
You can try converting it to a nested promise resolve pattern like this
var ptor = protractor.getInstance();
ptor.findElement(protractor.By.css('.btn')).click().then(function(){
//execute something after
});
I only have some basic info about firebase but haven't used it ever. But I guess this should help with promises/http requests.

angular event doesn't update page

I'm converting a page in a mvc application with a lot of inline jquery javascript to angular using typescript.
The first calls works fine but I have a problem: based on a selection in a dropdown, the event updates several controls in the view, make a few ajax calls and finally update the view with the data from the calls.
Seems the conversion is working fine, but at the end of the call the page isn't updated.
I tried to remove all the old jquery code to avoid problems.
batarang and java console reports no errors.
the final ajax call is done and the result shown in a debug.
All seems to work fine, but the page isn't updated.
How can I find the problem?
thanks
Without seeing any code, it's difficult to answer but if you bind an event to an element and want to update something in the callback, you will have to use $apply
scope.$apply(function () {
// your code
});
$apply will trigger a $digest cycle, and should be used when you want to update something while being outside angular's context.
Most likely you are not handling your asynchronous calls correctly. It's impossible to tell from your question but it is a very common mistake with symptoms as you describe.
Make sure you are updating your model within the .then() method of a promise returned from an $http request. For example
someFnDoingHttpRequest().then(function(data){
// updated the model with the data
})
Also (another common mistake) make sure someFnDoingHttpRequest() returns a promise.
If you want to "find the problem" then you can use the following option.
Go to Internet Explorer (10 or 11).
Select "Internet Options" from the settings menu.
Go to the "Advanced" tab (the last tab)
Settings are listed and select "Display a notification about every script error"
Deselect the "Disable Script debugging (Internet Explorer)" and "Disable script debugging (Other)"
Run the program again, you will get notification about the real issue that happens while displaying actual result.

Angular-UI Bootstrap Modal requiring a timeout to close without error when closing from event

I'm getting an error current is null when I am executing the following code in the controller of the modal.
$scope.$on('cart:item_updated',function(evt, item){
$modalInstance.close();
//$timeout($modalInstance.close, 500);
});
I had to add the timeout to get it to work. I believe it has to do with the digest cycle, but my concern is that the timeout fix is a hack that will not work depending on how quickly a user's device is able to process the code. I'd rather know what is going on here and solve this properly. If I execute the .close() via a user initiated action from a button within the modal it seems to perform the action as expected with no errors.
The code is pretty limited to answer, however I am giving it a shot, you may try to use $scope.$watch instead of $scope.$on.

Resources