Nested child state with ui-router - javascript

As I'm working on an Angular app, I was wondering about ui-route nested states.
As said in the docu, it's possible to create nested state such as (taken from the doc) :
$stateProvider
.state('contacts', {
templateUrl: 'contacts.html',
controller: function($scope){
$scope.contacts = [{ name: 'Alice' }, { name: 'Bob' }];
}
})
.state('contacts.list', {
templateUrl: 'contacts.list.html'
});
But is it possible to create a granchild state ? (possibly by adding something like) :
.state('contacts.list.state', {
templateUrl: 'html_file.html'
)}

Yes, you can do it like that, as you suggested. EG:
$stateProvider
.state('contacts', {
url: '/',
templateUrl: 'contacts.html',
controller: function($scope){
$scope.contacts = [{ name: 'Alice' }, { name: 'Bob' }];
}
})
.state('contacts.list', {
url: ':list',
templateUrl: 'contacts-list.html'
})
.state('contacts.list.fullDetails', {
url: '/fullDetails',
templateUrl: 'contacts-list-full-details.html'
});

Related

How to consolidate code into one file for same feature on all views using angularjs?

I was using 4 different views and four different controller for some thing similar in each $state , only data source socket.io is different so i tried to consiladated into one view and controller. but i am not getting searchEnv and states loaded.
Any idea how can i fix this issue ?
app.js
$stateProvider
.state('app', {
abstract: true,
url: '',
templateUrl: 'web/global/main.html',
controller: 'MainCtrl'
})
.state('app.home', {
url: '/',
templateUrl: 'view/home.html',
controller: 'MainCtrl'
})
.state('app.dit', {
url: '/:type',
templateUrl: 'view/partials/dit.html',
controller: 'DitCtrl'
})
.state('app.st', {
url: '/:type',
templateUrl: 'view/partials/dit.html',
controller: 'DitCtrl'
})
.state('app.uat', {
url: '/:type',
templateUrl: 'view/partials/dit.html',
controller: 'DitCtrl'
})
.state('app.prod', {
url: '/:type',
templateUrl: 'view/partials/dit.html',
controller: 'DitCtrl',
});
});
DitCtrl.js
var searchEnv = $stateParams.type;
$scope.event = [];
socket.on(searchEnv + 'Consumer', function(data) {
var obj = {
file: $scope.filename,
data: data
}
var messageSize = getBytesForBuffer(data);
$scope.event.push(data);
});
mainCtrl.js
$scope.tabs = [{
heading: 'Home',
route: 'app.home',
active: true
},
{
heading: 'DIT',
route: 'app.dt({type: '
dt '})',
active: false
},
{
heading: 'ST',
route: 'app.st({type:'
st '})',
active: false
},
{
heading: 'UAT',
route: 'app.uat',
active: false
},
{
heading: 'LSP',
route: 'app.lsp',
active: false
}
];

How to navigate from a login state to an abstract dashboard state?

