Angular ui-router with express - javascript

I have set up ui router with the following states:
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/');
$stateProvider
.state('adminprojects', {
url: '/adminprojects',
templateUrl: 'views/adminProjects.html',
controller: 'adminProjectsCtrl'
})
.state('adminprojectsdetails', {
url: '/adminprojects/:id',
templateUrl: 'views/adminProjectsDetails.html',
controller: 'adminProjectsDetailsCtrl'
})
adminprojects view contains a list with ui-sref links. eg
<li><a ui-sref="adminprojectsdetails({id: project.id})" href="/adminprojects/1">Project 1</a></li>
If I click this link for example adminprojects/1 the adminProjectsDetails.html view is shown correctly. However if I refresh this page or navigate directly to this url then the view does not load.
This however works as expected if I have html5 mode set to false;
In express I have this
router.get('/*', function(req, res) {
res.sendfile(__dirname + '/public/index.html');
});
Controller are just pretty much boilerplate for now:
angular.module('jhApp')
.controller('adminProjectsCtrl', function($scope, projects) {
$scope.projects = projects.items;
});
and
angular.module('jhApp')
.controller('adminProjectsDetailsCtrl', function($scope, $stateParams) {
console.log($stateParams);
});
Any ideas why this is not working?

Did you create your project generator-angular ?
If so put <base href="/"/> inside your HEAD above all other elements.
Generator angular create index.html using relative paths for src folders like :
<script src="xxx/yyy.js"/>
When you refresh the page , browser looking for /adminprojects/xxx/yyy.js (.css , *) file which is not found. Because of that you can get lots of script and style errors. Using base tag fixes that problem.
Or simply just change your all src locations to "xxx/yyy." -> src="/xxx/yyy."

Related

AngularJs 1.4.8 remove hash from url

I'm practising a demo application using AngularJs 1.4.8 with backend as core php. Im using linux os. My app files reside inside, var/www/demo/ang/ directory. What I need is, to remove the "#" hash from the url. I approached many examples from internet but the only final result Im getting is that nothing being displayed in the browser. Most of the approaches say to set
<head>
<base href="/" />
</head>
or
<head>
<base href="/var/www/demo/ang/" />
</head>
app.config(function($routeProvider, $locationProvider)
{
$routeProvider
.when('/', {
templateUrl : 'index.html',
controller : indexController
})
.when('/about', {
templateUrl : 'about.html',
controller : aboutController
});
$locationProvider.html5Mode(true);
});
or
app.config(function($routeProvider, $locationProvider)
{
$routeProvider
.when('/', {
templateUrl : 'index.html',
controller : indexController
})
.when('/about', {
templateUrl : 'about.html',
controller : aboutController
});
$locationProvider.html5Mode(
{
enabled:true,
requireBase: false
});
});
Even tried this $locationProvider.html5Mode(true).hashPrefix('!'); . I know that somewhere I'm doing a mistake or forgot to add something. Kindly help me to go through this
UPDATED: Answer Found
https://www.formget.com/angularjs-remove-hashtag/
I made two mistakes
One mistake is that, I set the <base href=""/> as absolute path rather than the relative path of the url. Hence provide the relative path http://www.siteame.com/ or http://localhost/path/to/angularjs_dir/
Second mistake is that, I named the main file which includes all the scripts, ng-view etc.., as some name other than index.html. Hence provide the base file name as index.html.
Rest of this all others were correct.

