[And a second question (see below) - rootScope variable set in one controller not visible in a second, sibling controller?]
Possible Duplicate: angularjs $location.path only updates URL on second click - the cause of the problem and the answer does not seem relevant in my, more basic, situation
As per the angularjs docs (https://docs.angularjs.org/guide/$location):
[The $location service]
Maintains synchronization between itself and the browser's URL when the user
...
Clicks on a link in the page.
I understood that $location.path() reflects the current url in the browser, but when I click a link to change the view, exhibits strange behaviour: $location.path() does not 'change' the first time one clicks on a link, and every time thereafter it will change to the link that was clicked the previous time
To see this go here: http://jsfiddle.net/7Ah2W/
I attempted a workaround whereby I must manually set $location.path() using the setter overload.
In doing so, I found another flaw in my understanding of angularjs. I tried setting a variable in the rootScope to reflect the 'current path.' The idea is that views would automatically detect the change in the variable and update. Does not every scope inherit from rootScope?
Here is a jsfiddle
Why is my expectation that $rootScope.currentPath, being changed in 'NavCtrl' and updated in 'CtrlTwo' not being met?
My end goal is to have my navigation bar automatically change when a link in the view is clicked. Similar to https://console.developers.google.com where if you click your project, the navigation to the left changes to API&Auth, settings, etc.
The reason it seems to always be "one behind" is that you're accessing the $location.path() before the actual angular page process can run. Strangely enough if you just add a $timeout with even 0ms delay, it'll work as intended.
$timeout(function () {
$scope.currentPath = $location.path();
}, 0);
jsFiddle example
$rootScope is the global scope, as opposed to the regular $scope which is basically the glue between the controller & view.
For example I set $rootScope.test = 123; in your first controller, and in the second controller I alert that variable, and get the result. jsFiddle $rootScope example. Be careful with $rootScope, it creates globally scoped variables
Related
I am a bit of a beginner, but I would like to ask a general question. AngularJS does a watch on binded variables. My question is, when I navigate and a new html template is loaded, are the old watched values removed, or do they stay in the loop?
Hello $watch is bound to a controller ,which in turn shows the data to an HTML template.
So, If you navigate to another state or url and another controller loads , then the previous controller with all the data and the $watch will be unloaded, but new ones($watch) will load from the new loaded controller(if there are any).
$watch are never removed by itself, they have to be removed manually.
You should go through $watch lifecycle : $watch life cycle
No, the $watch list is updated as per the html which is being rendered by the browser.If you change template inside the page, the browser will have to render the new expression.
I think this youtube video would help you in getting
I hope someone can help me with this problem, it really drives me crazy :P I have created a Plunker in order to illustrate the problem. See the Demo here http://plnkr.co/edit/BRlDgKYlE87Bh3t53tpZ?p=preview.
My code is in the plunker.
So my problem is that I'm not able to change my scope value in a different html view that I'm in. As the Plunker show, I have two buttons in index.html; button1 and button2. When I click on button1 I want scope.test to change to "button1", and when I click on button2 it should change to "button2", this value exists in index2.html. As you can see on the console.log message, that never happen. I use rootscope, but still I'm only able to change the value if the scope exists in the same html page and not in another. Please help!
What you have coded up is not a single page application, html2 has no idea about your angular code in app.js. You need to use routing and you should be using a service to share state between the two 'pages' or views in the case of angular routing
EDIT
Take a look at this plunkr
Here you will see angular routing in action and a service that can be shared between the two controllers. When switching between the two pages, the controllers they are attached to get destroyed, so going from Page 1 to Page 2 means that contollerA no longer exists, so you need to use the service to store the state of what was clicked on from Page 1.
Hope this makes sense!
I am simply trying to add a dynamic element to the end of a list but I want that dynamic element to be evaluated by Angular so that when it is clicked it can register an ng-click event. This works as expected but when I click it a second time I get an infdig error.
This may be important, not sure, the list it gets appended to is a list of links, they go to different pages in the application (using angularUI router) and those "pages" are in the same view so the page doesn't change just the content on the page. All of those "pages" use the same controller and template.
feedbacklink = angular.element('<li><a ng-click="test()" id="reviewPageLink">Customer Feedback</a></li>');
$('#section_2 ul').first().append(feedbacklink);
$compile(feedbacklink)($scope);
The ng-click triggers (simplified to show the issue):
$scope.test = function () {
alert('test');
};
It seems to me like the $compile is being called again but that doesn't seem to be the case when I put a console.log immediately following the compile, it only shows once. Is there a way to assure that compile only runs once, or is that not even the problem?
I am having issues with something which might imply I am missing something conceptual. I am using a view with a controller which populates from a couple of different services(asynchronous). Everything works fine the FIRST time the view is navigated to. All the expected elements get populated in the controller and the dom is rendered perfectly. However, the SECOND time a user navigates to the same view, the DOM does not render all the elements. I have put breaks in the code and have confirmed that the data is populated by the service exactly as it was the first time.
I put a break on a click event so I could inspect the scope post rendering. As expected the first time it is rendered, everything is as expected. The second time, despite watching the scope variable get set, when I inspect the scope post rendering the variable is undefined!! I have looked to see the $id of the scope. I can see that the first time the $id of the scope is the same through the whole initialization and rendering. The second time the controller is initializing the same scope but when I inspect post rendering I can see that the scope has changed and is now different from the one used by the controller to initialize. I don't understand what created this second scope OR why the first scope was used to initialize the controller.
So my question(s) to the AngularJS folks are as follows:
1. Are there differences in how Angular behaves from the first and then subsequent route events to the same route. I have noticed that the pages render faster.
2. How do $digest/$apply come in to play? It won't let me call them because I get the inprog error.
3. How/approaches to debugging this? I really don't understand where to go with this. Its as if I have lost the two way bindings.
Thanks.
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.