I have two level nested state on ui-router and I can't set a default nested state for some view.
I need to load the state cars.detail.supply.list when the state cars.detail is active without changing the current url.
I'm expecting to show supplies list without click on List supplies button.
What am I missing?
Full code: https://plnkr.co/edit/DqwhaDXh3biMbq9PLCV3?p=preview
ui-states:
.state('cars.detail', {
parent: 'cars',
url: '/edit/:id',
views: {
'content#index': {
templateUrl: 'cars.detail.html',
controller: 'CarDetailController'
},
'supplies': {
templateUrl: 'cars.supply.html',
controller: 'CarDetailController'
}
}
})
.state('cars.detail.supply', {
url: '',
parent: 'cars.detail',
abstract: true,
//'default': '.list',
views: {
'supplies#cars.detail': {
templateUrl: 'cars.supply.html',
//controller: 'SupplyListController'
}
}
})
.state('cars.detail.supply.list', {
parent: 'cars.detail.supply',
url: '',
views: {
'#cars.detail.supply': {
templateUrl: 'cars.supply.list.html',
controller: 'SupplyListController'
}
}
})
.state('cars.detail.supply.add', {
parent: 'cars.detail.supply',
url: '/add-supply',
views: {
'#cars.detail.supply': {
templateUrl: 'cars.supply.add.html',
controller: 'AddSupplyController'
}
}
})
The view:
<div>
...
<h4 ng-if="car.id">
Supplies
<a class="btn btn-default btn-sm pull-right" ui-sref="cars.detail.supply.add({ carId: car.id })">
<i class="glyphicon glyphicon-plus"></i> Add supply
</a>
<a class="btn btn-default btn-sm pull-right" ui-sref="cars.detail.supply.list({ carId: car.id })">
<i class="glyphicon glyphicon-plus"></i> List supplies
</a>
</h4>
<div ui-view="supplies" class="">
</div>
</div>
I've tried:
https://github.com/nonplus/angular-ui-router-default
set abstract state for cars.detail.supply
solutions from many SO related questions
set url = '' as mentioned here https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-set-up-a-defaultindex-child-state
In order to get it to work, you have to differentiate the cars.detail's and cars.detail.supply.list's urls. So, step one is to give cars.detail.supply.list a url:
.state('cars.detail.supply.list', {
parent: 'cars.detail.supply',
url: '/list',
templateUrl: 'cars.supply.list.html',
controller: 'SupplyListController'
})
Once the state urls can be differentiated, you need to transition to the list state by either updating the link in the car list repeater to
ui-sref="cars.detail.supply.list(...)"
or
by indicating a redirect from the details state to the details's list state in app.js:
$urlRouterProvider.when('/dashboard/cars/edit/{id}', '/dashboard/cars/edit/{id}/list');
Related
I am trying to render a child view. However it is not showing, here is a sample of code below. Most examples I see have the entire state template in a single template; however I have several views in different templates which composed each states template.
.state({
name: 'search',
url: '/x',
abstract: true,
views: {
'searchBar': {
templateUrl: "template/template.html",
controller: "searchBar"
}
}
})
.state({
name: 'search.final',
url: '^/details',
params: {
Data: "hello World"
},
views: {
'dashb': {
templateUrl: 'template/dashb.html'
},
'sidebar': {
templateUrl: 'template/sidebar.html'
},
}
and then my index.html is as follow
<div>
<div class="row">
<div class="col-lg-3">
<div ui-view="searchBar"></div>
<br>
<div ui-view="sidebar"></div>
<br>
</div>
<div class="col-lg-9" ui-view="dashb"></div>
</div>
</div>
I have in searchBartemplate
<ui-view></ui-view> for the child view to be inserted, meaning the sideBar and dashb
and in a controller I have this:
$state.go("search.final" , {Data:"Byee"})
However I am not rendering the child view.. any help appreciated. thanks
I figured it out. We need to append # at the end of the name of the view for the child view. :)
.state({
name: 'search',
url: '/x',
abstract: true,
views: {
'searchBar': {
templateUrl: "template/template.html",
controller: "searchBar"
}
}
})
.state({
name: 'search.final',
url: '^/details',
params: {
Data: "hello World"
},
views: {
'dashb#': {
templateUrl: 'template/dashb.html'
},
'sidebar#': {
templateUrl: 'template/sidebar.html'
},
}
I have an ionic app with some views, when I start the app I will go to my main view, when the controller of the view is initialized I will load some data.
The problem is, when I navigate from that view, using tabs, that controller is sometimes destroyed, so when I navigate back the data will have to load again.
I have done some testing with '$ionicView.loaded' and '$ionicView.unloaded' and it seems to be pretty random when the view is unloaded.
This is my state configuration
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('login', {
name: "login",
url: "/login",
templateUrl: "templates/login.html",
controller: 'loginCtrl'
})
// This is a sidemenu
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/menu.html'
})
.state('app.hms', {
url: '/hms',
views: {
'menuContent': {
templateUrl: 'templates/hms-app.html',
controller: 'HmsCtrl'
}
}
})
.state('app.hms-item', {
url: '/hms/:hmsId',
views: {
'menuContent': {
templateUrl: 'templates/hms-item.html',
controller: 'HmsItemCtrl'
}
},
params: {
item: null
}
})
.state('app.history', {
url: '/history',
views: {
'menuContent': {
templateUrl: 'templates/history-list.html',
controller: 'HistoryCtrl'
}
}
})
.state('app.history-item', {
url: '/history/:itemId',
views: {
'menuContent': {
templateUrl: 'templates/history-item.html',
controller: 'HistoryItemCtrl'
}
},
params: {
itemId: null
}
})
.state('app.event-new', {
url: '/event/new',
views: {
'menuContent': {
templateUrl: 'templates/event-new.html',
controller: 'EventCtrl as ctrl'
}
}
})
.state('app.risk-new', {
url: '/risk/new',
views: {
'menuContent': {
templateUrl: 'templates/risk-new.html',
controller: 'RiskCtrl as ctrl'
}
}
});
// if none of the above states are matched, use this as the fallback
// this is also the first page, 'front page'
$urlRouterProvider.otherwise('login');
});
My tabs are defined in each .html template I need them in (so not the login page, for instance), they are defined after the closing of ion-content:
<div class="tabs tabs-icon-top">
<a class="tab-item" href="#/app/hms">
<i class="icon ion-home"></i>
Home
</a>
<a class="tab-item" href="#/app/event/new">
<i class="icon ion-document-text"></i>
Hendelse
</a>
<a class="tab-item" href="#/app/risk/new">
<i class="icon ion-document-text"></i>
Risikorapport
</a>
<a class="tab-item" href="#/app/history">
<i class="icon ion-ios-list"></i>
Historikk
</a>
What could cause the controller of the view to be destroyed when I navigate from it?
Turns out, Ionic removes caching for views that are "forward", so when navigating back from a forward view that $scope will be destroyed.
This is explained under caching here
By default, when navigating back in the history, the “forward” views are removed from the cache. If you navigate forward to the same view again, it’ll create a new DOM element and controller instance. Basically, any forward views are reset each time. This can be configured using the $ionicConfigProvider:
So, configuring the $ionicConfigProvider with $ionicConfigProvider.views.forwardCache(true); fixed my issue
I also saw I could fix my issue another way, and that was to not make my views "forward", when navigating to a new view using href, we can specify what sort of view that should be, by doing nav-direction="swap", available directions are forward, back, enter, exit, and swap
Example of tab, with direction
<a class="tab-item" nav-direction="swap" nav-transition="android" href="#/app/home">
<i class="icon ion-home"></i>
Home
</a>
I've got this error when clicking on ui-sref="favorite-list":
Could not resolve 'favorite-list' from state 'studies'
I have code like this:
$stateProvider
.state('study', {
url: '/study/:studyId',
templateUrl: 'scripts/study/study-edit.template.html',
controller: 'StudyController'
})
.state('studyObject', {
url: '/study/:studyId/studyObject/:studyObjectId',
templateUrl: 'scripts/study-object/study-object-edit.template.html',
controller: 'StudyObjectController'
})
.state('studies', {
url: '/studies?all&field&term&page&sort&sort_dir',
templateUrl: 'scripts/studies/studies.template.html',
controller: 'StudiesController',
onExit: function exitStudies(filterQuery) {
filterQuery.emptyQuery();
},
menuElement: 'studies',
resolve: {
attributes: function (attribute, manageAttributes) {
...
}
}
})
.state({
name: 'studies.favorite-list',
template: '<favorites-list></favorites-list>',
parent: 'studies'
});
and html:
<div class="left-menu" ng-class="{collapsed: menu.isCollapsed}" click-outside="closeMenu()">
<ul class="list-unstyled">
<li>
<button role="button" ui-sref="favorite-list" ng-class="{'text-bold': favorites.active}">
<img src="images/divos/star.svg" alt="Favorites" height="20" width="30"> Favorites
</button>
</li>
</ul>
<div ui-view></div>
</div>
I've try with parent and without, using .state('studies.favorite-list', {}) also using ui-sref="studies.favorite-list" but I'm keep getting this error. I'm using version 0.2.18 from bower.
Found the solution, I've only needed to add comma before the name:
ui-sref=".favorite-list"
Using ui-router in angular, I have setup a 'users' state where all the users in my application are returned in an ng-repeat. I am trying to create the show state for the users profile page however the view of the child state is inheriting the parent view 'templates/users/index.html' (Here is my app.js:
.state('users', {
abstract: true,
name: 'users',
url: '/users',
views: {
nav: {
templateUrl: 'templates/navbar.html',
controller: 'MainCtrl'
},
content: {
templateUrl: 'templates/users/index.html',
controller: 'UsersCtrl'
}
}
})
.state('users.show', {
url: '/show/:id',
views: {
nav: {
templateUrl: 'templates/navbar.html',
controller: 'MainCtrl'
},
content: {
templateUrl: 'templates/users/show.html',
controller: 'UsersCtrl'
}
}
});
Here is my index.html:
<div class="container">
<label>Search: <input ng-model="searchText"></label>
<a ui-sref="users.show({id: user.id})" ng-click="showUser(user.id)" ng-repeat="user in users | filter:searchText ">
<h2> {{ user.name }} </h2>
<h3> {{ user.email }} </h3>
<button ng-click="createConversation({sender_id: current_user.id, recipient_id: user.id})" >Message</button>
</a>
</div>
The url in the browser is http://localhost:8080/#/users/show/2 however the html file being inherited in the users.show state is the parents users (index.html) file.
Any help appreciated!
The nested view users.show will actually render within the user view. So you just need to place another <ui-view> within templates/users/index.html where the show view will render.
Hey I have Angular rendering a list of Quotes as resources. The Quotes are stored in a rails back end. I am at the point where I would like to use Angular to render the show.html for that specific quote resource.
I havent been able to get angular to resolve to the state.
I'm not sure if I understand how to pass id's into state.
I need help figuring out how to get angular to render the show.html in the ui-view labeled "fullquote" for the specific quote. Here is my code.
Quotes.html
<div class="quotes col-xs-10 col-md-8" ng-controller="QuotesCtrl" >
<div ng-repeat="quote in quotes">
<a ng-click="showQuote(quote);">
<span ng-if="quote.read == false"> *NEW*</span>
<span>Quote id: {{quote.id}}</span>
<span>Name: {{quote.name}}</span>
<span>Email: {{quote.email}}</span>
<span>City: {{quote.city}}</span>
<span>Region: {{quote.region}}</span>
<span>State: {{quote.state}}</span>
</a>
<div ng-show="quote.visible">
<a ui-sref="quotes/{{quote.id}}"> View </a>
<ui-view="fullquote"></ui-view="fullquote">
<a ng-click="quotes.splice($index, 1)"> Delete </a>
<div ng-if"">
<span> {{quote.question2 }}</span>
<span> {{quote.question3 }}</span>
<span> {{quote.question4 }}</span>
<span> {{quote.question5 }}</span>
<span> {{quote.question6 }}</span>
<span> {{quote.question7 }}</span>
<span> {{quote.question8 }}</span>
<span> {{quote.question9 }}</span>
<span> {{quote.question10 }}</span>
<span> {{quote.question11 }}</span>
<span> {{quote.question12 }}</span>
<span> {{quote.question13}}</span>
</div>
</div>
</div>
</div>
Quotes.js
app.factory('Quotes', ['$resource',function($resource){
return $resource('/quotes.json', {},{
query: { method: 'GET', isArray: true },
create: { method: 'POST' }
})
}]);
app.factory('Quote', ['$resource', function($resource){
return $resource('/quotes/:id.json', {}, {
show: { method: 'GET' },
update: { method: 'PUT', params: {id: '#id'} },
delete: { method: 'DELETE', params: {id: '#id'} }
});
}]);
app.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('home', { url: '', templateUrl: 'static_pages/home.html'})
.state('quotes', { url: '/quotes', abstract: false, views : { templateUrl: 'quotes.html', controller: 'QuotesCtrl'}})
.state('quotes/:id', { url: 'quotes/:id', view: { "fullquote": { templateUrl: 'show.html', controller: 'QuotesCtrl'}}})
.state('quotes/:id.pdf', { url: 'quotes/:id.pdf', controller: 'QuotesCtrl'})
.state('users', { url: '/users', templateUrl: 'users.html', controller: 'UsersCtrl'})
.state('/users/:id', { url: 'users_show.html', controller: "UsersCtrl" });
$urlRouterProvider.otherwise( function($injector, $location) {
var $state = $injector.get("$state");
$state.go("home");
})
$locationProvider.html5Mode({ enabled: true, requireBase: false });
});
app.controller("QuotesCtrl", ['$scope', '$state', '$http', 'Quotes', 'Quote', '$location', function($scope, $state, $http, Quotes, Quote, $location ) {
$scope.quotes = Quotes.query();
$scope.quote = Quote.query();
$scope.showQuote = function (quote) {
quote.visible = !quote.visible;
}
}]);
There are several things you should look into:
Your state naming is incorrect. I assume you are trying to use nested states.In this case you need to have quotes.detail or something of the kind. Also, in the state, you need to name your object views instead of view. Please, refer to UI.Router multiple views guide for more information.
.state('quotes.detail',
{ url: 'quotes/:id',
views: {
"fullquote": { templateUrl: 'show.html',
controller: 'QuoteCtrl'}
}
})
To pass a parameter to the state you need to change your link to this. If you'd like to know more about passing parameters to ui.router states - read the manual:
<a ui-sref="quotes.detail({{quote.id}})"> View </a>
If you want to have a separate view, you also need to have separate controller for it. I named it it QuoteController. You can get ht :id from the URL by injecting $stateParams in the controller. More info about getting parameters into the controllers - here:
//QuoteController
['$stateParams, Quote , function($stateParams, Quote) {
Quoute.get({id:$stateParams.id});
}]
I'm not sure this will completely solve your problem, but it will certainly bring you closer to solving it. I hope I was helpful!