Relative URL for RouteProvider in AngularJS - angularjs

I have a website that will likely be placed within a directory in IIS. When I am running the application on my computer through IISExpress, the routes are relative to the base URL, so I can just define my routes as follows:
$routeProvider.when("/home", {
controller: "homeController",
templateUrl: "/app/layout/myView.html"
});
This gives me the following URL:
http://localhost:60847/#/home
When I put publish this site to our server, I have the URL:
http://dev.mysite.com/MyApp/#/home
However, I keep getting an error "Failed to load template: /app/layout/myView.html". When I look at Fiddler, I can see that it is trying to pull in the template from http://dev.mysite.com/app/layout/myView.html instead of from http://dev.mysite.com/MyApp/app/layout/myView.html. I have tried rewriting the templateUrl as ../app/layout/myView.html, as ~/app/layout/myView.html, and as ../../app/layout/myView.html. No matter what I do, I still end up trying to pull it from the parent folder instead of from MyApp. I have also tried setting a web.config setting and using that to put a prefix on the templateUrl, but it doesn't seem to want to run that code prior to loading the template. Finally, I have tried setting up a function for the templateUrl, but the way I have that stored in the web.config file creates timing issues with pulling the information.
It seems as if this must be a common issue that I am making overly complicated. Is there a way to make this a relative URL?

You should add to your HTML's head:
<base href="MyApp/" />
See this documentation page for more details.

Related

Is it possible to define AngularJS route's templateUrl path fully agnostic to IIS app folder structure?

I have have done some research here and in general, but couldnt find a proper way to implement this.
We have and MVC/WebAPI2/AngularJS Web app.
I am trying to achive this goal: being able to put my app anywhere in IIS app folder structure without any code changes. That means, get rid of any IIS Application name in my code.
Here is a simple fragment of ng-route path defined:
.when("/", { templateUrl: "Home/Main", controller: "MainController",
controllerAs: "vm" })
Now, the IIS app is called ReportsWeb (but could be any name)
If I set ReportsWeb app under Default Web Site root:
http://localhost/ReportsWeb/
then everything works fine, and templateUrl page is loaded fine.
But if the app is placed under another IIS App (the one we have here is called RealSuiteApps, which is itself under Default Web Site)
http://localhost/RealSuiteApps/ReportsWeb/
then, the templates are not loaded, since constructed URL for templateUrl is no longer valid:
http://localhost/RealSuiteApps/Home/Main
If I change templateUrl to "/Home/Main", constructed URL is not valid again
http://localhost/Home/Main
If I change templateUrl to "./Home/Main", constructed URL is not valid again
http://localhost/RealSuiteApps/Home/Main
Is it possible to define templateUrl only relative to the latest App name in the IIS hierarchy without hardcoding all these names, so that it will work in any IIS app tree
http://localhost/App1/App2/App3/ReportsWeb/
Thanks!
I use grunt-html2js tool to convert all html templates to Javascript at build time, which uses Angular's template cache.
I've defined my grunt task to overwrite the default module naming to templates/ so that I can reference any template easily:
html2js: {
options: {
rename: function (moduleName) {
return moduleName.replace(/^.*[\/\\]/, 'templates/');
}
},
all: {
src: ['./src/**/*.html', '!./src/index.html'],
dest: 'tmp/templates.js'
}
},
This will create a templates.js file that I can include as a script tag. Then I can access any template like so:
templatUrl: 'templates/my-template-filename.html'
Regardless of where it's path was in the source code.

AngularJS Routing not working when url typed

So, I'm pretty new to AngularJS and I'm trying to use AngularJs ngRoute in my application.
It all works smoothly when I start at the application homepage:
http://localhost:8080/appName/
And when I click on links from this point it works smoothly.
However, when I type a URL that I know exists/works, it gives me a 404 error. If I go to that link by using the application instead of the url it loads fine, even though it has the same url.
Eg. http://localhost:8080/appName/search
will give a 404, even though that is the same url that is the default redirect.
Indeed, the only url that will load by typing in the location is the base URL I mentioned above.
My app.js looks like this:
app.config( ['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider){
$routeProvider
.when("/search", {
templateUrl: "search.html",
controller: "SearchController"
})
.when("/results", {
templateUrl: "results.html",
controller: "ResultsController"
})
.when("/browse", {
templateUrl: "browse.html",
controller: "BrowseController"
})
.otherwise({redirectTo:"/search"});
//This gets rid of the # on the urls to the templates
$locationProvider.html5Mode(true);
}]);
I am hosting this on a glassfish4 server.
Is there something obvious I am missing/misunderstanding about how ngRoute works? Is there some setting that I am missing?
All help appreciated...
EDIT 1: As #Matthew Green below says, I need to configure the webserver to return the index.html for all pages below
http://localhost:8080/appName
I know I am being completely dense here, but where abouts is this configured? I am hosting the code in a MAVEN Jersey-Quickstart-Webapp.
When you use ngRoute, you are using javascript to handle routing to create a SPA. That means you need to hit a real page that loads your routing for your application to know what page to route to.
For example, your http://localhost:8080/appName/ should be routing to your index.html which would contain the javascript for your routing. With that page loaded it knows how to handle the links you have in your application. However, if you were to go directly to http://localhost:8080/appName/pageName you also need that to load index.html, as it is the one that loads your routing. Once your routing is loaded it should direct you to the correct page in your application. Without redirecting in place, http://localhost:8080/appName/pageName is not a real page and therefore correctly returns a 404.
Knowing this, the thing you have to figure out is what kind of server setup you have to configure the appropriate redirects for everything under http://localhost:8080/appName/ to go to your index.html page.

