Fábrica de Código

Nessa vídeo aula eu vou mostrar como fazer requisições HTTP a uma API REST.
Esse exemplo é valido tanto para aplicações feitas com Angular e Ionic.
E também como paginar os resultados utilizando o InfiniteScroll.

 

O que é API REST

REST significa Representational State Transfer, em português Transferência de Estado Representacional e é um conjunto arquiteturas mais moderno para construção de webservices.

 

Criando uma aplicação de exemplo

Será criado uma aplicação onde eu vou mostrar como criar uma conta, efetuar um login e incluir/alterar/excluir/consultar um usuário.

Vou usar também a API Reqres que prove vários exemplos de endpoints com dados fake.

E vou mostrar como paginar os dados utilizando o componente InfiniteScroll do Ionic.

O passo a passo abaixo é o mesmo mostrado no vídeo.

  • Passo 1: Criar o aplicativo.
  • Passo 2: Configurar o aplicativo para requisições HTTP.
  • Passo 3: Ajustar a Home para exibir os botões para os exemplos.
  • Passo 4: Criar o provider a criação de conta/login/CRUD de usuários.
  • Passo 5: Criar a página de criação de conta
  • Passo 6: Criar a página de login.
  • Passo 7: Criar a página para listar usuários.
  • Passo 8: Criar a página para incluir/alterar um usuário.
  • Passo 9: Criar a pagina para exibir um usuário.

 

Passo 1: Criar o aplicativo

ionic start NOME_DO_APP blank

 

Passo 2: Configurar o aplicativo para requisições HTTP

Registrar o HttpModule na parte de imports.

Arquivo app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { UsersProvider } from '../providers/users/users';

import { HttpModule } from '@angular/http';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp),
    HttpModule
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler},
    UsersProvider
  ]
})
export class AppModule {}

 

Passo 3: Ajustar a Home para exibir os botões para os exemplos

Arquivo home.ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  constructor(public navCtrl: NavController) { }

  openCreateAccount() {
    this.navCtrl.push('CreateAccountPage');
  }

  openLogin() {
    this.navCtrl.push('LoginPage');
  }

  openListUsers() {
    this.navCtrl.push('UserListPage');
  }
}

 

Arquivo home.html

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Rest Api Example
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>

  <h1 text-center margin-bottom>Exemplo de API REST</h1>

  <button ion-button block (click)="openCreateAccount()">Criar conta</button>
  <button ion-button block (click)="openLogin()">Login</button>
  <button ion-button block (click)="openListUsers()">CRUD de usuários</button>

</ion-content>

 

Passo 4: Criar o provider a criação de conta/login/CRUD de usuários

ionic g provider users

 

Arquivo users.ts

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

@Injectable()
export class UsersProvider {
  private API_URL = 'https://reqres.in/api/'

  constructor(public http: Http) { }

  createAccount(email: string, password: string) {
    return new Promise((resolve, reject) => {
      var data = {
        email: email,
        password: password
      };

      this.http.post(this.API_URL + 'register', data)
        .subscribe((result: any) => {
          resolve(result.json());
        },
        (error) => {
          reject(error.json());
        });
    });
  }

  login(email: string, password: string) {
    return new Promise((resolve, reject) => {
      var data = {
        email: email,
        password: password
      };

      this.http.post(this.API_URL + 'login', data)
        .subscribe((result: any) => {
          resolve(result.json());
        },
        (error) => {
          reject(error.json());
        });
    });
  }

  getAll(page: number) {
    return new Promise((resolve, reject) => {

      let url = this.API_URL + 'users/?per_page=10&page=' + page;

      this.http.get(url)
        .subscribe((result: any) => {
          resolve(result.json());
        },
        (error) => {
          reject(error.json());
        });
    });
  }

  get(id: number) {
    return new Promise((resolve, reject) => {
      let url = this.API_URL + 'users/' + id;

      this.http.get(url)
        .subscribe((result: any) => {
          resolve(result.json());
        },
        (error) => {
          reject(error.json());
        });
    });
  }

