Angular ui-router para realizar uma visão condicional
-
21-12-2019 - |
Pergunta
Estou fazendo uma pergunta semelhante a esta pergunta: Visualizações condicionais da interface do usuário do roteador da interface do usuário?, mas minha situação é um pouco mais complexa e não consigo fazer a resposta fornecida funcionar.
Basicamente, tenho uma url que pode ser renderizada de duas maneiras muito diferentes, dependendo do tipo de entidade para a qual a url aponta.
Aqui está o que estou tentando atualmente
$stateProvider
.state('home', {
url : '/{id}',
resolve: {
entity: function($stateParams, RestService) {
return RestService.getEntity($stateParams.id);
}
},
template: 'Home Template <ui-view></ui-view>',
onEnter: function($state, entity) {
if (entity.Type == 'first') {
$state.transitionTo('home.first');
} else {
$state.transitionTo('home.second');
}
}
})
.state('home.first', {
url: '',
templateUrl: 'first.html',
controller: 'FirstController'
})
.state('home.second', {
url: '',
templateUrl: 'second.html',
controller: 'SecondController'
});
Configurei um Resolve para buscar a entidade real de um serviço tranquilo.Tudo parece estar funcionando até que eu chegue ao transactionTo com base no tipo.
A transição parece funcionar, exceto que a resolução é acionada novamente e o getEntity falha porque o ID é nulo.
Tentei enviar o ID para as chamadas transactionTo, mas ele ainda tenta fazer uma segunda resolução, o que significa que a entidade é buscada duas vezes no serviço restante.
O que parece estar acontecendo é que no manipulador onEnter, o estado ainda não mudou, então, quando a transição acontece, ele pensa que está fazendo a transição para um estado totalmente novo, em vez de para um estado filho.Isso fica ainda mais evidenciado porque quando eu removo a entidade.do nome do estado na transição para, ele acredita que o estado atual é raiz, e não inicial.Isso também me impede de usar 'go' em vez de transactionTo.
Alguma ideia?
Solução
O modeloUrl também pode ser uma função, para que você verifique o tipo e retorne uma visualização diferente e defina o controlador na visualização, em vez de como parte da configuração do estado.Você não pode injetar parâmetros em templateUrl, então talvez seja necessário usar templateProvider.
$stateProvider.state('home', {
templateProvider: ['$stateParams', 'restService' , function ($stateParams, restService) {
restService.getEntity($stateParams.id).then(function(entity) {
if (entity.Type == 'first') {
return '<div ng-include="first.html"></div>;
} else {
return '<div ng-include="second.html"></div>';
}
});
}]
})
Outras dicas
Você também pode fazer o seguinte:
$stateProvider
.state('home', {
url : '/{id}',
resolve: {
entity: function($stateParams, RestService) {
return RestService.getEntity($stateParams.id);
}
},
template: 'Home Template <ui-view></ui-view>',
onEnter: function($state, entity) {
if (entity.Type == 'first') {
$timeout(function() {
$state.go('home.first');
}, 0);
} else {
$timeout(function() {
$state.go('home.second');
}, 0);
}
}
})
.state('home.first', {
url: '',
templateUrl: 'first.html',
controller: 'FirstController'
})
.state('home.second', {
url: '',
templateUrl: 'second.html',
controller: 'SecondController'
});
Acabei tornando o controlador inicial um irmão do primeiro e do segundo, em vez de um pai, e então fiz o controlador inicial fazer um $state.go para o primeiro ou segundo, dependendo dos resultados da resolução.
Use código verificado para visualização condicional em ui-route
$stateProvider.state('dashboard.home', {
url: '/dashboard',
controller: 'MainCtrl',
// templateUrl: $rootScope.active_admin_template,
templateProvider: ['$stateParams', '$templateRequest','$rootScope', function ($stateParams, templateRequest,$rootScope) {
var templateUrl ='';
if ($rootScope.current_user.role == 'MANAGER'){
templateUrl ='views/manager_portal/dashboard.html';
}else{
templateUrl ='views/dashboard/home.html';
}
return templateRequest(templateUrl);
}]
});