AngularJs - Routing for Dynamic URL - angularjs

I have the following code for states:
.config(function ($stateProvider, $urlRouterProvider, CONSTANTS) {
$urlRouterProvider.otherwise('/cyo');
$stateProvider.state('pri', {
url: '/pri',
controller: 'priController',
templateUrl: CONSTANTS.PRI_TEMPLATES.PRI_TEMPLATE_URL,
redirectTo: 'pri.size'
}).state('rec', {
url: '/rec',
controller: 'recController',
controllerAs: 'recCtrl',
templateUrl: CONSTANTS.REC_TEMPLATES.REC_TEMPLATE_URL
})
});
The URL is being generated is http://adc.com/REC/1440/#
1440 being a ID that changes depending upon a prod Cat. the template is not loaded with this url. but as soon I add '/rec/' after the current url the template is loaded - http://adc.com/REC/1440/#/rec/ the page loads correctly
I am not able to understand how to get this fixed.
Ayush

You should define the state paramaters when you define the state.
Try this:
.state('rec', {
url: '/rec/:id',
params: {id: 'defaultValue'}, // optional
controller: 'recController',
controllerAs: 'recCtrl',
templateUrl: CONSTANTS.REC_TEMPLATES.REC_TEMPLATE_URL
})
And the html code:
<a ui-sref='rec({id: 123})'>Go to rec</a>

Related

Using ui-view and states

in my app.js folder I have a
$stateProvider
.state('state1', {
url: '/',
templateUrl: 'app/list.html',
controller: 'Ctrl1',
})
.state('state2', {
url: '/details',
templateUrl: 'app/details.html',
controller: 'Ctrl2'
})
.state('state3', {
url: '/list',
templateUrl: 'app/list.html',
controller: 'Ctrl3'
});
At the moment I am calling all of these altogether in index.html using
Is there a way to specify which controller you want displayed in each part of the page. As I'm calling it now it seems that it simply calls everything where it is called in the index.html page which makes it quite hard to organise.

Migrate from ngRoute to ui-router