  insert(user: any) {
    return new Promise((resolve, reject) => {
      let url = this.API_URL + 'users/';

      this.http.post(url, user)
        .subscribe((result: any) => {
          resolve(result.json());
        },
        (error) => {
          reject(error.json());
        });
    });
  }

  update(user: any) {
    return new Promise((resolve, reject) => {
      let url = this.API_URL + 'users/' + user.id;
      let data = {
        "first_name": user.first_name,
        "last_name": user.last_name
      }

      this.http.put(url, user)
        .subscribe((result: any) => {
          resolve(result.json());
        },
        (error) => {
          reject(error.json());
        });
    });
  }

  remove(id: number) {
    return new Promise((resolve, reject) => {
      let url = this.API_URL + 'users/' + id;

      this.http.delete(url)
        .subscribe((result: any) => {
          resolve(result.json());
        },
        (error) => {
          reject(error.json());
        });
    });
  }
}

 

Passo 5: Criar a página de criação de conta

ionic g page create-account

 

Arquivo create-account.ts

import { UsersProvider } from './../../providers/users/users';
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams, ToastController } from 'ionic-angular';

@IonicPage()
@Component({
  selector: 'page-create-account',
  templateUrl: 'create-account.html',
})
export class CreateAccountPage {
  model: User;

  constructor(public navCtrl: NavController, public navParams: NavParams, private toast: ToastController, private userProvider: UsersProvider) {
    this.model = new User();
    this.model.email = 'sydney@fife';
    this.model.password = 'pistol';
  }

  createAccount() {
    this.userProvider.createAccount(this.model.email, this.model.password)
      .then((result: any) => {
        this.toast.create({ message: 'Usuário criado com sucesso. Token: ' + result.token, position: 'botton', duration: 3000 }).present();

        //Salvar o token no Ionic Storage para usar em futuras requisições.
        //Redirecionar o usuario para outra tela usando o navCtrl
        //this.navCtrl.pop();
        //this.navCtrl.setRoot()
      })
      .catch((error: any) => {
        this.toast.create({ message: 'Erro ao criar o usuário. Erro: ' + error.error, position: 'botton', duration: 3000 }).present();
      });
  }
}

export class User {
  email: string;
  password: string;
}

 

Arquivo create-account.html

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Rest Api Example
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>

  <h1 text-center>Exemplo de criação de conta</h1>

  <ion-list>
    <ion-item>
      <ion-label stacked>Email</ion-label>
      <ion-input type="text" name="email" [(ngModel)]="model.email"></ion-input>
    </ion-item>

    <ion-item>
      <ion-label stacked>Senha</ion-label>
      <ion-input type="password" name="password" [(ngModel)]="model.password"></ion-input>
    </ion-item>
  </ion-list>

  <button ion-button block (click)="createAccount()" color="primary">Criar conta</button>

</ion-content>

 

Passo 6: Criar a página de login

ionic g page login

 

Arquivo login.ts

import { UsersProvider } from './../../providers/users/users';
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams, ToastController } from 'ionic-angular';

@IonicPage()
@Component({
  selector: 'page-login',
  templateUrl: 'login.html',
})
export class LoginPage {
  model: User;

  constructor(public navCtrl: NavController, public navParams: NavParams, private toast: ToastController, private userProvider: UsersProvider) {
    this.model = new User();
    this.model.email = 'sydney@fife';
    this.model.password = 'pistol';
  }

  login() {
    this.userProvider.login(this.model.email, this.model.password)
      .then((result: any) => {
        this.toast.create({ message: 'Usuário logado com sucesso. Token: ' + result.token, position: 'botton', duration: 3000 }).present();

        //Salvar o token no Ionic Storage para usar em futuras requisições.
        //Redirecionar o usuario para outra tela usando o navCtrl
        //this.navCtrl.pop();
        //this.navCtrl.setRoot()
      })
      .catch((error: any) => {
        this.toast.create({ message: 'Erro ao efetuar login. Erro: ' + error.error, position: 'botton', duration: 3000 }).present();
      });
  }
}

