Make messages
an abstract state, keep the resolve
, and move the templateUrl
and controller
to a new state, messages.list
. Then, create a parent <ui-view />
for your messages
state, and give it a templateUrl
with whatever you want the user to see while the message is loading. Should work.
Automatically redirect to child state
-
11-07-2023 - |
Question
I'm using UI-Router in my AngularJS app and I have routes like this:
angular.module('app.messages').config(function($stateProvider, ACCESSLEVELS) {
$stateProvider.state('messages', {
url: '/messages',
templateUrl: 'messages/list.html',
controller: 'MessagesListCtrl as controller',
resolve: {
'conversations': function(Restangular) {
return Restangular.all('conversations').getList();
}
}
});
$stateProvider.state('messages.detail', {
url: '/{conversationId:[0-9]{1,8}}',
templateUrl: 'messages/conversation.html',
controller: 'MessagesDetailCtrl as controller',
resolve: {
'conversation': function(conversations, $stateParams) {
return conversations.get($stateParams.conversationId);
}
}
});
});
So if you go to /messages
it'll show a list of your conversations (and it contains a ui-view
for the details view). If you go go /messages/1
you view a single conversation.
When you go to /messages
you should automatically be redirected to the most recent conversation, because just showing the list and a message like "Select a conversation from the list" is just stupid :)
The problem is that I don't know how to do this. If I have some redirect logic in the MessagesListCtrl then you'll always have a delay where you see the empty landing page and are then redirected. I can't do it a resolve function since those are also used by the child state. Surely others have had this same problem, how did they solve this?
Solution
OTHER TIPS
Solved with the help of Nate's answer above:
angular.module('app.messages').config(function($stateProvider) {
$stateProvider.state('messages', {
abstract: true,
templateUrl: 'messages/list.html',
controller: 'MessagesListCtrl as controller',
resolve: {
'conversations': function(Restangular) {
return Restangular.all('conversations').getList();
}
}
});
$stateProvider.state('messages.list', {
url: '/messages',
templateUrl: 'messages/conversation.html',
controller: 'MessagesDetailCtrl as controller',
resolve: {
'conversation': function(conversations) {
var lastId = _.last(_.sortBy(conversations, 'lastwrite')).id;
conversations.selectedId = lastId;
return conversations.get(lastId);
}
}
});
$stateProvider.state('messages.detail', {
url: '/messages/{conversationId:[0-9]{1,8}}',
templateUrl: 'messages/conversation.html',
controller: 'MessagesDetailCtrl as controller',
resolve: {
'conversation': function(conversations) {
conversations.selectedId = $stateParams.conversationId;
return conversations.get($stateParams.conversationId);
}
}
});
});
Basically messages.list and messages.detail show the exact same template and use the same controller. The resolve is just a bit different. I'm keeping track of the selectedId on conversations so I can mark the active conversation in the list.