AngularJS: ui-router-tabs selecting a default tab - angularjs

I am currently using the ui-router-tabs (https://github.com/rpocklin/ui-router-tabs) module in my application.
I have got most of it working as I need but I want to select a default tab.
Here is an example of how my states are currently configured (pretty much the way the example is from the site above!):
.state('state', {
url: "/foo/:id/bar",
controller: 'SomeController',
templateUrl: 'pageA.html'
}).state('state.substateA', {
url: "/somepath",
templateUrl: 'partials/pageB.html',
controller: 'SomeOtherController'
}).state('state.substateB', {
url: "/someotherpath",
templateUrl: 'partials/pageC.html',
controller: 'AnotherController'
});
So at present if the url is "/foo/:id/bar" I want to select my first tab by default, is this something I ought to be doing at the controller level, so sniff the current matched state and if equal to "/foo/:id/bar" then trigger another state change manually?
EDIT
OK, so as I was writing the question I came up with a way, but not sure of it's really the angular way of doing it.
So in my controller code I check the current state and set a default sub state accordingly to end up selecting one of my tabs:
if ($state.current.name === 'state') {
$state.go('state.substateA');
}
Does this seem like a sensible approach?

Related

Navigate back to state without reloading template

I have done some research but couldn't find a definitive answer. I have main application area where I load different screens. From one screen I want to open a page that would cover the whole screen. So, navigating to 'viewreport' does exactly that. And when I click on Browser's Back button or have my own Back button on the whole screen page I want to get back to the previous state without reloading its template and controller. Another words, I want to see all selections I have done prior opening the whole screen page. Here is my state configuration:
$stateProvider
.state('body', {
url: '/',
abstract: true,
template: '<div ui-view />'
})
.state('viewreport', {
url: 'viewreport',
templateUrl: 'wholescreen.html',
controller: 'wholescreenController'
});
I am loading different modules into the main 'body' state which might look like this:
function ($stateProvider) {
$stateProvider.state('body.htmlreports', {
templateUrl: function ($stateParams) {
return 'htmlReports.html';
},
controller: 'htmlReportsController',
url: 'htmlreports',
}).state('body.htmlreports.reportarea', {
templateUrl: 'htmlReportParams.html',
controller: 'htmlReportParamsController',
});
I am navigating to viewreport state from htmlReportParamsController controler. The new page then opens into the whole screen. That part works fine. But navigating back to htmlreports when clicking on the Browser's Back button will reload 'body.htmlreports' state. Is there a way of getting back to it without reloading its template?
Update. Why I think it's not a duplicate.
I tried what's suggested in it before posting. This: $state.transitionTo('yourState', params, {notify: false});
still reloads 'yourState'. Also the use case in the provided link is not exactly as mine. Because the OP uses edit mode for already loaded view while I am loading a new view over the the whole screen.
Thanks
Use
$window.history.back();
Add $window in dependency injections of your controller. This will refresh your page and wont reload data we selected.
Please maintain states like this
function ($stateProvider) {
$stateProvider.state('body.htmlreports', {
templateUrl: function ($stateParams) {
return 'htmlReports.html';
},
controller: 'htmlReportsController',
url: 'htmlreports',
}).state('body.htmlreports.reportarea', {
templateUrl: 'htmlReportParams.html',
controller: 'htmlReportParamsController',
}).state('body.htmlreports.reportarea.viewreport', {
url: 'viewreport'
});

Dynamic variable in URL in AngularJS

I have an Angular app which has several dynamic fields, each of these fields are changed updated based on config which comes from a backend database.
In order to control what config is used I need to dynamically switch a single variable - I've decided that the URL is the best way to set/switch the variable as there need to be multiple permutations of the site based on the URL so:-
/:dynamicVariable/
I'm looking for some guidance as to whether this is the best way to do it and what the best way to do it would be? I'm struggling as I don't want to have to set each route for each section like this /:dynamicVariable/homepage /:dynamicVariable/about-us etc etc. Ideally the core module checks it and sets it but the routing ignores it so /:dynamicVariable/ becomes the root.
Hope that makes sense, thanks in advance for your help.
I ended up doing this by using ui.router and nesting states within an abstract parent state which held the client, like so :-
.state('rootClient', {
abstract: true,
url: '/:client',
templateUrl: 'app/layout/layout.html',
controller: 'Layout',
controllerAs: 'layout',
noClient: false,
resolve: {
client: function ($stateParams, ClientService) {
return ClientService.getClient($stateParams.client);
}
}
})
.state('rootClient.home', {
url: '/homepage',
views: {
'content': {
templateUrl: 'app/homepage/homepage.html',
controller: 'Homepage',
controllerAs: 'home'
}
}
});
This way all the routes are under the parent route, I also added a resolve to make sure the client exists before moving to the route. Hopefully this will help someone else down the line.
Cheers

Using $state.params in resolve does not work

I'm currently working on a small application that shows a 'drill down' type of menu. Unlike a TreeView my component only displays the current level.
There are only 3 levels: main, submenu, item. Drilling deeper (on the item) will result in a new state that corresponds to a detail view of the selected item.
I have only 2 states, the first is valid for any of the three levels. The second is the detail state:
$stateProvider.state('menu', {
url: '/menu/:submenu/:item',
templateUrl: 'src/menu/views/menu.html',
controller: 'MenuController',
controllerAs: 'MenuController',
resolve: {
data: function($stateParams, MenuService){
return MenuService.loadUri($stateParams);
}
}
}).state('menu.details', {
url: '/:selectedItem',
templateUrl: 'src/menu/views/menu-details.html',
controller: 'MenuDetailsController',
controllerAs: 'MenuDetailsController',
resolve: {
data: function($stateParams, MenuService){
return MenuService.loadUri($stateParams);
}
}
});
This solutions works correctly, however I'm a bit annoyed by the fact I need to define the resolvemethod twice. I am required to do this as $stateParams contains only the params of that exact state (excluding child states) and I need all parameters to form a valid URL to fetch the corresponding resource via the MenuService.
I know that state.params can be used to get all state params, however it doesn't seem to work in the resolve method: it contains the parameters of the previous state.
Does anybody know how I could fix this? Having a child state that should simply trigger a new view, whilst using the resolve method of the parent state with all state parameters?
If you think I'm completely misunderstanding how states work, then please go ahead and tell me :)

AngularJS multiple routes using JSON data ids

We are new to AngularJS and finding one-or-two problems with setting up multiple routes when using ID's from Json Data.
We are trying to replicate AngularJS Tutorial, so we can click each 'View' button to display a more detailed page of the selected 'Warranty Item' same as the tutorial.
We have uploaded our AngularJS problem to Plunker, If anyone can see something we're missing or know a better route to go down please let us know.
App.js State with ResultSet.JobID
.state('home.singleWarranty', {
url: '/singlewarranty/{resultset.JobID}',
templateUrl: 'singlewarranty.html',
controller: 'warrantyListController'
})
There is a working/updated plunker
Because there are these states
.state('home', {
url: '/home',
templateUrl: 'home.html',
controller: 'homeController'
})
.state('home.singleWarranty', {
url: '/singleWarranty/:jobID',
templateUrl: 'singlewarranty.html',
controller: 'warrantyListController'
})
We need to build the url like this
View
Instead of this original
// View
The point is that state 'home.singleWarranty' inherits/extends the url from its parent. So we have to include the parents '/home' as well.
Other solution:
In case we would like to start the url in a child state from the begining, we can do it like this
.state('home.singleWarranty', {
url: '^/singleWarranty/:jobID',
See the ^ at the url begining. Then even this would work:
View
Check the updated plunker here

Change route path without reloading controller and template in angularjs route

Hi all angularjs developer, I have followed the ng document (link) .I have searched since many times but i did not find any solution that will help me properly. I need to change route without reloading the controller and template. I have written a route that look like this below:-
$routeProvider
.when('/page1', {
templateUrl: 'page1',
controller: 'page1Ctrl',
caseInsensitiveMatch: true,
reloadOnSearch: false
})
.when('/page2', {
templateUrl: 'page2',
controller: 'page2Ctrl',
caseInsensitiveMatch: true,
reloadOnSearch: false
})
.when('/page3', {
templateUrl: 'page3',
controller: 'page3Ctrl',
caseInsensitiveMatch: true,
reloadOnSearch: false
}).otherwise({ redirectTo: '/index' });
Moreover, at first I go to the page1 then page2 then page3 after that now i want to go to the page1 without reloading or calling page1Ctrl and page1 template. Example: suppose when i was page1 that time i have worked something like i have selected an ng-grid record which was paging size 3 and i have inputted some fields. After that i go the page3 then i go to the page1 again. Now this time i want to see the page1 what i selected ng grid record and what i inputted. How can i solve this? Thanks.
I want to suggest to use Angular Ui.router
you will have the ability to change the state of routes , for more check the documentation
To persist data when moving away from a controller and then back again, the recommended Angular approach is to use services. See this NG-Conf talk: https://www.youtube.com/watch?v=62RvRQuMVyg.
To persist input fields and paging index when leaving page1Ctrl and then returning, for example, you could create a pagingModelService.
function PagingModelService($rootScope)
{
var pagingModelService = {};
////////////////////
// persisted data //
////////////////////
pagingModelService.pagingIndex;
pagingModelService.field1;
pagingModelService.field2;
////////
//Init//
////////
return(pagingModelService);
}
Then inject the service in the controller, and set the $scope values to the service:
function Page1Ctrl($scope, pagingModelServiceModel)
{
///////////////////////////////////////////////////
//set local $scope variables to persisted service//
///////////////////////////////////////////////////
$scope.pageIndex = pagingModelService.pagingIndex;
$scope.field1 = pagingModelService.field1;
$scope.field2 = pagingModelService.field2;
}
Also, you can look into angular-local-storage for persisting data: https://github.com/grevory/angular-local-storage

Resources