how to remove hash tag (#) from url address in ui-router

My url looks like this
http://127.0.0.1:50884/index.html#/home
This is index page. I am using angular ui-router to change to various views like but url comes with # tag like this:
http://127.0.0.1:50884/index.html#/mobileOperator
http://127.0.0.1:50884/index.html#/contentExpertise
Question :
Is there a way to remove/clean # tag from url.. to show the url path like below:
http://127.0.0.1:50884/index.html/home
http://127.0.0.1:50884/index.html/contentExpertise
I tried html5mode but it give angular error in console.
Error: [$location:nobase] http://errors.angularjs.org/1.5.0-rc.2/$location/nobase
K/<#http://127.0.0.1:50884/js/angular-v1.5.min.js:6:421
pf/this.$get<#http://127.0.0.1:50884/js/angular-v1.5.min.js:110:96
h/<.invoke#http://127.0.0.1:50884/js/angular-v1.5.min.js:41:293
gb/F<#http://127.0.0.1:50884/js/angular-v1.5.min.js:43:96
d#http://127.0.0.1:50884/js/angular-v1.5.min.js:40:270
e#http://127.0.0.1:50884/js/angular-v1.5.min.js:41:1
h/<.invoke#http://127.0.0.1:50884/js/angular-v1.5.min.js:41:86
gb/F<#http://127.0.0.1:50884/js/angular-v1.5.min.js:43:96
d#http://127.0.0.1:50884/js/angular-v1.5.min.js:40:270
e#http://127.0.0.1:50884/js/angular-v1.5.min.js:41:1
h/<.invoke#http://127.0.0.1:50884/js/angular-v1.5.min.js:41:86
gb/F<#http://127.0.0.1:50884/js/angular-v1.5.min.js:43:96
d#http://127.0.0.1:50884/js/angular-v1.5.min.js:40:270
e#http://127.0.0.1:50884/js/angular-v1.5.min.js:41:1
h/<.invoke#http://127.0.0.1:50884/js/angular-v1.5.min.js:41:86
s/</<#http://127.0.0.1:50884/js/angular-v1.5.min.js:52:121
n#http://127.0.0.1:50884/js/angular-v1.5.min.js:7:364
s/<#http://127.0.0.1:50884/js/angular-v1.5.min.js:52:90
h/<.invoke#http://127.0.0.1:50884/js/angular-v1.5.min.js:41:293
e/<#http://127.0.0.1:50884/js/angular-v1.5.min.js:38:458
h/<.invoke#http://127.0.0.1:50884/js/angular-v1.5.min.js:41:293
gb/F<#http://127.0.0.1:50884/js/angular-v1.5.min.js:43:96
d#http://127.0.0.1:50884/js/angular-v1.5.min.js:40:270
K#http://127.0.0.1:50884/js/angular-v1.5.min.js:71:447
la#http://127.0.0.1:50884/js/angular-v1.5.min.js:60:266
R#http://127.0.0.1:50884/js/angular-v1.5.min.js:58:229
R#http://127.0.0.1:50884/js/angular-v1.5.min.js:58:397
R#http://127.0.0.1:50884/js/angular-v1.5.min.js:58:397
N#http://127.0.0.1:50884/js/angular-v1.5.min.js:56:263
Ac/c/</<#http://127.0.0.1:50884/js/angular-v1.5.min.js:21:99
sf/this.$get</m.prototype.$eval#http://127.0.0.1:50884/js/angular-v1.5.min.js:140:363
sf/this.$get</m.prototype.$apply#http://127.0.0.1:50884/js/angular-v1.5.min.js:141:83
Ac/c/<#http://127.0.0.1:50884/js/angular-v1.5.min.js:21:57
h/<.invoke#http://127.0.0.1:50884/js/angular-v1.5.min.js:41:293
Ac/c#http://127.0.0.1:50884/js/angular-v1.5.min.js:20:1
Ac#http://127.0.0.1:50884/js/angular-v1.5.min.js:21:274
de#http://127.0.0.1:50884/js/angular-v1.5.min.js:20:83
#http://127.0.0.1:50884/js/angular-v1.5.min.js:306:372
n.Callbacks/i#http://127.0.0.1:50884/js/jquery-2.2.1.min.js:2:27060
n.Callbacks/j.fireWith#http://127.0.0.1:50884/js/jquery-2.2.1.min.js:2:27828
.ready#http://127.0.0.1:50884/js/jquery-2.2.1.min.js:2:29619
J#http://127.0.0.1:50884/js/jquery-2.2.1.min.js:2:29804
"
Please help
By default, AngularJS will route URLs with a hashtag.
It is very easy to get clean URLs and remove the hashtag from the URL using $locationProvider in AngularJS.
You need to inject $locationProvider into your config section of module and use the HTML5 History API like this.
e.g.
app.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'partial-home.html'
})
.state('about', {
url: '/aboutus',
templateUrl: 'aboutus.html'
});
$locationProvider.html5Mode(true);
});
Also don't forget to put a <base href="/"> tag inside index.html section.
In order for html5 mode to work you must define a baseurl like:
<base href="whatever/" />
See w3schools for more information: http://www.w3schools.com/tags/tag_base.asp

