Angular Router not updating browser URL when called from AngularJS - angularjs

I have an AngularJS application, which I'm in the process of converting to a hybrid Angular/AngularJS application using ngUpgrade. The AngularJS application is unusual in that it doesn't use the AngularJS or Angular UI router - instead it has its own hand-rolled navigation solution, which doesn't update the URL displayed in the browser, or interact with the browser's history API. So far, so good.
I want to start using the Angular Router in the hybrid application, but initially only for new pages.
To get the 2 parts of the application - Angular and AngularJS - interoperating with each other, I have downgraded the Angular Router service and injected it into one of my AngularJS services, so that I can call Router.navigateByUrl() to navigate to a new Angular page component, from my AngularJS code.
This works correctly - the Angular page component is added to my <router-outlet> and is displayed in the browser as expected.
Strangely though, the browser URL does not change. When I enable tracing for the Router, I can see the new route being correctly processed, and the new page is displayed in the browser, but the browser URL still shows the old route. Also, if I look at the browser history, the new route has not been added to it.
I've tried injecting NgZone into my AngularJS service and calling Router.navigateByUrl() inside NgZone.run(), but it doesn't make any difference.
When I call Router.navigateByUrl() from my Angular code, everything works fine - except when I do this after I've done it from AngularJS, when I then see the same symptoms. It's as if calling the Router directly from AngularJS is somehow breaking the link between the route and the browser URL bar.
Can anyone help please...?

So the issue was that the AngularJS $location service wasn't being updated when the route changed, leaving a disparity between its value and the value being displayed in the browser. There was also a watch in this service which was being triggered in every digest cycle, that was then resetting the browser url from the value in the $location service!
Turns out this was because I needed to configure the Unified Angular Location Service in my AppModule viz:
imports: [
LocationUpgradeModule.config()
]
and downgrade the $locationShim service for injection into AngularJS viz:
angularJS.module('my-app')
.factory('$location', downgradeInjectable($locationShim));

Related

if i used angular but handled routing through backend would it be still a single page application?

I read that if i handled routing through server, when a client asks for a page resulting the server to render a new document which will also result to refresh the web page unlike frontend/angular routing.
No. It wouldn't be a single page application. If you route through backend, whenever you change a route, your entire application will be bootstrapped in the browser again losing the essence of angularJS

Why does my angular js service gets destroyed after server call?

As per my understanding services in angularjs are "Singleton". Following is my Scenario where I am using angularjs with Asp.net MVC application.
I have created angularjs service and I use it in one of my controller, which is used on one of the HTML view. If I navigate from that page to some other page, Which results in call to Server then in that case my angularjs Service gets reset. Later, When I come back to the same page my service again gets created/initialized. Can someone please explain me the reason?
Most likely you use ngRoute or angular-ui routing for making single page app, when you change pages controller gets reloaded, which forces all the logic in controller to run again hence call your service, If you are on the view which use other controller its expected not to run service from first one. Some code would be nice too.
hope this helps.

Using $location service with non SPA

I am trying to build a non SPA angularjs app. Routing from my server works fine but the problem I have encountered is that the $location service seems unable to understand my url. For example, if I have http://localhost:9000/test/item?id=abc123 and I call $location.search() in my controller, it returns an empty object. It appears as though angular always assumes there is a hash (#) in your url. I tried using the $locationProvider to turn on html5 mode and in this mode $location.search() will return an object with id=abc123 as expected. However, with html5 mode turned on, non of my links are hitting up the server for routing anymore. The url in the address bar gets changed but no server call is made.
So, how do you build a non SPA site with angular and still make use of the $location service for parsing query params. Is this possible or do I have to write my own url parser?
update: I am using angular 1.3.15

Prevent angular from handling a url

I have an angular web page in which I also have a twitter bootstrap carousel.
The carousel have arrow buttons to jump to the next/previous image with the following url: http://localhost:8080/#myCarousel
Whenever I click on it, it takes me to http://localhost:8080/#/
I tried removing every angular reference and just building an html static version of the page and it works ok, so I guess that the angular router is handling the url with the #myCarousel fragment.
How can I prevent this from happening?
On clicking the arrows the url changes in the address bar and the router handles the change which is the required behaviour. Use carousel directive from ui-bootstrap to implement the carousel or you can write ur custom function on click of those links
Angular uses # as the prefix for any route handled by it by default. This allows angular routes to be handled as if they are page anchors, and allows the page to update without a new browser request going to the server. Unfortunately, JQuery also uses this technique.
To avoid this conflict, you can change the prefix which is used by angular. From the angular Documentation:
$locationProvider.hashPrefix("!");
This will result in Angular links as /#! rather than /#. You can also optionally enable HTML5Mode, which uses HTML5 Push State to handle URLs without a hash at all, in browsers that support it. You should still consider adding a hash prefix as a fallback, for older browsers.

Removing the hashtag from AngularJS when working with SailsJS

I'm getting really frustrated with configuring the Routing on our app, which is using sailsJS and angularJS.
The problem is, that the browser doesn't know about angular, so any request like /login returns a 404 Error from sails. I need a solution, to keep the sails routes from the angular ones,
One solution would be to disable html5Mode, but i really don't like the look of URLs with the /#/ which is typical for angular.
I have researched a lot on this and haven't yet found a good answer or maybe a working project for this.
Is what I am trying to do even possible right now?
If you're using HTML5 mode with Angular, then you need to configure your web server (in this case SailsJS) to respond with your index.html file for requests to /login or any arbitrary routes.
If you navigate directly to http://localhost:3000/login in your web browser (assuming you're running Sails on localhost:3000), Sails needs to respond with your index.html so that your Angular app can bootstrap and then display the appropriate route. Then, subsequent links that the user clicks on in your app will be intercepted directly by the Angular router instead of Sails directly.
Angular has documentation about making HTML5 mode work correctly here.
Using this mode requires URL rewriting on server side, basically you have to rewrite all your links to entry point of your application (e.g. index.html). Requiring a <base> tag is also important for this case, as it allows Angular to differentiate between the part of the url that is the application base and the path that should be handeled by the application.

Resources