Se você é como eu, você já usou ui-router antes com angular.js. Seus aplicativos provavelmente se parecem com isto:
var app = angular.module('intro-ui-router', [
'ui.router'
]);
app.config(function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise("/");
$stateProvider
.state('home', {
url: "/",
templateUrl: "templates/main.html",
controller: 'MainCtrl'
});
});
templates / main.html é renderizado em <div ui-view></div>
de index.html . É funcional e funciona.
Adicionar dados
Para mostrar a obtenção de dados e alguns recursos mais avançados do ui-router, acionei um servidor expresso em server.js que serve index.html e uma API de “posts”.
Para uma implementação realmente básica, obtendo as postagens:
app.controller('MainCtrl', function($scope, $http){
$http.get('/api/posts').then(function(posts){
$scope.posts = posts.data;
console.log($scope.posts);
})
});
Assim que o controlador for instanciado, ele disparará uma solicitação para o endpoint apropriado. Assim que a solicitação for retornada com dados, os dados preencherão a posts
matriz no escopo.
Em templates / main.html renderizamos as postagens na tela com um simples .ng-repeat
<h1>All posts</h1>
<div class='col-sm-12'>
<ul>
<li ng-repeat='post in posts'>
<a ng-href='/#/posts/{{post._id}}'>{{post.title}}</a>
</li>
</ul>
</div>
Esta é uma implementação bem simples de roteamento com angular.js, mas funciona. Recentemente, aprendi alguns truques extras que gostaria de compartilhar.
Refatorar
O problema com isso, tendo a chamada no controlador, é que haverá um pequeno atraso de quando a página é carregada até quando ela é realmente preenchida com dados do servidor. ui-router tem uma solução – resolver .
Dos documentos :
Você pode usar a resolução para fornecer ao seu controlador conteúdo ou dados personalizados para o estado. Se alguma dessas dependências forem promessas, elas serão resolvidas e convertidas em um valor antes que o controlador seja instanciado e o
$stateChangeSuccess
evento seja disparado.
Usando a propriedade resolve em nosso estado:
.state('home', {
url: "/",
templateUrl: "templates/main.html",
controller: 'MainCtrl',
resolve: {
posts: function($http){
return $http.get('/api/posts').then(function(posts){
return posts.data;
});
}
}
})
Resolve torna nosso controlador mais simples:
app.controller('MainCtrl', function($scope, posts){
$scope.posts = posts;
});
A vantagem dessa abordagem é que ela posts
estará disponível quando o controlador da rota for instanciado.
Mostrar uma postagem individual
Portanto, temos uma lista de postagens. Cada postagem usa ng-href para que possamos usar propriedades de escopo no caminho do url. Vamos definir essa rota de URL:
.state('viewPost', {
url: '/posts/:id',
templateUrl: 'templates/post.html',
controller: 'PostCtrl',
resolve: {
post: function($http, $stateParams){
// get the post data for the page
return $http.get('/api/posts/' + $stateParams.id).then(function(post){
return post.data;
});
}
}
})
O controlador está leve novamente:
app.controller('PostCtrl', function($scope, post){
$scope.post = post;
});
E a visão é simples:
<h1>{{post.title}}</h1>
<p>{{post.description}}</p>
Isso /#/
para o ng-href é feio. ui-router usa estados, então podemos usar ui-sref . ui-sref direciona para um estado em vez de uma rota de url. Nossa lista de atualizações de postagens para:
<h1>All posts</h1>
<div class='col-sm-12'>
<ul>
<li ng-repeat='post in posts'>
<a ui-sref="viewPost({id: post.id})">{{post.title}}</a>
</li>
</ul>
</div>
Desta forma, se alterarmos a url do endpoint para visualizar um post, nós apenas a alteramos na definição de rotas, não em todo o nosso html.
Para navegar para estados no javascript, você pode usar $state.go('state_name');
Por exemplo, um simples botão Voltar na página de postagem:
<div class='btn btn-primary' ng-click='goBack()'>< Back</div>
e o método é definido em PostCtrl
:
app.controller('PostCtrl', function($scope, post, $state){
$scope.post = post;
$scope.goBack = function(){
$state.go('home');
};
});
Agora podemos ver uma postagem individual e navegar facilmente de volta ao estado de origem. O url é persistente, o que significa que você pode marcá-lo e atualizar a página e ver a mesma coisa. Conseguimos isso de graça com o ui-router, onde é necessário código extra em uma estrutura como o Backbone.
Vistas aninhadas
Na página inicial, quero mostrar uma prévia da descrição do post quando clico em “visualizar”. Para fazer isso, usaremos uma visão aninhada sem alterar o url .
Vamos definir um estado filho:
.state('home.preview', {
controller: function($scope, $stateParams){
$scope.post = $stateParams.post;
},
params: {
post: 'defaultValue'
},
template: '{{post.description}}'
})
Em seguida, atualize templates / main.html :
<h1>All posts</h1>
<div class='col-sm-6'>
<ul>
<li ng-repeat='post in posts'>
<a ui-sref="viewPost({id: post.id})">{{post.title}}</a>
<small ui-sref='home.preview({post: post})'>preview</small>
</li>
</ul>
</div>
<div class='col-sm-6'>
<!-- show a preview of the post here -->
<div ui-view></div>
</div>
Agora, ao clicar em visualização, você verá a descrição do post. Existem mais alguns truques com o ui-router, como usar estados abstratos e declarar múltiplas visualizações nomeadas . Esta é uma introdução ao roteador da interface do usuário e será útil no futuro. Boa codificação!
Verifique também o CÓDIGO FONTE .
Você também pode me seguir no twitter !