Angular HTML5 mode routing gives he resource cannot be found - javascript

I'm developing an application in .net mvc with angularjs. When I don't use html5 mode it works fine, but when I set html5 mode to true the server calls that address giving me an he resource cannot be found.
This is my app.js
var app = angular.module("myApp", ['ngRoute'])
.config(function ($routeProvider, $locationProvider) {
$routeProvider.when('/test',
{
templateUrl: 'templates/TestPage.html',
controller: 'ProfesionalController'
});
$routeProvider.otherwise({ redirectTo: '/' });
$locationProvider.html5Mode(true);
});
And this is my view (layout):
<!DOCTYPE html>
#Scripts.Render("~/bundles/modernizr")
<script src="~/Scripts/angular/angular.js"></script>
<script src="~/Scripts/angular/angular-route.js"></script>
<script src="~/app/app.js"></script>
<script src="~/app/home/home.js"></script>
<script src="~/app/profesional/profesional.js"></script>
<base href="/">
Test
#*this is the link*#
</div>
</div>
</div>
<div ng-app="myApp" class="container body-content">
<div ng-view></div>
#RenderBody()
</div>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
When I click to test link the server try to locate:
http://localhost:39881/test" giving me an 404 Not Found - http://localhost:39881/test"
What I'm missing. It works well with no html5 mode.

Even I was facing the same issue when I was trying to enable html5 mode in my application. Later when I saw the entire code carefully, I came to know the name of my API call and my route call were same. The browser was getting confused and instead of calling route call it was calling the api call.
Try changing either of the name. It should work fine.

You need to configure your server side rewrites so it doesn't try to load up pages at that path. See details for your server type here: https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode

Something that cost me a lot of time that hopefully will help others if you are using Azure and a pure ng app:
I am using Azure and Angular and hit the same problem. I had the IIS Rewrite rules to redirect all requests to the index.html file as per the documentation in ng.
However, it still was not working on production, only on local. It turned out to be a stupid user error - my Angular webapp is a pure HTML/JS app (ie. no ASP.NET MVC) and the Azure Publishing Profile had not marked the web.config for dpeloyment to the cloud. I used Kudu on Azure to check the webapp and there was no web.config on live, hence the rewrite rules were not being considered... changing it to FileType Content solved the issue so the web.config was deployed correctly and the routing now works..

Related

Adding office.js adds # in the url, then removes it

I have a mean-stack web site. Initially, views/index.html (having <ui-view></ui-view>) is the entry point of all the pages. It uses angular-ui-router and html5mode. Thus, https://localhost:3000/XXXX in a browser will remain the same (rather than adding #) and show the corresponding content based on the router.
Then, I want the server to serve also an Office add-in. I will need views/addin.html that contains office.js and another router, such that the site serves a set of urls https://localhost:3000/addin/XXXX, and I don't mind if it is html5mode or not (a url can contain # somewhere).
So here is the correpsonding of routes/index.js:
router.get('/addin/*', function (req, res) {
console.log("router.get /addin/*");
res.sendfile('./views/addin.html')
});
router.get('*', function(req, res) {
console.log("router.get *");
res.sendfile('./views/index.html');
});
And here is views/addin.html:
<html>
<head>
<title>F-addin</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.2/angular-ui-router.js"></script>
<!--<script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>-->
<base href="/" />
</head>
<body ng-app="addinF">
addin content
<ui-view ng-cloak></ui-view>
</body>
<script>
var addinApp = angular.module('addinF', ['ui.router'])
addinApp.config(['$stateProvider', '$locationProvider', function ($stateProvider, $locationProvider) {
$stateProvider
.state('addinNew', {
url: '/addin/new',
template: "new page"
})
.state('addinHome', {
url: '/addin/home',
template: "home page"
})
$locationProvider.html5Mode(true);
}]);
</script>
</html>
When office.js is commented as above, https://localhost:3000/addin/new and https://localhost:3000/addin/home in a browser work well. However, when office.js is uncommented, there is an odd behavior: typing https://localhost:3000/addin/new in a browser will change to https://localhost:3000/#/addin/new, then change back to https://localhost:3000/addin/new. And we will see addin content new page appear once and disappear.
With office.js uncommented, if we load a manifest file with <SourceLocation DefaultValue="https://localhost:3000/addin/new"/>, we will see also in the task pane addin content new page appear once and disappear, and then Add-in Error Something went wrong and we couldn't start this add-in. Please try again later or contact your system administrator.
Without html5mode here, .../addin/new or .../addin/home in a browser will only show addin content; the add-in can be loaded, with only addin content too.
My goal is to make an add-in pointing to .../addin/new or .../addin/home work. office.js has to be loaded somewhere. I don't mind if it is html5mode (ie, the url has #), but the behavior in either way is odd or unsatisfactory. Does anyone know how to fix it or have a workaround?
Looking at the debug version of the office.js file:
https://appsforoffice.microsoft.com/lib/1/hosted/office.debug.js
You'll see that the window's history replaceState and pushState functions are set to null:
window.history.replaceState = null;
window.history.pushState = null;
Which disables the ability to manipulate the browser's history and it seems it has Angular thinking the history API is not available, so Angular falls back to hashtag navigation.
In the office.js minified version you can find these two lines by looking for:
window.history.replaceState=e;window.history.pushState=e;
You could remove these two lines of code to re-enable html5mode, but i'm not sure if the office.js plugin will keep working properly.