Routing to non-Angular pages within Angular

I am converting a large server rendered app to use Angular. Because of the size, we are doing it a bit at a time. During this conversion period, part of the app will use Angular and part will not. This means that routing sometimes will route within the Angular app and sometimes it will need to transition from old world to new world (easy) or new world to old world (harder).
Ideally, I would like to specifically route some page transitions within the Angular app (new world) to the proper controllers but then any other page transitions should just fetch new HTML pages (old world).
I can't seem to figure out how to do this. I think I need to use the routeProvider and when / otherwise, but there isn't a lot of documentation that I found which is helpful.
You can't use routeProvider for the old world, since angular routes only direct you within the actual same page.
You could make a placeholder angular route for each legacy route, then in the controller, inject $window and do something like:
$window.location.href = destinationUrl;
Something like: (go to the old world on logout)
app.controller('LogoutCtrl', function ($scope, $window) {
var destinationUrl = 'https://mywebsite.com/';
$window.location.href = destinationUrl;
});
Vice versa, to go back to the angular world, just use a normal link to your angular route:
Link
If you want a catch-all route to redirect to the outside, you can do the following:
otherwise({
controller: 'NotFoundCtrl'
});
...
app.controller('NotFoundCtrl', function($scope, $location, $window) {
var path = $location.path();
$window.location.href="http://test.com" + path;
})
As triggerNZ said, you can always have a controller redirect unhandled routes to the outside. Here is the HTML and Javascript showing how to do it.
HTML
<div ng-app="myApp">
<script type="text/ng-template" id="this.html">
This Page.
</script>
<script type="text/ng-template" id="that.html">
That Page.
</script>
<div>
<ul>
<li>This</li>
<li>That</li>
<li>Other</li>
</ul>
<ng-view></ng-view>
</div>
</div>
Javascript
var app = angular.module("myApp", ['ngRoute']);
app.config(function ($routeProvider, $locationProvider) {
$routeProvider.when('/this', {
templateUrl: 'this.html'
}).when('/that', {
templateUrl: 'that.html'
}).otherwise({
template: "<div></div>",
controller: function ($window, $location, $rootScope) {
if (!$rootScope.isInitialLoad) {
$window.location.href = $location.absUrl();
}
}
});
$locationProvider.html5Mode(true);
});
app.run(function ($rootScope) {
$rootScope.$on('$routeChangeSuccess', function() {
$rootScope.isInitialLoad = (typeof $rootScope.isInitialLoad === "undefined");
});
});

Angular JS Routing - Links inside SPA

I have created a project with index.html with certain links to other pages. My routing works as intended but I'm wondering what's the best approach to go with when it comes to links on other pages.
To clarify it:
My index.html page has routes:
Feed
Bblog
Marketplace
Recruiting
Adverts
Now what I'm curious about is how do I for example route links inside these pages.
For example, my Bblog page has tabs which I want to be opened inside the same page. Now for example whenever I click some tab link, it redirects me to my index.html since my .otherwise route is set to /.
Not sure what engine or library you're using for your routing. Though I faced the same requirement not too long ago.
We're using ui-router for our routing. It's very similar to Angulars routing.
A snippet from our routing table contains something similar to this.
$stateProvider
.state('home', {
url: '/',
templateUrl: '/views/index',
})
.state('orders', {
url: '/orders',
templateUrl: '/views/orders',
})
.state('orderdetail', {
url: '/orders/detail/:id',
templateUrl: '/views/orderdetail',
})
.state('orderdetail.address', {
url: '/:addressId',
templateUrl: '/views/orderdetail',
})
Essentially you use the .dot notation to separate nested views. So the orderdetail.address is nested inside the orderdetail
This means that the routing above will go something allow you to see an overview of order details at /orders/detail/myOrderId and drill further in to, say, an address by visiting /orders/detail/myOrderId/myaddressId
If you're using ui-router then you will get more info on nested views on this link
If you're using angular ngRoute then the [ngRoute][3] docs and supporting plunker demonstrate how to stack up the routes.
So (from the plunker) -
.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/Book/:bookId', {
templateUrl: 'book.html',
controller: 'BookController',
resolve: {
// I will cause a 1 second delay
delay: function($q, $timeout) {
var delay = $q.defer();
$timeout(delay.resolve, 1000);
return delay.promise;
}
}
})
.when('/Book/:bookId/ch/:chapterId', {
templateUrl: 'chapter.html',
controller: 'ChapterController'
});
this will give you /book/myBookId and /book/myBoodId/ch/myChapterId