$routeProvider stopped working from absolute path

Weird thing happened. It was working fine. I have not changed anything related to routes, but it stopped working when accessed using an absolute path.
Here's what I have in app.js:
myApp.config(function($routeProvider) {
$routeProvider.when('/', {
templateUrl: '/app/views/entry.html'
})
.when('/orderstatus/:routeParam', {
controller: 'controllerController',
templateUrl: '/app/views/page.html'
})
...etc.etc
If I access "orderstatus" with parameter from inside the website, e.g. I navigate to the website.com, then access this route, it works fine.
But if I access it using an absolute path, e.g.
https://website.com/index.html#/orderstatus/24c98f38-190d-4a0c-86a2-49fb5f4d68fb
it redirects back to https://website.com/index.html#/
It used to work fine. I need this direct path because we email the customer order confirmation, and they can click on the link and get to the order confirmation page directly.
Now it does not work all of a sudden. I am totally perplexed as to why this could have happened. Like I said, it worked before.
If that matters, I am referencing a CDN at
https://code.angularjs.org/1.4.6/angular-route.min.js
and regular angular js at:
https://code.angularjs.org/1.4.5/angular.min.js
Live and learn.
One of my directives that's included in index.html was redirecting to the root on error.
ng-route was working fine and as expected.

Angular setup with xampp as server

I'm working on a front-end project which I have wired up with angularjs. In the main page I have an ng-view component and the router basically matches partial routes to different template views with different controllers, as such:
/* ... */
myApp.config(function($routeProvider) {
$routeProvider.when('/', {
templateUrl: '/pages/01-landing-page.html',
controller: 'firstCtrl'
}).
when('/part2', {
templateUrl: '/pages/02-second-page.html',
controller: 'secondCtrl'
})
/* ... */
When I run the project from the Adobe Brackets editor which comes with a built-in server all files are loaded properly, including the view pages from the 'templateUrl' attributes.
However when I try to serve the files from XAMPP, the routing seems to get messed up.
Suppose I have the project inside the following directory path: '/xampp/htdocs/proj/proj1'
The main page "index.html" is loaded, however when the angular tries to load the "/pages/01-landing-page.html" the http request for that component is
GET myipaddress/pages/01-landing-page.html 404 (Not Found)
instead of
GET myipaddress/proj/proj1/pages/01-landing-page.html
Any idea why angular in this xampp instance seems to ignore the relative path to the project but inside the brackets server it serves everything as it should?

AngularJS and PhoneGap: $location.path causes subsequent tempateUrl lookup to fail

I'm having trouble getting path lookup to work with a AngularJS v1.2.0 and PhoneGap/Cordova Android application. I've come pretty far with html5mode(true) by setting <base href="."/> in index.html and then changing $routeProvider.when('/') to $routeProvider.when('/android_asset/www/index.html'). After that I am able to get redirectTo('login') to reach $routeProvider.when('/login') and there render templateUrl: 'static/partials/login.html' as expected.
The problem I have is that if I instead try to redirect to the login page from my Javascript code with $location.path('/login');, the route is found but templateUrl loading fails with an insecurl exception.
I've tried whitelisting access to file:// by using the new angular-sanitize module, but that does not help.
How can I make $location.path() do the same things as redirectTo so that the partial is loaded? Or is there some other way to solve this problem?
UPDATE: I got a bit forward by adding a call to replace() after the path function, e.g.:
$location.path('/login').replace();
but that seems like a hack, and it still causes the templateUrl in the otherwise route to fail with the same exception.
Any ideas on what might be wrong? Is it that html5mode(true) just does not work at this moment with Phonegap and the only way to fix this is to set it to false and add hashtags to every path (like is done in the angular phonegap seed project)?
For future reference, this is how I managed to solve the problem:
AngularJS currently does not seem to support html5mode(true) inside a Cordova application because of the insecurl problem I reported. What I had to do is add
var h5m = (typeof html5Mode !== 'undefined') ? html5Mode : true;
$locationProvider.html5Mode(h5m);
which gives me the possibility to explicitly set html5Mode in the PhoneGap index.html with a global variable:
<script>
var html5Mode = false;
</script>
So now $location.path('/login') as well as redirectTo: 'login' works, but links in html files, don't. To get those working in PhoneGap, with html5Mode disabled, I had to add #/ in front of every link, e.g. login.
That makes PhoneGap work, but breaks the web page which uses History API with html5Mode(true). The last piece of the puzzle was to add <base href="/"/> to the web page's index.html (and leave it out of the index.html of the PhoneGap project.) So now even though I have a link that says #/login in the web page, I get to the url http://example.com/login and don't see any hashes in the address bar.
**
So in the end I have History API working in my web page and History API disabled in the PhoneGap project (where there really is no need for History API as there is no address bar). The only downside is the extra #/ I have to put in each template html file, but that is a minor annoyance compared to the ability to use all of the same html and javascript files for both web and mobile.
I had this same problem as well. I managed to fix it by skipping the leading slash in the route config:
$routeProvider
// route for the foo page
.when('/foo', {
templateUrl: 'foo.html', //previously: '/foo.html'
controller: 'fooController'
}) //etc.

Resources