export class User {
  email: string;
  password: string;
}

 

Arquivo login.html

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Rest Api Example
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>

  <h1>Exemplo de login</h1>

  <ion-list>
    <ion-item>
      <ion-label stacked>Email</ion-label>
      <ion-input type="text" name="email" [(ngModel)]="model.email"></ion-input>
    </ion-item>

    <ion-item>
      <ion-label stacked>Senha</ion-label>
      <ion-input type="password" name="password" [(ngModel)]="model.password"></ion-input>
    </ion-item>
  </ion-list>

  <button ion-button block (click)="login()" color="primary">Logar</button>

</ion-content>

 

Passo 7: Criar a página para listar usuários

ionic g page user-list

 

Arquivo user-list.ts

import { UsersProvider } from './../../providers/users/users';
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams, ToastController, InfiniteScroll } from 'ionic-angular';
import { ViewChild } from '@angular/core';

@IonicPage()
@Component({
  selector: 'page-user-list',
  templateUrl: 'user-list.html',
})
export class UserListPage {
  users: any[];
  page: number;
  @ViewChild(InfiniteScroll) infiniteScroll: InfiniteScroll;

  constructor(public navCtrl: NavController, public navParams: NavParams, private toast: ToastController, private userProvider: UsersProvider) { }

  ionViewDidEnter() {
    this.users = [];
    this.page = 1;
    this.infiniteScroll.enable(true);
    this.getAllUsers(this.page);
  }

  getAllUsers(page: number) {
    this.userProvider.getAll(page)
      .then((result: any) => {
        for (var i = 0; i < result.data.length; i++) {
          var user = result.data[i];
          this.users.push(user);
        }

        if (this.infiniteScroll) {
          this.infiniteScroll.complete();
          if (this.users.length == result.total) {
            this.infiniteScroll.enable(false);
          }
        }
      })
      .catch((error: any) => {
        this.toast.create({ message: 'Erro ao listar os usuários. Erro: ' + error.error, position: 'botton', duration: 3000 }).present();
      });
  }

  getUsers() {
    setTimeout(() => {
      this.page += 1;
      this.getAllUsers(this.page);
    }, 500);
  }

  openUser(id: number) {
    this.userProvider.get(id)
      .then((result: any) => {
        this.navCtrl.push('UserDetailPage', { user: result.data });
      })
      .catch((error: any) => {
        this.toast.create({ message: 'Erro ao recuperar o usuário. Erro: ' + error.error, position: 'botton', duration: 3000 }).present();
      });

  }

  openCreateUser() {
    this.navCtrl.push('UserEditPage');
  }

  openEditUser(id: number) {
    this.userProvider.get(id)
      .then((result: any) => {
        this.navCtrl.push('UserEditPage', { user: result.data });
      })
      .catch((error: any) => {
        this.toast.create({ message: 'Erro ao recuperar o usuário. Erro: ' + error.error, position: 'botton', duration: 3000 }).present();
      });
  }

  deleteUser(user: any) {
    this.userProvider.remove(user.id)
      .then((result: any) => {
        let index = this.users.indexOf(user);
        this.users.splice(index, 1);

        this.toast.create({ message: 'Usuário excluído com sucesso.', position: 'botton', duration: 3000 }).present();
      })
      .catch((error: any) => {
        this.toast.create({ message: 'Erro ao excluir o usuário. Erro: ' + error.error, position: 'botton', duration: 3000 }).present();
      });
  }
}

 

