$urlRouterProvider.when keeps reloading state - javascript

I have just added nested states to my AngularJS application, but I also wanted to add a reroute if the parent state was hit, so I added this code to my UI-router
angular.module('app')
.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.when('/PDGODSTD', '/PDGODSTD/weekinfo');
$stateProvider.state('PDGODSTD', {
//abstract: true, // uncommenting this resolves in an error telling me that I can't navigate to an abstract state
url: "/PDGODSTD",
templateUrl: '../Modules/PDGODSTD/web/index.html'
})
.state('PDGODSTD.weekinfo', {
url: "/weekinfo",
templateUrl: '../Modules/PDGODSTD/web/weekinfo/weekinfo.html',
controller: 'PDGODSTDweekinfoController',
resolve: {
}
})
});
index.html file only contains this piece of code <ui-view><ui-view />
What happens is that the router keep rerouting back and fourth between the parent state and the nested state, or so it seems in my debugger in Chrome.

This simple plunker seems to work: http://plnkr.co/edit/8O7YZY9vBsCW0Wbj6ygU?p=preview
Check if your templateUrl are fetching properly (check network tab).
In ui-router 1.0.0-rc.1 the preferred mechanism to redirect is to use redirectTo:.
The docs for redirectTo are here: https://ui-router.github.io/ng1/docs/latest/interfaces/ng1.ng1statedeclaration.html#redirectto
$stateProvider.state('PDGODSTD', {
redirectTo: 'PDGODSTD.weekinfo',
url: "/PDGODSTD",
templateUrl: '../Modules/PDGODSTD/web/index.html'
})
.state('PDGODSTD.weekinfo', {
url: "/weekinfo",
templateUrl: '../Modules/PDGODSTD/web/weekinfo/weekinfo.html',
controller: 'PDGODSTDweekinfoController',
resolve: {
}
})

The error was in my index.html file. The end tag was wrong it should have been <ui-view></ui-view> rather than <ui-view><ui-view />
Chris' answer is set as the correct one since he showed me that the error wasn't in the logic but somewhere else

Related

Angular Route for specific url