https://plnkr.co/edit/ByatrCzdUJfAV3oc8XPq?p=preview
^ On line 10, if you put back in the abstract:true key you will see the tags view appear in this plnkr app.
However my problem is that in my real app it won't let me use the abstract key because you first start at a login state and then transition to the dashboard state.
And the abstract key allows me to add the additional tags state as a child of dashboard.
When I have that key in there and I login in my real app this is the error I get:
Error: Cannot transition to abstract state 'dashboard'
Plnkr code:
var dash = {
name: 'dash',
url: '/dash?ticker',
// abstract: true,
views: {
'': { templateUrl: 'dashboard.html' },
'tickersList#dash': {
templateUrl: 'tickers-list.html',
controller: 'tickersController'
},
'alertsList#dash': {
templateUrl: 'alerts-list.html',
controller: 'alertsController'
}
}
};
var tags = {
name: 'dash.tags',
url: '?ticker',
params: {
ticker: 'AAA'
},
views: {
'tagsList#dash': {
templateUrl: 'tags-list.html',
controller: 'tagsController'
}
}
}
$stateProvider
.state(dash)
.state(tags);
Real app
LoginController:
$state.go('dashboard')
STATE_CONSTANTS:
dashboard state object:
.constant('STATE_CONSTANTS', {
dash: {
name: 'dashboard',
// abstract: true,
url: `/dashboard?ticker?start_epoch?end_epoch?timespan?group?sort?term_id_1?term_id_2?term_id_3?social?stream?links?retweets?tags_open?feed_open?chart_alerts?chart_max`,
views: {
'': {
templateUrl: 'dash/dashboard_container.html',
controller: function(UserFactory, container, user) {
this.container = container;
UserFactory.storeUser(user);
},
controllerAs: 'dc',
bindToController: true,
resolve: {
user: (AuthFactory) => AuthFactory.check_login(),
settings: (user, UserFactory) => UserFactory.settings(user),
container: ($stateParams, TagsFactory) => TagsFactory.createTerms($stateParams)
}
},
'platformHeader#dashboard': {
templateUrl: 'headers/platform/platform_header.html',
controller: 'PlatformCtrl',
controllerAs: 'ph'
},
'timespanHeader#dashboard': {
templateUrl: 'headers/timespan/timespan_header.html',
controller: 'TimeHeaderCtrl',
controllerAs: 'thc'
},
'tickersPanel#dashboard': {
templateUrl: 'tickers/panel/tickers_panel.html',
controller: 'TickersPanelCtrl',
controllerAs: 'tikp'
},
},
params: {
ticker: '',
},
data: { authorizedRoles: ['All'] }
},
login state object:
login: {
name: 'login',
url: '/login',
templateUrl: 'auth/login.html',
controller: 'LoginCtrl',
data: { authorizedRoles: ['All'] }
}
dashboard.html template
<div>
<header>
<div ui-view="platformHeader"></div>
<div ui-view="timespanHeader"></div>
</header>
<aside>
<!-- the headers and tickersPanel are all child states of
dashboard state -->
<div ui-view="tickersPanel"></div>
<!-- tags is a seperate state from dashboard -->
<div ui-view="tagsPanel"></div>
</aside>
//...
app.js
$stateProvider
.state(STATE_CONSTANTS.login)
.state(STATE_CONSTANTS.password)
.state(STATE_CONSTANTS.passwordreset)
.state(STATE_CONSTANTS.settings)
.state(STATE_CONSTANTS.settingsDefault)
.state(STATE_CONSTANTS.settingsAlerts)
.state(STATE_CONSTANTS.dash)
The behavior is right. You cannot transit to abstract state. Look at your example from plunker.
var dash = {
name: 'dash',
url: '/dash?ticker'
var tags = {
name: 'dash.tags',
url: '?ticker',
You have an abstract state "dash" and you have a child state "dash.tags" which is not abstract. So you can transit only to child state.
In your app, you try transiting to an abstract state which is not possible.
Abstract states are used if you want to have some basic state with common behavior (parent state). You cannot transit to such states but they can have some basic template, resolve functions... So, you have to remove abstract flag or create a child state.

Angular UI-Router doesn't match a defined state

I'm using UI-Router module for routing. I have 2 states that router should match the urls with them :
// Dashboard
.state('dashboard', {
url: "/dashboard",
templateUrl: "dashboard/views/index.html",
controller: "DashboardController",
...
})
// Users
.state('users', {
url: "/users",
templateUrl: "users/views/index.html",
controller: "UsersController",
...
})
// Single User
.state('users.id', {
url: "/{id:^[a-z0-9_-]{3,16}$}",
templateUrl: "users/views/show.html",
controller: "UserController",
...
})
also I have set a default route :
$urlRouterProvider.otherwise("/dashboard");
I want the router to match users state when I go to http://127.0.0.1:8000/app/#/users
and to match user state when I go to http://127.0.0.1:8000/app/#/users/testuser
Problem :
the users state works good, but the user state url doesn't get matched and redirects to the default state. What's the problem?
There is a working example
Try to use this regex def:
.state('users.id', {
url: "/{id:(?:[a-z0-9_-]{3,16})}",
These links will work
<a href="#/users">
<a href="#/users/testuser">
This will go to otherwise
<a href="#/users/xx">
Some inspiration could be found here
In case, we want to go to state 'users.id' directly, we just have to use proper call. In this extended plunker, we can see that it could be done like this:
// working
<a ui-sref="users">
<a ui-sref="users.id({id:'testword'})">
// not working - id does not fit - otherwise is used
<a ui-sref="users.id({id:'not-working simply too long'})">
The same would be with $state.go('users.id', {id:'testword'})
Check it here
Here is an example of how I've done it in the past. Maybe it will help you.
app.config(['$stateProvider', '$urlRouterProvider',
function ($stateProvider, $urlRouterProvider,$rootScope,$cookieStore) {
$urlRouterProvider.otherwise("/login");
$stateProvider
.state('login', {
url: '/login',
title: 'Login',
templateUrl:'views/loginView.html',
controller: 'loginCtrl',
resolve: resolver($rootScope),
})
.state('account', {
url: '/account',
title: 'My Account',
accessLevel: 2,
resolve: resolver($rootScope,$cookieStore),
views: {
'navigation': {
templateUrl: 'views/navigationView.html',
controller: 'navigationCtrl'
},
'content': {
templateUrl: 'views/contentView.html',
controller: 'navigationCtrl'
}
}
})
.state('account.dashboard', {
url:'/dashboard',
title: 'Dashboard',
views : {
'pageContent': {
templateUrl:'views/dashboardView.html',
controller: 'dashboardCtrl'
}
}
})
.state('account.foo', {
url:'/foo',
title: 'foo',
views : {
'pageContent': {
templateUrl:'views/foo.html',
controller: 'fooCtrl'
}
}
})
.state('account.maps', {
url:'/maps',
title: 'Maps and stuff',
views : {
'pageContent': {
templateUrl:'views/mapsView.html',
controller: 'mapsCtrl'
}
}
})
}])

Angular, Item Details

I'm learning angular (with ionic framework, includes phone gap)and I am trying to create a single app that lists some data and when you click on one it show details for it. I was able to list all the item but I can't manage how to show details for a single one. I know the issue probably has to do with $routeParams but I can't find what is wrong.
app.js
angular.module('app', ['ionic', 'app.controllers'])
.config(function($stateProvider, $urlRouterProvider, $routeProvider) {
.state('app.list', {
url: '/list',
views: {
'menuContent' :{
templateUrl: "templates/list.html"
}
}
})
.state('app.staff', {
url: '/staff/:staffid',
views: {
'menuContent' :{
templateUrl: "templates/staff-details.html",
controller: 'StaffDetailsCtrl'
},
}
})
});
controllers.js
.controller('FooCtrl', function($scope) {
$scope.staff = [
{ id: 1, name: 'Jim', color: 'red' },
{ id: 2, name: 'Bob', color: 'blue' },
{ id: 3, name: 'Peter', color: 'yellow' }
/*... etc... */
];
});
// Review Controller
.controller('StaffDetailsCtrl', function($scope, $routeParams) {
// Get staff
alert('yeeeees');
var id = $routeParams.staffid;
$scope.staff = $scope.staff.get(id);
});
staff-details.html
{{staff.id}}<br />
{{staff.name}}<br />
{{staff.color}}
UPDATE
Link to Plunker.
If you're using the angular-ui-router then your should be injecting $stateParams rather than $routeParams. So you code will look like:
angular.module('app', ['ionic', 'app.controllers'])
.config(function($stateProvider, $urlRouterProvider, $routeProvider) {
$stateProvider
.state('app.staff', {
url: '/staff/:staffid',
views: {
'menuContent' :{
templateUrl: "templates/staff-details.html",
controller: 'StaffDetailsCtrl'
},
}
})
});
// Review Controller
.controller('StaffDetailsCtrl', function($scope, $stateParams) {
// Get staff
alert('yeeeees');
var id = $stateParams.staffid;
$scope.staff = $scope.staff.get(id);
});

Angularjs nested router does not work

I am working on angular route and have some problems when using nested one:
The following 'abc' state works perfectly for route /admin/team/:teamId
.state('admin', {
url: '/admin',
controller: 'AdminController',
templateUrl: '/views/admin/index.html'
})
.state('admin.home', {
url: '/home',
parent: 'admin',
templateUrl: '/views/admin/dashboard.html'
})
.state('admin.team', {
url: '/team',
parent: 'admin',
controller: 'TeamController',
templateUrl: '/views/admin/team/index.html'
})
.state('abc', {
url: '/admin/team/:teamId',
// parent: 'admin.team',
controller: function($scope, $stateParams){
console.info('$stateParams.teamId', $stateParams.teamId);
},
templateUrl: '/views/admin/player/index.html'
});
but if I replace the state 'abc' as the following, the player template does not render and hold onto the admin/team/index.html, even no console output, such as:
.state('admin.team.details', {
url: '/:teamId',
parent: 'admin.team',
controller: function($scope, $stateParams){
console.info('$stateParams.teamId', $stateParams.teamId);
},
templateUrl: '/views/admin/player/index.html'
});
are there anyway for me to solve it?
Try this
.state('admin.team.details', {
url: '/details/:teamId',
parent: 'admin.team',
controller: function($scope, $stateParams){
console.info('$stateParams.teamId', $stateParams.teamId);
},
templateUrl: '/views/admin/player/index.html'
});
finally, I've found the following would works:
.state('admin.team', {
url: '/team',
parent: 'admin',
controller: 'TeamController',
templateUrl: '/views/admin/team/index.html'
})
.state('admin.team.details', {
url: '/team/:teamId',
parent: 'admin',
controller: 'PlayerController',
templateUrl: '/views/admin/player/index.html'
});
Thanks for all answering me.

Categories

Resources