Aplicações nativas em JavaScript com Capacitor

Capacitor, o novo framework da Ionic.

Você sabe o que é o Ionic? É uma ferramenta para criar aplicativos mobile, utilizando HTML, CSS e JavaScript.

Capacitor é uma cross-plataform API que facilita chamar SDKs nativos a partir de código da Web e fornece suporte de progressive web apps. Criada pela Ionic, é uma alternativa ao Apache Cordova, que foi lançado em 2009. O Capacitor foi criado devido ao sistema de plugins desatualizados do Apache Cordova e pela restrição ao gerenciamento de plataformas nativas.

Ele foi projetado pela equipe do Ionic Framework como uma alternativa ao Cordova. O Capacitor pode ser usado sem o Ionic, mas em breve se tornará uma parte essencial do mesmo.

Continue lendo “Aplicações nativas em JavaScript com Capacitor”

Ionic 3: Infinite Scroll

Infinite scroll é uma das formas que temos de criar paginação em nossos sistemas. Veja nesse artigo como implementar ele em um projeto mobile criado com Ionic na versão 3.

No final desse artigo você terá criado um app como o da imagem abaixo.

Para que possamos ter uma lista com dados reais, eu irei utilizar uma das API`s disponibilizadas pelo The New York Times (NYT). Para utilizar essa API, você irá precisar de uma KEY que pode ser encontrada no link: Developer NYT.

Criação do projeto

Nosso primeiro passo será a criação de um novo projeto. Para isso, execute o comando abaixo no seu terminal:

ionic start ionic-nyt blank

O comando a cima irá criar um novo projeto com uma configuração básica. Para testar ele, execute o seguinte comando ionic serve no seu terminal e abra o seguinte endereço no seu navegador: http://localhost:8100/.

Criação do provider

O próximo passo será a criação de um provider para buscar os dados na API do NYT. Para isso, execute o seguinte comando no seu terminal:

ionic g provider nyt-api

Agora abra o projeto em uma IDE de sua preferência, para esse artigo eu irei utilizar o VS Code. Em seguida, atualize o seu provider com o código abaixo:

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

import {NewsModel} from '../..//models/news-model'

/*
  Generated class for the NytApiProvider provider.

  See https://angular.io/guide/dependency-injection for more info on providers
  and Angular DI.
*/
@Injectable()
export class NytApiProvider {

  private apiUrl = 'https://api.nytimes.com/svc/topstories/v2/home.json?api-key={your key}';


  constructor(public http: Http) {}

  getTopStories(page): Observable<NewsModel[]> {
    return this.http.get(this.apiUrl)
                    .map(this.extractData)
                    .catch(this.handleError);
  }

  private extractData(res: Response) {
    let body = res.json();
    return body || { };
  }

  private handleError (error: Response | any) {
    let errMsg = `${error.status} - ${error.statusText || ''}`;
   console.error(errMsg);
    return Observable.throw(errMsg);
  }

}

Agora para organizar o código, vamos criar uma Model para o nosso APP. Para isso, crie um novo diretório chamado Models e dentro dele um arquivo chamado news-model.ts, em seguida atualize ele com o código abaixo:

export class NewsModel {
constructor(
   public title?: string,
   public date?: Date) { }
}

Não podemos esquecer de adicionar HttpModule e NytApiProvider no nosso arquivo app.module.ts.

O próximo passo será injetar o NytApiProvider na nossa HomePage. Para isso, atualize o seu arquivo home.ts com o código abaixo:

import { Component } from "@angular/core";
import { NavController } from "ionic-angular";
import { NytApiProvider } from "../../providers/nyt-api/nyt-api";
import { NewsModel } from "../..//models/news-model";

@Component({
  selector: "page-home",
  templateUrl: "home.html"
})
export class HomePage {
  data: any;
  news: NewsModel[] = [];
  errorMessage: string;
  page = 1;
  perPage = 0;
  totalData = 0;
  totalPage = 0;

  constructor(public navCtrl: NavController, private nyt: NytApiProvider) {
    this.getTopStories();
  }

  getTopStories() {
    this.nyt.getTopStories(this.page).subscribe(res => {
      this.data = res;

      for (let i = 0; i <= 10; i++) {
        let n = new NewsModel(
          this.data.results[i].title,
          this.data.results[i].published_date
        );
        this.news.push(n);
      }

      this.perPage = 10;
      this.totalData = this.data.num_results;
      this.totalPage = 10;
    }, error => (this.errorMessage = <any>error));
  }

  doInfinite(infiniteScroll) {
    this.totalPage = this.page * 10;
    setTimeout(() => {
      let result = this.data.results.slice(this.page * 10);

      for (let i = 1; i <= this.perPage; i++) {
        if (result[i] != undefined) {
          
          let n = new NewsModel(result[i].title, result[i].published_date);
          this.news.push(n);
        }
      }

      this.page += 1;

      infiniteScroll.complete();
    }, 2000);
  }
}

Analisando o código acima nós temos dois métodos: getTopStories que faz um request ao nosso provider e popula a nossa NewsModel e o doInfinite que é requisitado no nosso scroll.

Como a API do NWT não tem paginação, eu precisei fazer a páginação no APP, mas em cenário real, a melhor forma seria que essas regras ficassem no backend.

Agora atualize o seu arquivo home.html com o código abaixo:

<ion-header>
  <ion-navbar>
    <ion-title>
      <img src="https://a1.nyt.com/assets/homepage/20171218-150818/images/foundation/logos/nyt-logo-379x64.png"/>
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
 
  <ion-list>
    <ion-item *ngFor="let n of news">
      <h1>{{n.title}}</h1>
      <h6>{{n.date}}</h6>
    </ion-item>
  </ion-list>

  <ion-infinite-scroll (ionInfinite)="doInfinite($event)" *ngIf="totalPage < totalData">
    <ion-infinite-scroll-content loadingSpinner="bubbles" loadingText="Loading more data..."></ion-infinite-scroll-content>
  </ion-infinite-scroll>


</ion-content>

O ponto mais importando do código a cima está entre as linhas 18 e 20, onde utilizamos ion-infinite-scroll para fazer um request ao nosso método doInfinite() toda vez que o componente apresentar todos os itens que estão na nossa Model, até que o total da Model seja maior que o total de itens.

Caso você queira baixar a versão final do projeto criado nesse artigo, segue o seu link no GitHub.