Arquivo user-list.html

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Rest Api Example
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>

  <ion-list>
    <ion-item-sliding *ngFor="let user of users">
      <ion-item (click)="openUser(user.id)">
        <ion-avatar item-start>
          <img src="{{ user.avatar }}">
        </ion-avatar>
        <h2>{{ user.first_name }} {{ user.last_name }}</h2>
      </ion-item>

      <ion-item-options side="left">
        <button ion-button color="primary" (click)="openEditUser(user.id)">
            <ion-icon name="create"></ion-icon>
            Editar
          </button>
        <button ion-button color="danger" (click)="deleteUser(user)">
            <ion-icon name="trash"></ion-icon>
            Excluir
          </button>
      </ion-item-options>
    </ion-item-sliding>

  </ion-list>

  <ion-infinite-scroll (ionInfinite)="getUsers($event)">
    <ion-infinite-scroll-content loadingSpinner="bubbles" loadingText="Aguarde...">
    </ion-infinite-scroll-content>
  </ion-infinite-scroll>

  <ion-fab right bottom>
    <button ion-fab color="light" (click)="openCreateUser()"><ion-icon name="add"></ion-icon></button>
  </ion-fab>
</ion-content>

 

Passo 8: Criar a página para incluir/alterar um usuário

ionic g page user-edit

 

Arquivo user-edit.ts

import { UsersProvider } from './../../providers/users/users';
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams, ToastController } from 'ionic-angular';

@IonicPage()
@Component({
  selector: 'page-user-edit',
  templateUrl: 'user-edit.html',
})
export class UserEditPage {
  model: User;

  constructor(public navCtrl: NavController, public navParams: NavParams, private toast: ToastController, private userProvider: UsersProvider ) {
    if (this.navParams.data.user) {
      this.model = this.navParams.data.user;
    } else {
      this.model = new User();
    }
  }

  save() {
    this.saveUser()
      .then(() => {
        this.toast.create({ message: 'Usuário salvo com sucesso.', position: 'botton', duration: 3000 }).present();
        this.navCtrl.pop();
      })
      .catch((error) => {
        this.toast.create({ message: 'Erro ao salvar o usuário. Erro: ' + error.error, position: 'botton', duration: 3000 }).present();
      })
  }

  private saveUser() {
    if (this.model.id) {
      return this.userProvider.update(this.model);
    } else {
      return this.userProvider.insert(this.model);
    }
  }

}

export class User {
  id: number;
  first_name: string;
  last_name: string;
}

 

Arquivo user-edit.html

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Rest Api Example
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>

  <ion-list>
    <ion-item>
      <ion-label stacked>Nome</ion-label>
      <ion-input type="text" name="first_name" [(ngModel)]="model.first_name"></ion-input>
    </ion-item>

    <ion-item>
      <ion-label stacked>Sobrenome</ion-label>
      <ion-input type="text" name="last_name" [(ngModel)]="model.last_name"></ion-input>
    </ion-item>
  </ion-list>

  <button ion-button block (click)="save()" color="primary">Salvar</button>

</ion-content>

 

Passo 9: Criar a pagina para exibir um usuário

ionic g page user-detail

 

Arquivo user-detail.ts

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';

@IonicPage()
@Component({
  selector: 'page-user-detail',
  templateUrl: 'user-detail.html',
})
export class UserDetailPage {
  user: any;

  constructor(public navCtrl: NavController, public navParams: NavParams) {
    this.user = this.navParams.data.user;
  }

}

 

Arquivo user-detail.html

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Rest Api Example
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <div text-center>
      <img src="{{ user.avatar }}">
    <h1>{{ user.first_name }} {{ user.last_name }}</h1>
  </div>
</ion-content>

 

Clique no botão abaixo para ver o código fonte gerado nessa aula

 

[button style=”btn-primary btn-lg” type=”link” target=”true” title=”Código fonte gerado na aula” link=”https://github.com/fabricadecodigo/IonicConsumeRestApiExample” linkrel=””]

 

Referências

 

Gostou desse artigo? Aproveite e curta e compartilhe para que mais pessoas possam também visualiza-lo!

Ainda ficou alguma dúvida ou tem alguma sugestão? Deixa aí nos comentários!