I'm currently working on a MEAN stack project and am trying to get a specific template to display on a specific url.
Currently if users goto www.myurl/catalog, it loads the catalog.html template, as it would with any /catalog?catagory=productType url.
I would like it so that when users go to /catalog?category=specificProductType that it loads the catalogSpecific.html template. Currently, the catalog.html template supersedes the catalogSpecific.html template. I can't find much about this specific issue so any help would be appreciated.
Currently my routes look like this:
app/front/app.js
angular.module('app', ['ngRoute',
'app.LandingModule.controller',
'app.CatalogModule.controller',
'app.ProductModule.controller',
'app.HeaderModule.directives',
'app.FooterModule.directives'
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'html/landing.html',
controller: 'LandingController'
})
.when('/catalog', {
templateUrl: 'html/catalog.html',
controller: 'CatalogController'
})
.when('/catalog?category=specificProductType', {
templateUrl: 'html/catalogSpecific.html',
controller: 'CatalogController'
})
.otherwise({
redirectTo: '/'
});
}]);
EDIT: Seems I was wrong about this not being possible with the default router. As Hadi describes in their comment, you can replace "templateUrl" with a function that returns a template url given the current route.
To my knowledge you cannot route the way that you want to with the built-in angular router.
As far as I can see you have two options to go with from here:
1: Learn to use the ui-router library (found here: https://github.com/angular-ui/ui-router)
2: Send all routes from /catolog to a controller/page that manually looks at your route-params and re-routes you based off of that manually. (see https://docs.angularjs.org/api/ngRoute/service/$routeParams)
Try use templateUrl function like to this. I have not tested.
templateUrl: function($location){
if($location.category)
return 'html/catalogSpecific.html';
else
return 'html/catalog.html';
},
Demo
I was able to figure this out following Hadi's example:
.when('/catalog', {
templateUrl: function($location){
if($location.category == "specificProductType") {
return 'html/catalogSpecific.html';
} else {
return 'html/catalog.html';
}
},
controller: 'CatalogController'
})

Controller loads 2 times if $location.path() changed

I'm facing a distrubing issue with my website. I'm using angular and typescript for development, the problem is : When a user logs in successfully, i'll redirect him to another page like " dashboard" , or "parentDashboard".
If i put a debugger on controller's constructor on parentDashboard or dashboard i see that the breakpoint is hit 2 times. I'm using $location.path('url') to redirect him.
This bug occurs only if i redirect him from login page. If i reload , for example dashboard page, that breakpoint is hit once.
This is the router:
.state('login', {
url: '/login',
templateUrl: '/app/login/login.partial.html',
controller: 'LoginController',
controllerAs: 'vm',
ncyBreadcrumb: {
label: 'Login'
},
.state('dashboard', {
url: '/dashboard',
templateUrl: '/app/dashboard/dashboard.partial.html',
controller: 'DashboardController',
controllerAs: 'vm',
}) //etc.....
NOTE: I don't have data-ng-controller tag in none of the pages. I found that will be a problem for multiple loads.
I don't know how to figure this.
If other sourcecode needed, i'll edit my question. Thanks
function initRouter($locationProvider: angular.ILocationProvider,
$urlRouterProvider: angular.ui.IUrlRouterProvider,
$stateProvider: angular.ui.IStateProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
$urlRouterProvider.otherwise('/');
$stateProvider
Please pay attention on trailing slash using $location.path('url').
$location.path('dashboard/')
may explain such behaviour.

angularjs nested routing doesn't load layout

.state('home', {
url: '/',
templateUrl: 'index.html',
abstract:true
})
.state('home.dashboard', {
url: '/dashboard',
templateUrl: 'dashboard/index.html',
controller: 'dashboardCtrl'
})
I failed to load index.html when I visit example.com/dashboard, I was only able to get the raw html of what is inside dashboard/index.html. That's strange, because in index.html I've declared <ui-view></ui-view> within the body so I expect dashboard/index.html to be a child of index.html.
Pushed a repo of my code.
You don't actually have nested states; you simply have a primary index.html file that serves as the container for your application, its dependencies, and your views. Angular won't load your primary index.html page, the index.html page loads Angular.
So there is no need for your 'home' state to have a templateUrl. You will use nested states if, for example, your dashboard view has an inner view that can load different templates depending on a user action. See Angular UI Router's documentation for some example use cases for nested views.
You can't declare index.html as your firststate like #jakeblues said.
Try to put all the specific content from index.html in a new template :
.state('home', {
url: '/',
templateUrl: 'home.html',
controller: 'homeCtrl'
})
.state('dashboard', {
url: '/dashboard',
templateUrl: 'dashboard/index.html',
controller: 'dashboardCtrl'
})
I downloaded your code from the repo.
The main problem I am seeing is that your angular code is not being loaded when you do example.com/dashboard
app.use(express.static(path.join(__dirname, 'public')));
This makes your public folder as the folder from which the project is being loaded.
When you do example.com, Your angular code is loaded because you are responded with public/index.html file which contains angular code and it is correct.
But when you do example.com/dashboard, it is actually loading html file /public/dashboard/index.html where there is no any angular code.
Try doing alert on dashboardCtrl.js. You will get nothing because it is not being loaded. It is only included in index.html file which is not loaded at all.
Try changeing url to dashboards and remove 'home.dashboard'
.state('dashboard', {
url: '/dashboards',
templateUrl: 'dashboard/index.html',
controller: 'dashboardCtrl'
})

Angular html5mode does not work as expected

In my angular app all the URLs are like this:
testsite.com/#/standard-page
And I would like them to be like:
testsite.com/standard-page
I have read about adding the html5mode to my config, I now have this:
angular.module('myApp').config(['$stateProvider', '$urlRouterProvider', '$locationProvider', config]);
function config($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$stateProvider
.state('index', {
url: '/',
templateUrl: siteInfo.templateRoot + '/startPage.html',
})
.state('standard-page', {
resolve: {
standardPageData: getStandardPageData
},
url: '/standard-page',
templateUrl: siteInfo.templateRoot + '/standardPage.html',
controller: 'StandardPageController',
controllerAs: 'StandardPageCtrl'
});
};
and I added <base href="/"> to the head of my head, but it does not work completely as expected yet.
When I go to testsite.com/#/standard-page in my browser it loads the page, then it modifies the URL to testsite.com/standard-pagein the address bar. However, if I type in directly ``testsite.com/standard-page`, it gives me a 404.
So I'm almost there, just not quite yet. Any ideas what I might have forgotten to do here?
Angular can't do all the job. When you write testsite.com/standard-page, your server must handle the request and respond correctly. Your server respond 404 so your browser can't display anything.

AngularJS relative url routing issue

I have my backend web framework loading my AngularJS app with following URL
http://localhost/New/Alpha/App
I also have it set up so that anything after App will still load the same thing
http://localhost/New/Alpha/App/home
http://localhost/New/Alpha/App/settings
...
I'm trying to make my AngularJS app to work in the way that it would pick up the bit of URL after App and load a controller/template accordingly. I have a problem with routing in my AngularJS app though
var main = angular.module("main", ["ui.bootstrap", "ngRoute"]);
main.config(function($routeProvider, $locationProvider) {
$routeProvider
.when("home", {
templateUrl: "assets/tpl/home.html",
controller: "mainController"
})
.otherwise({
redirectTo: "fail"
});
$locationProvider.html5Mode(true);
});
main.controller("mainController", function($scope) {
console.log("home")
});
If I try this URL
http://localhost/New/Alpha/App/home
it changes the URL to
http://localhost/fail
instead of leaving the URL as it is and loading the template/controller. If however I change the config and give it a full relative URL it does work as supposed to
.when("/New/Alpha/App/home", {
templateUrl: "assets/tpl/home.html",
controller: "mainController"
})
My problem is, that the part of URL before App - /New/Alpha cannot be hardcoded in. It could be /New/Beta, /New/Gamma, etc.
Is what I want to do possible at all without hardcoding the full relative URL match?
UPDATE Sorry, forgot to mention that the number of URL segments before App can change, as in it could be /New/Beta/App and it also could be /New/Another/Beta/App. I don't suppose something like */App or /New/*/App is possible instead of /New/:placeholder/App?
Will this work for you?
var main = angular.module("main", ["ui.bootstrap", "ngRoute"]);
main.config(function($routeProvider, $locationProvider) {
$routeProvider
.when("/New/:greek/App/home", {
templateUrl: "assets/tpl/home.html",
controller: "mainController"
})
.otherwise({
redirectTo: "fail"
});
$locationProvider.html5Mode(true);
});
main.controller("mainController", function($scope) {
console.log("home")
});
You could then retrieve the greek with $routeParams.greek from within your controller.
The general solution to this problem is to have the server pass the app URL to your client-side code. In other words, use server-side code to dynamically write the equivalent of the following on the page:
var appUrl = '/New/Alpha/App';
Then setting up the route provider becomes:
main.config(function($routeProvider, $locationProvider) {
$routeProvider
.when(appUrl + "/home", {
templateUrl: "/assets/tpl/home.html",
controller: "mainController"
})
.otherwise({
redirectTo: appUrl + "/fail"
});
$locationProvider.html5Mode(true);
});
That way the knowledge of the application base URL lives in one place — server-side (which makes sense as only the server is in a position to truly know, if you think about it).
In your specific case, if the application base URL is implicit in the URL structure, you could calculate the following client-side:
var appUrl = window.location.pathname.match(/^\/New\/.*\/App/);
Needs work, but you get the idea. Then you can set up the route provider exactly as above.

Categories

Resources