Angular UI Router: ui-sref does not render render the page I'm trying to route to, but it appears in my dev tools

I've been banging my head against the problem for embarrassingly long now. I'm using Angular UI Router to handling the routing in a small personal project I'm working on, and I have a strange issue. I have a VERY simple HTML file:
<head>
<title>MY FUN EXCITING PROJECT</title>
<script src='node_modules/angular/angular.min.js'></script>
<script src='node_modules/angular-ui-router/release/angular-ui-router.min.js'></script>
<script src='app.js'></script>
<script src='routes.js'></script>
<script src='dist/auth/authenticationController.js'></script>
<script src='dist/auth/authenticationFactory.js'></script>
</head>
<body>
<H1>I AM A FILE. HELLO.</H1>
<a ui-sref='login'>CLICK ME</a>
</body>
And, again, a VERY simple route provider file:
(function () {
'use strict';
angular.module('project',['ui.router'])
.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('login', {
url: '/login',
templateUrl:'dist/auth/authentication.html'
});
}])
})();
And the authentication.html file is literally just a I AM AN AUTHENTICATION PAGE right now.
What's happening is that clicking on the link will cause the address in the address bar to change properly, but the template itself won't render. If I look in the dev tools, though, the page is being sent back from the response (screenshot attached).
I'm using a basic barebones node server to run the server for this, and using
app.use(express.static(__dirname+'/public'));
to serve all the files. Is there something basic I'm missing? I'd infinitely appreciate any help. Thank you!

ng-view won't display template

I have been working a bit with Angular and I tried to implement simple routing.
I have a basic HTML which contains reference to all the required scripts and a ng-view tag.
For some reason, when the page is loaded, the template isn't shown in the ng-view location. Why isn't it shown, and how to fix it?
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular-route.js"></script>
<script src="routCtrl.js"></script>
</head>
<body ng-app='ngRouteTest'>
<div ng-view></div>
</body>
and the the script file:
var ngRouteTest = angular.module('ngRouteTest',['ngRoute']);
ngRouteTest.config(function($routeProvider){
$routeProvider
.when('/',
{templateUrl : '/routView1.html'})
});
You need to redirect to that page so that routing will come to know which page to render inside ng-view directive.
There are multiple ways to do it.
Define one more otherwise to redirect to /.
$routeProvider.otherwise({redirectTo: '/'})
Add anchor to page that will redirect to /.
<body ng-app='ngRouteTest'>
Home Page
<div ng-view></div>
</body>
Having default url on page in <head> tag.
<base href="/"/>
Okay first you need to run your code from a server, so to test it locally use http-server which is really easy to prepare.
Then you will need to change your templateUrl path from:
{templateUrl : '/routView1.html'}
to:
{templateUrl : './routView1.html'}
After starting a local host and ruining the code from there it worked perfectly fine.
The issue was with the chrome related security when you make local ajax calls.
So one has this problem should do one of the following things:
1.Disable web-security in chrome.
2.Start a local host to test.