Needs some guidance with respect to migrating my ngRoute configuration to a ui.router configuration. Currently I have one main template (index.html) and it has an ng-view where all views are injected. My current ngRoute config is as follows:
app.config(function ($routeProvider) {
$routeProvider
.when('/login', {
templateUrl: 'app/views/login.html',
controller: 'LoginCtrl'
})
.when('/contact', {
templateUrl: 'app/views/contact.html',
controller: 'ContactCtrl'
})
.when('/notification', {
templateUrl: 'app/views/notification.html',
controller: 'NotificationCtrl'
})
.otherwise({
redirectTo: '/login'
});
I now want to define a second place in index.html where I can inject some view content - not a nested view, but rather another ng-view (or ui-view in ui-router terminology). The original ng-view section is the default one (currently just for /login and /contact), and the new one is just for specific routes (currently just '/notification' but maybe others in the future). Lets call the new ui-view 'notification-view'.
I've gone through much of the ui-router documentation and still am unsure of how to migrate the above to the new ui.router config. Can someone get me started or point me toward some decent examples?
Update:
Ok, here is where I am. I've adding some states and a new ui-view to my index.html page. See below:
<div class="container">
<div id="header"></div>
<div data-ui-view></div>
<div data-ui-view="notification-view"></div>
</div>
My routing is now:
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/login');
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'app/views/login.html',
controller: 'LoginCtrl'
})
.state('contact', {
url: '/contact',
templateUrl: 'app/views/contact.html',
controller: 'ContactCtrl'
})
.state('notification', {
url: '/notification',
views: {
"notification-view": {
templateUrl: 'app/views/notification.html',
controller: 'NotificationCtrl'
}
}
});
});
This seems to work ok for the most part. When the url /notification is triggered, the app is routed to the NotificationCtrl and renders ui-view content into the notification-view. However the only problem is that the ui content in the main (unnamed) ui-view is lost. I would like whatever is already rendered in the main ui-view to be untouched, and only target the notification-view. Is this possible? Does it have to instead be a nested-view?
When using ui.router, you should think in terms of states rather than routes. So instead of the $routeProvider you instead inject $stateProvider, plan out various states and work from there . So from your example above, we convert it to:
app.config(function ($stateProvider,$urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('login', {
url:'/login',
templateUrl: 'app/views/login.html',
controller: 'LoginCtrl'
})
.state('contact', {
url:'/contact',
templateUrl: 'app/views/contact.html',
controller: 'ContactCtrl'
})
.state('notification', {
url:'/notification',
templateUrl: 'app/views/notification.html',
controller: 'NotificationCtrl'
});
}
There's alot of methods for adding a "sub-view" to uirouter, one method is by adding a child state.
$stateProvider
.state('login', {
url:'/login',
templateUrl: 'app/views/login.html',
controller: 'LoginCtrl'
})
.state('login.error', {
url:'/login',
templateUrl: 'app/views/login-error-subview.html',
controller: 'LoginErrorCtrl'
})
Also as $stateProvider doesnt provide a default state handler, you will also need to inject in $urlRouterProvider. This is a provider that also comes with ui-router that is tasked with the responsibility of watching $location for changes.
The thing with ui-router is that you won't see a huge difference compared to the built-in route provider and ease of use it brings until you start using sub-states and stacked-states.
In your example above, ui.router wouldnt know what templte to use tor the ui-view and thus leaves it empty. You can give it a template and thus becomes:
...
.state('notification', {
url: '/notification',
views: {
'':{
templateUrl: 'app/views/notification-main.html',
controller: ''
}
'notification-view': {
templateUrl: 'app/views/notification.html',
controller: 'NotificationCtrl'
}
}
...
But from what I'm getting you want the login and contact to have the notification in it. So ideally you'd create a notification child state for each, as right now there is now way to declare wildcard or multiple parents for a child-state. Hopefully when v1.0 comes out there'll be support for this use-case already.
Below is a link from the docs that will get you upto speed:
https://github.com/angular-ui/ui-router/wiki/URL-Routing
https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views

Angular Nested states not working as expected

Can someone see why this is not working? /series is not loading the Gallery, however the /series/:id/seasons part is working. (Its not a missing ng-view problem see working code below!)
angular.module('xbmcremoteApp')
.config(function ($stateProvider) {
$stateProvider
.state('series', {
url: '/series',
templateUrl: 'app/series/series.html',
controller: 'SeriesCtrl'
}).state('series.gallery', {
url: '',
templateUrl: 'app/series/series-gallery/series-gallery.html',
controller: 'SeriesGalleryCtrl'
}).state('series.seasons', {
url: '/:id/seasons',
templateUrl: 'app/series/seasons/seasons.html',
controller: 'SeasonsCtrl'
});
});
if i change it to this it works but thats not what i want:
angular.module('xbmcremoteApp')
.config(function ($stateProvider) {
$stateProvider
.state('series', {
url: '',
templateUrl: 'app/series/series.html',
controller: 'SeriesCtrl'
}).state('series.gallery', {
url: '/series',
templateUrl: 'app/series/series-gallery/series-gallery.html',
controller: 'SeriesGalleryCtrl'
}).state('series.seasons', {
url: '/series/:id/seasons',
templateUrl: 'app/series/seasons/seasons.html',
controller: 'SeasonsCtrl'
});
});
EDIT and soltuion:
My post lacked some information. To make that clear: I want to display a gallery when the /seriesurl is called. And i want to display the seasons with the seasons url. No more views!
Found an very easy solution. Setting the abstract property to true forces the stateprovider to use the child view.
....
.state('series', {
abstract:true, //adding this line makes the states work as expected
url: '/series',
templateUrl: 'app/series/series.html',
controller: 'SeriesCtrl'
})
....
In the first definition the url /series is evaluated as a root state 'series'
.state('series', {
url: '/series', // url evaluation will stop here, because
... // there is a match for /series
}).state('series.gallery', { // this will never be reached via url
url: '', // but ui-sref="series.gallery" will work
...
While the second mapping does distinguish both states, and '/series' will navigate to 'series.gallery' state :
.state('series', {
url: '', // url like "#" will navigate there
...
}).state('series.gallery', { // url /series will trigger this child state
url: '/series',
...
In general, if states should be unique by url, each of them should have some defintion. So mostlikely this should be working as inteded:
.state('series', {
url: '/', // url like "#/" will navigate to series
...
}).state('series.gallery', { // url '/series' will trigger this
url: '^/series',
...
check the magical sign: ^:
Absolute Routes (^) (cite:)
If you want to have absolute url matching, then you need to prefix your url string with a special symbol '^'.

UI-Router using routes within a Section of a Site

The site I'm building already has URL's built up using MVC. So for example /Account goes to a page, /Customers goes to a page, and /Quotes goes to a page. On the /Quotes page I have a multi-step wizard which I want to use Ui-Routing on. See my app.js below, this all works.
So my URL becomes /Quotes#newmodel, /Quotes#customer, etc. A different #{value} for each step on the wizard. The problem is that the .otherwise affects all other areas of the site. So if I'm going to /Account, I get the url /Account#wizard. I do not want this to occur anywhere other than on the /Quotes page. Is there anything I can do with the URL matching so I can remove the .otherwise?
'use strict';
var myApp = angular.module('myApp', ['ui.router']);
myApp.config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/wizard");
$stateProvider
.state('wizard', {
url: '/wizard',
templateUrl: 'Scripts/templates/wizardLayout.html',
controller: 'wizardNavigationCtrl'
})
.state('wizard.newmodel', {
url: '/newmodel',
templateUrl: 'Scripts/templates/wizardModel.html',
controller: 'wizardModelCtrl'
})
.state('wizard.other', {
url: '/other',
templateUrl: 'Scripts/templates/wizardOther.html',
controller: 'wizardOtherCtrl'
})
.state('wizard.customer', {
url: '/customer',
templateUrl: 'Scripts/templates/wizardCustomer.html',
controller: 'wizardCustomerCtrl'
})
.state('wizard.shipping', {
url: '/shipping',
templateUrl: 'Scripts/templates/wizardShipping.html',
controller: 'wizardShippingCtrl'
})
.state('wizard.review', {
url: '/review',
templateUrl: 'Scripts/templates/wizardReview.html',
controller: 'wizardReviewCtrl'
});
}]);
I'm also interested in how I can cause the route to load the layout and then by default go to the wizard.newmodel route (though this may be a separate question). Basically the same behavior as if I click on an:
<a sref-ui=".newmodel">
I removed the $urlRouterProvider.otherwise("/wizard") in the app.js.
Instead I added a controller to the main /Quote page that redirects the $location.url to '/wizard'. Below is the code.
myApp.controller('wizardCtrl', ['$location', function ($location) {
$location.url('wizard')
}])

How to make tabs in angularJS have separate controllers?

Right now i am using routeProvider to change between views which works awesome. But now i want to create a view which contains 4 different tabs which should contain 4 different controllers. ive read here that it could be done with stateProvider:
Angular ui tab with seperate controllers for each tab
here is my code:
var WorkerApp = angular.module("WorkerApp", ["ngRoute", 'ngCookies', "ui.bootstrap", "ngGrid", 'ngAnimate', 'ui.router']).config(function ($routeProvider, $stateProvider) {
$routeProvider.
when('/login', {
templateUrl: 'Home/Template/login', resolve: LoginCtrl.resolve
})
.when('/register', { templateUrl: 'Home/Template/register', resolve: RegisterCtrl.resolve })
.when('/', { templateUrl: 'Home/Template/main', resolve: MainCtrl.resolve })
.when('/profile', { templateUrl: 'Home/Template/profile', controller: "ProfileController" })
.when('/contact', { templateUrl: 'Home/Template/contact', controller: "ContactController" })
$stateProvider.state('tabs', {
abstract: true,
url: '/profile',
views: {
"tabs": {
controller: "ProfileController",
templateUrl: 'Home/Template/profile'
}
}
}).state('tabs.tab1', {
url: '/profile', //make this the default tab
views: {
"tabContent": {
controller: "ProfileController",
templateUrl: 'Home/Template/profile'
}
}
})
.state('tabs.tab2', {
url: '/tab2',
views: {
"tabContent": {
controller: 'Tab2Ctrl',
templateUrl: 'tab2.html'
}
}
});
});
but i cant get it really to work because default of routeprovider is set to send over to work because my routeprovider is sending over to "/" on default, which makes "/tabs" invalid. so i cant actully figure out if it is possible to switch to states on specific url. Or change state on specific URL in routeProvider?
I can't tell you for sure exactly what's wrong with the code you've provided, but I'm using Angular UI-Router with the same use case you described, and it's working for me. Here's how I have it configured and how it's different from your configuration:
I don't use $routeProvider at all (none of your $routeProvider.when statements). I'm pretty sure you should not be using $routeProvider since you're using $stateProvider.
I have one use of the $urlRouterProvider with an 'otherwise' statement to specify a default URL:
$urlRouterProvider.otherwise("/home");
My calls to $stateProvider.state is a little different from yours. Here's the one for the parent view of the tabs:
$stateProvider.state('configure', {
url: "/configure",
templateUrl: 'app/configure/configure.tpl.html',
controller: 'ConfigureCtrl'
});
Here's an example of the child state (really the same except for the state name being parent.child format, which you already have in your code; and I added a resolve block but you could have that on the parent as well):
$stateProvider.state('configure.student', {
url: "/student",
templateUrl: 'app/configure/student/configure.student.tpl.html',
controller: 'ConfigureStudentCtrl',
resolve: {
storedClassCode: function($q, user, configureService) {
return configureService.loadMyPromise($q, user);
}
}
});
Also, I'm using version 0.2.8 of Angular UI-Router with version 1.2.9 of Angular. I think this would work with any version of Angular 1.2.0 or later.

Resources