Consultando a API do Blog.
E ai pessoal, vamos voltar para o desenvolvimento da nossa aplicação, devido ao pouco tempo que livre, resolvi que a série dará continuidade e será lançada toda quarta-feira pela manhã, e na parte 2 da nossa série estaremos consultando nossa API e consumindo as postagens do blog.
Para começar iremos editar o nosso arquivo index.html e deixar com a seguinte estrutura
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> <title></title> <link rel="manifest" href="manifest.json"> <!-- un-comment this code to enable service worker <script> if ('serviceWorker' in navigator) { navigator.serviceWorker.register('service-worker.js') .then(() => console.log('service worker installed')) .catch(err => console.log('Error', err)); } </script>--> <link href="lib/ionic/css/ionic.css" rel="stylesheet"> <link href="styles/style.css" rel="stylesheet"> <!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above <link href="css/ionic.app.css" rel="stylesheet"> --> <!-- ionic/angularjs js --> <script src="lib/ionic/js/ionic.bundle.js"></script> <!-- cordova script (this will be a 404 during development) --> <script src="cordova.js"></script> <!-- your app's js --> <script src="app/app.js"></script> <script src="app/posts/posts.controller.js"></script> <script src="app/posts/posts.service.js"></script> <script src="app/menu/menu.controller.js"></script> </head> <body ng-app="appvila"> <ion-nav-view></ion-nav-view> </body> </html>
Estaremos importando os scripts de serviços e controladores dentro do index.html e o nome da nossa aplicação vai ser appvila dentro do ng-app.
Feito isso podemos agora criar nosso controlador de Posts e o serviço onde vamos tratar a chamada aos endpoints, assim vamos poder consumir o serviço no nosso controlador. Para o desenvolvimento da nossa aplicação estarei adotando o padrão de projeto proposto por John Papa, para você estudar mais sobre clique aqui, você encontrará tanto sobre angular 1 como angular 2.
Dentro do diretório app/posts iremos criar o arquivo chamado posts.service.js, ele será responsável por consultar nosso endpoints da nossa API do WordPress. Nele iremos escrever o seguinte código:
angular.module('posts.service', []) .factory('postsService', postsService); function postsService($http, $q) { // interface var service = { posts: [], getPosts: getPosts }; return service; // implementacao function getPosts() { var def = $q.defer(); $http.jsonp("http://localhost/appvila/wp-json/posts?filter[posts_per_page]=3&_embed&_jsonp=JSON_CALLBACK ") .success(function(data) { service.posts = data; def.resolve(data); }) .error(function() { def.reject("Falha ao buscar posts"); }); return def.promise; } }
Vamos criar uma promise onde iremos retornar o resultado de nossa requisição em formato JSON em caso de sucesso ou falha em caso de erros. Falando um pouco sobre promise. Uma promise é um proxy para um valor não necessariamente conhecido quando a promessa é criada. Ele permite que você associe manipuladores com o valor de sucesso ou o motivo de falha de uma ação assíncrona. Isso permite que métodos assíncronos retornem valores como métodos síncronos: em vez de retornar imediatamente o valor final, o método assíncrono retorna uma promessa de fornecer o valor em algum ponto no futuro.
Uma promise está em um destes estados:
- pendente: estado inicial, não cumprido ou rejeitado.
- Preenchido: o que significa que a operação foi concluída com êxito.
- Rejeitada: significa que a operação falhou.
Com o nosso serviço criado, usaremos ele no controlador que será chamado na visão. Nosso arquivo posts.controller.js ficará assim:
angular.module('posts.controller', []) .controller('PostsCtrl', PostsCtrl); function PostsCtrl(postsService) { var vm = this; //usando nosso service para consultar as postagens vm.posts = []; vm.getPosts = function(){ postsService.getPosts() .then( function(posts){ for(var i=0; i < posts.length; i++){ vm.posts.push(posts[i]); } vm.posts = posts; }, function(data) { console.log('Falha ao consumir API.') } ); }; vm.getPosts(); }
No nosso controlador iremos injetar o serviço para podermos usá-lo, dentro da nossa promise estaremos preenchendo um vetor com o resultado das postagens, isso será usado posteriormente para fazer a paginação. Com nosso controlador pronto para pegar as postagens vamos agora implementar a visão, onde serão exibidos todas as postagens.
Agora vamos abrir o posts.html e escrever o seguinte código:
<ion-view view-title="Posts"> <ion-content> <div ng-repeat="post in postsCtrl.posts" class="list card"> <div class="item item-avatar"> <img ng-src="{{post.author.avatar}}"> <h2 class="cor-texto">{{post.author.name}}</h2> <p class="cor-texto">{{post.date}}</p> </div> <div class="item item-body"> <div> <h2 ng-bind-html="post.title"></h2> <img class="full-image" src="{{post.featured_image}}"> </div> </div> </div> </ion-content> </ion-view>
O código acima irá iterar sobre todas as postagens que foram retornadas e serão exibidas para gente na nossa rota principal, podemos ver o que nossa API retorna, usando a url diretamente no browser ou usando um programa para testar API’s chamado POSTMAN, com ele podemos visualizar o JSON que é retornado da API, que contém a seguinte estrutura:
Vamos deixar o controlador do menu criado, mas sem nenhuma função:
angular.module('menu.controller', []) .controller('MenuCtrl', MenuCtrl); function MenuCtrl(){ }
Estamos quase prontos para testar, vamos injetar nossos controladores e serviços no nosso módulo principal o app.js, ele ficará assim:
// Ionic Starter App // angular.module is a global place for creating, registering and retrieving Angular modules // 'starter' is the name of this angular module example (also set in a <body> attribute in index.html) // the 2nd parameter is an array of 'requires' angular.module('appvila', ['ionic', 'menu.controller', 'posts.controller', 'posts.service']) .run(function($ionicPlatform) { $ionicPlatform.ready(function() { if(window.cordova && window.cordova.plugins.Keyboard) { // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard // for form inputs) cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); // Don't remove this line unless you know what you are doing. It stops the viewport // from snapping when text inputs are focused. Ionic handles this internally for // a much nicer keyboard experience. cordova.plugins.Keyboard.disableScroll(true); } if(window.StatusBar) { StatusBar.styleDefault(); } }); }) .config(function($stateProvider, $urlRouterProvider) { $stateProvider .state('app', { url: '/app', abstract: true, templateUrl: 'app/menu/menu.html', controller: 'MenuCtrl as menuCtrl' }) .state('app.posts', { url: "/posts", views: { 'menuContent': { templateUrl: "app/posts/posts.html", controller: 'PostsCtrl as postsCtrl' } } }); $urlRouterProvider.otherwise('/app/posts'); });
Com todas as telas ajustadas, podemos testar nossa aplicação, acessando o diretório pelo terminal e usando o comando
$ ionic serve -l
O aplicativo terá essa aparência:
Podemos ver que a aplicação está funcionando e já é possível visualizar as postagens, porém só temos uma postagem em nosso blog, vamos criar mais algumas para podermos implementar a paginação com scroll infinito futuramente.
A página onde nos permite criar postagens é essa acima, criei algumas, vocês podem ficar a vontade para criar quantas quiserem. Podemos perceber que foram criadas exibidas apenas 3 postagens no nosso aplicativo, isso ocorreu por conta da url que passamos no nosso serviço, onde foi filtrado para trazer apenas 3 posts por página.
Vocês podem conferir como anda ficando nossa aplicação em https://github.com/viladosilicio/serie-ionic. Para ficar visivelmente melhor, vamos acessar o dashboard do nosso blog e criar uma categoria e um post novo.
Muito bom, estou acompanhando
Valeu Bruno, se tiver qualquer dúvida, crítica ou sugestão, comente!