Throwing cannot get error after enabling html5Mode in AngularJS

I am using UI-Router for routes/states in my app and URLs were having "#" so to remove this , I used $locationProvider like -
function configState($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode(true);
Added ngRoute in module dependency and added <base href="/" > in my index.html.
Problem -
If I am using it as a normal app like in same tab and navigates to other state, it works BUT whenever I pasted the URL in another tab and hit enter its throwing Cannot GET /app_views/contacts URL is like - http://localhost:9000/app_views/contacts
Though with hash in URL it works in both way manner.
You are likely getting this error because your server is not configured correctly. In other words when you manually enter /app_views/contacts it will make a request to the server for that page. For this to work properly you need configure your server to route all traffic to your index.html page in order for Angular to properly take over and display the correct view.
Here is a related post Reloading the page gives wrong GET request with AngularJS HTML5 mode

Why AngularJS routes are not working in local?

I have html file which implements AngularJS routes as follows,
index.html:
<!DOCTYPE html>
<html ng-app="demo">
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div ng-view>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
<script src="http://code.angularjs.org/1.2.1/angular-route.min.js"></script>
<script>
// Code goes here
var demo = angular.module('demo', ['ngRoute']);
demo.config(function($routeProvider){
$routeProvider.when('/', {
controller: 'testController',
templateUrl: 'test.html'
})
})
var controllers = {};
controllers.testController = function($scope){
$scope.first = "Info";
$scope.customers=[
{name:'jerry',city:'chicago'},
{name:'tom',city:'houston'},
{name:'enslo',city:'taipei'}
];
}
demo.controller(controllers)
</script>
</body>
</html>
test.html:
<div>
<input type="text" ng-model="name"/>
</br>
{{first}}
</br>
<ul>
<li ng-repeat="cust in customers | filter:name">{{cust.name | uppercase}} - {{cust.city}}</li>
</ul>
</div>
You can find the working version here
But why is it not working when I run the same in my local browser :(
Here is the chrome console error:
Any help appreciated! :)
It is important to make it clear. For security reasons, Chrome (for example) won't allow you to load local files (ie: the templates for your views). My suggestion is to set up a web server to test your applications:
Use the free edition of the Visual Studio Express for web development.
Use gruntjs to quickly set up your project.
Alternatively you can use inline templates in place of loading it externally, but it does not seems to be a good practice.
Edit:
Using the console error print that you posted, Chrome is blocking your ajax request. You can bypass this restriction using a command line argument:
chrome.exe --allow-file-access-from-files
However I would encourage you to set up a simple local web server, It will prevent you for some headaches while your are learning...
You can use Firefox for test. Route and ajax will work.
But it is better to set up a web server like #gustavodidomenico said
the work around to make ng-view work in local is to put the content of other htmls in the script tag as
<script type="text/ng-template" id="index22.html">
This is index 2 template.
</script>
<script type="text/ng-template" id="index33.html">
This is index 3 template.
</script>
in the same HTML from where the call is being made.
ngview makes an AJAX call to load the content of external HTMLs or seperate HTMLs , chrome does not allow AJAX call for local resources , IE 11 also shows 'Access is denied' error message.
when including in script tags , this AJAX call is not made.
There is a Chrome Extension called Web Server for Chrome. you can add it and then lunch it, in browse dialog choose your working folder, then it gives you a Local URL, you can test your app there.

Categories