Flexible routing and 'passing through' certain URLs?

I have a Django web application serving an Angular JS client application.
My URL tree looks like this:
> /
> /admin/
> /login/
> /logout/
> /static/
> /admin/
My Angular application's base URL is /admin/, and its static content lives in /static/admin/(js|css|views).
Here's the configuration for the route provider:
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/admin/', {
controller: 'IndexController',
templateUrl: '/static/admin/views/index.html'
}).otherwise({ redirectTo: '/admin/' });
});
app.config(['$locationProvider', function($locationProvider) {
$locationProvider.html5Mode(true);
});
I have a few problems here. The first problem is URL flexibility. What if I decide to move my base URL to something like /angularadmin/? I'll have to rewrite a lot of JavaScript and a lot of <a> links. The second problem is that when
I provide a link to /logout/, this link hits the otherwise clause and redirects back to /admin/.
How do I tell Angular to pass through links to /logout/ and how can I make configuration of the base URL here much more flexible?
You should always have your base path in configuration and then use that when you need to specify the URL.
Here is an example:
// Define the configuration
app.constant('config', {
serviceRoot: '/api/',
staticRoot: '/static/admin/',
appRoot: '/admin/'
});
//Use the configuration
app.config(['$routeProvider', 'config', function ($routeProvider, config) {
$routeProvider
.when(config.appRoot, {
controller: 'IndexController',
templateUrl: config.staticRoot + 'views/index.html'
})
.otherwise({ redirectTo: config.appRoot });
}]);
UPDATE:
As stated in the comments in order to open an external link use target="_self".
If you need the configuration values in the views/templates you can inject the configuration object in the $rootScope and access it from the views:
// We add the configuration as part of the root scope
app.run(['$rootScope', 'config', function($rootScope, config) {
$rootScope.appConfig = config;
}]);
Then you can use it in the view like this:
<a ng-href="{{appConfig.appRoot}}someroute/">...</a>
Step 1. update your base tag in your angular application progmatically so that if you move your angular application, you don't have to change your code.
in index.html - <script src='setbase.js' />
var baseTag = document.createElement('base');
var base = document.location.href;
//console.log('Detecting Document Base: ',base);
// remove query parameters and anchors
base = base.replace(/\#.*/,'').replace(/\?.*/,'');
//console.log(' Removing Anchors and Query Parameters: ',base);
// remove documents, leaving only path
base = base.replace(/\/?[^\/]]*$/,'/');
//console.log(' Removing Documents: ',base);
baseTag.href = base;
document.head.appendChild(baseTag);
document.scripts[document.scripts.length-1].remove();
step 2: setup angular to use hash tags in html5 mode so that it rewrites anchor links. Include this module and then in your own module configire this module as a dependency.
(function(window,angular)
{
'use strict';
var module;
module = angular.module('aLinkRewrite',[]);
module.config
(
[
'$provide','$locationProvider',
function (p,lp)
{ // (decorator is undocumented... *sigh*)
p.decorator( // decorate the
'$sniffer', // sniffer service
[
'$delegate', // obtain a delegate object to modify the sniffer
function(d) // which we will call 'd'
{
d.history = false; // tell angular that we don't have html5 history capabilities
return d;
}
]
);
lp.html5Mode(true); // turn on html5 mode link rewriting
}
]
).run(['$location',function($location){}]); // inject $location into the browser
})(window,window.angular);
From now on, all of your routes and links in angular do not include your base. If angular is located in '/admin/index.html', then your route for '/admin/' is now just '/'
All of your angular links in html can be referenced as <a href="whatever">, and they will directed to admin/whatever because of the base tag, and show up in the browser bar as admin/#/whatever
because your static content is outside of your base, you continue to link to it as /static/whatever. This is also true with your login and logout links.

Categories