Ir para o conteúdo
Como criar um aplicativo no App Builder usando a API baseada em função?

Como criar um aplicativo no App Builder usando a API baseada em função?

Neste guia passo a passo, mostraremos o caminho para criar um aplicativo totalmente funcional e personalizável. Para os fins do artigo, usaremos código baixo e API baseada em função.

20min de leitura

Neste emocionante tutorial, levaremos suas habilidades para o próximo nível, combinando duas ferramentas poderosas –a API que construímos em nosso tutorial anterior e a plataforma App Builder TM. Ao fazer isso, criaremos um aplicativo totalmente funcional e personalizável que pode ser usado em uma variedade de plataformas.

App Builder é uma ferramenta poderosa que permite aos usuários criar aplicativos robustos com experiência mínima em codificação. Com sua interface amigável, você pode facilmente arrastar e soltar diferentes elementos para criar um aplicativo polido e com aparência profissional rapidamente e gerar o código para ele em Angular, Blazor ou Web Components.

Criando seu primeiro aplicativo em low-code App Builder

Para começar, inicie o App Builder e selecione "Criar novo aplicativo". Em seguida, navegue até a seção "Aplicativos de amostra" e escolha o Painel de RH como o design base para o seu projeto. A partir daí, você pode estender e personalizar o design para atender às suas necessidades específicas.

Create new application in App Builder

Ao abrir o exemplo, você notará que várias páginas já foram criadas para você. No entanto, para melhor atender aos requisitos do nosso projeto, você precisará fazer modificações em algumas dessas páginas e criar novas também.

make changes to your app in App Builder

Agora, vamos criar as páginas de login e registro. Navegue até a guia "Visualizações" e selecione o ícone de adição para criar uma nova página que chamaremos de "Página de registro".

create example  login and register pages in App Builder

Para manter a consistência, também podemos reutilizar o plano de fundo da página mestra para a página Registrar. Precisaremos adicionar um layout de coluna. Dentro desse layout, incluiremos um título com o conteúdo Registrar e cinco campos de entrada junto com um botão. É importante observar que todos os campos de entrada devem ser obrigatórios e devem ter o tipo apropriado especificado.

Column layout in App Builder

Em seguida, podemos criar a tela de login. Esta tela exigirá apenas dois campos de entrada – um para e-mail e outro para senha. Para simplificar o processo, podemos duplicar a página Registrar e remover quaisquer elementos desnecessários.

Example login page in App Builder

Depois que ambas as páginas forem criadas, podemos adicionar links para cada página nos botões de envio.

Add links between two pages in App Builder

A página inicial apresentará o painel, que exibirá todos os eventos que o usuário atual está participando nos componentes do cartão. Se o usuário tiver uma função de Administrador, ele também verá uma grade com todos os eventos na plataforma, permitindo que ele execute operações CRUD conforme necessário.

event actions in App Builder

Seguindo em frente, criaremos uma página para adicionar novos eventos. Esta página só estará acessível a usuários com uma função de administrador, mas abordaremos isso mais adiante no tutorial. Para cada evento, exigiremos um título, categoria, e-mails dos usuários participantes e a data do evento.

create a page for adding new events in App Builder

Além disso, precisaremos criar uma página semelhante para alterar as funções dos usuários. Semelhante à página do evento, esse recurso só poderá ser acessado por administradores. Para os fins desta demonstração, só daremos suporte à concessão de permissões de administrador a outros usuários.

create a similar page for changing the roles of users in App Builder

Depois que todas as nossas páginas forem criadas, podemos vinculá-las à navegação da barra lateral.

link thems into the sidebar navigation in App Builder

Não há necessidade de conectar a API manualmente

Felizmente, conectar manualmente nossa API é desnecessário, pois podemos fazer isso diretamente pelo App Builder carregando-a como fonte de dados. Primeiro, devemos garantir que nossa API esteja em execução, navegue até a guia Fontes de dados, selecione o ícone de adição e escolha API REST. A partir daí, temos duas opções:

  1. Para adicionar uma definição do Swagger
  2. Ou para usar a URL JSON

Para nossos propósitos, utilizaremos a abordagem Swagger e adicionaremos o URL.

Precisaremos especificar um nome para a fonte de dados e prosseguir para a próxima etapa. Em seguida, devemos identificar quais endpoints queremos incluir. Para esta demonstração, selecionaremos todos os endpoints disponíveis. No entanto, é importante observar que todos os endpoints para Eventos exigem autorização para serem bem-sucedidos. Assim, precisamos obter um token JWT de um usuário na API e adicioná-lo à guia de autorização.

Mais adiante no tutorial, vamos substituí-lo pelo token do usuário atual. Depois que a autorização for definida, podemos prosseguir para Selecionar dados, garantir que todos os campos estejam selecionados e clicar em Concluído.

Select data in App Builder

Depois que a fonte de dados for carregada com sucesso, podemos continuar a conectar a grade na página do painel. Primeiro, selecione a grade e atualize a fonte de dados no campo Dados. A partir daí, podemos adicionar operações de atualização e exclusão que serão vinculadas aos endpoints em nossa API, permitindo a modificação ao vivo dos dados por meio de interações com a grade.

Depois que todas as páginas forem criadas, podemos visualizar o aplicativo selecionando o botão verde localizado no canto superior direito. Em seguida, precisamos baixar o aplicativo para facilitar a personalização.

preview the application by selecting the green button 

Execute o aplicativo criado localmente

Depois que o aplicativo for baixado, descompacte o projeto e abra-o no Visual Studio Code. No terminal, execute "npm install" seguido de "npm run start" para iniciar a execução do aplicativo.

O próximo passo é conectar as páginas de login e registro com nossa API. Para conseguir isso, devemos adicionar funções que chamarão a API. Essas funções devem ser adicionadas ao arquivo services/hrdashboard.service.ts onde todos os nossos serviços estão armazenados. Devemos adicionar mais duas funções, uma para login e outra para registro.

…
public registerUser(data: any, contentType: string = 'application/json-patch+json, application/json, text/json, application/*+json') {
    const options = {
    headers: {
        'content-type': contentType
    }
};
const body = data;
    return this.http.post(`${API_ENDPOINT}/Auth/Register`, body, options);
}
  public loginUser(data: any, contentType: string = 'application/json-patch+json, application/json, text/json, application/*+json') {
    const options = {
      headers: {
        'content-type': contentType
      }
    };
    const body = data;
    return this.http.post(`${API_ENDPOINT}/Auth/Login`, body, options);
  }
…

Na próxima etapa, navegue até o arquivo register-page.component.ts e adicione associações para as propriedades de entrada. Crie uma variável para armazenar mensagens de erro e mostrar validações para o usuário se a solicitação não for bem-sucedida. Além disso, adicione uma função que será acionada quando o formulário for enviado. Essa função verificará se todos os campos são obrigatórios e, em caso afirmativo, armazenará o token JWT em localStorage e navegará até a home page. Se algum campo estiver ausente, a função deverá exibir uma mensagem de erro para o usuário.

export class RegisterPageComponent {
  email: number;
  firstName: string;
  lastName: string;
  password: string;
  confirmedPassword: string;
  errorMessage: string;
 
  constructor(
    private hRAPIService: HRAPIService,
    private router: Router
  ) { }
  onSubmit(event) {
    event.preventDefault();
    if (this.password !== this.confirmedPassword) {
      this.errorMessage = 'Passwords should match!'
    }
    else if (this.email && this.firstName && this.lastName && this.password) {
      this.hRAPIService.registerUser({ firstName: this.firstName, lastName: this.lastName, email: this.email, password: this.password, confirmedPassword: this.confirmedPassword })
      .subscribe({
        next: (response) => {
          localStorage.setItem('hr_app_token', response['value']);
          this.router.navigateByUrl('/');
        },
        error: (error) => {
          console.log(error)
          this.errorMessage = error.error["errors"] ? Object.values(error.error["errors"])[0] as string : error.error;
        }
      });
    }
    else {
      this.errorMessage = "All fields are required!";
    }
  }
}

Também precisamos atualizar register-page.component.html para vincular as entradas.

<div class="column-layout background"></div>
<div class="column-layout group">
    <h2 class="h2">
            Register
    </h2>
    <p class="error-message">{{errorMessage}}</p>
    <igx-input-group type="border" class="input">
            <input type="text" required igxInput [(ngModel)]="firstName"/>
            <label igxLabel>FirstName</label>
    </igx-input-group>
    <igx-input-group type="border" class="input_1">
            <input type="text" required igxInput [(ngModel)]="lastName"/>
            <label igxLabel>Lastname</label>
    </igx-input-group>
    <igx-input-group type="border" class="input_1">
            <input type="email" required igxInput [(ngModel)]="email"/>
            <label igxLabel>Email</label>
    </igx-input-group>
    <igx-input-group type="border" class="input_1">
            <input type="password" required igxInput [(ngModel)]="password"/>
            <label igxLabel>Password</label>
    </igx-input-group>
    <igx-input-group type="border" class="input_1">
            <input type="password" required igxInput [(ngModel)]="confirmedPassword"/>
            <label igxLabel>Confirm password</label>
    </igx-input-group>
      <button (click)="onSubmit($event)" igxButton="raised" igxRipple class="button">
        Register
      </button>
</div>

Para estilizar o errorMessage, precisamos adicionar os estilos no register-page.component.scss.

.error-message {
  text-align: center;
  margin: 2rem 0;
  font-weight: bold;
  color: red;
}

Assim como a página de registro, precisamos criar propriedades para vincular as entradas e uma função que é executada quando o formulário é enviado para a página de login. Esta função chamará o serviço de login para autenticar o usuário enviando seu e-mail e senha. Se a autenticação for bem-sucedida, ele armazenará o token jwt no localStorage e navegará até a home page. Se falhar, ele exibirá uma mensagem de erro para o usuário. Também precisamos atualizar o login-page.component.html para vincular as entradas.

login.page.component.ts

export class LoginComponent {
  email: number;
  firstName: string;
  lastName: string;
  password: string;
  confirmedPassword: string;
  errorMessage: string;
 
  constructor(
    private hRAPIService: HRAPIService,
    private router: Router
  ) { }
  onSubmit(event) {
    event.preventDefault();
    if (this.email && this.password) {
      this.hRAPIService.loginUser({ email: this.email, password: this.password })
        .subscribe({
          next: (response) => {
            localStorage.setItem('hr_app_token', response['value']);
            this.router.navigateByUrl('/');
          },
          error: (error) => {
            console.log(error)
            this.errorMessage = error.error["errors"] ? Object.values(error.error["errors"])[0] as string : error.error;
          }
        });
    }
    else {
      this.errorMessage = "All fields are required!";
    }
  }
}

login-page.component.html

<div class="column-layout background"></div>
<div class="column-layout group">
    <h2 class="h2">
            Login
    </h2>
    <p class="error-message">{{errorMessage}}</p>
    <igx-input-group type="border" class="input">
            <input type="text" igxInput [(ngModel)]="email"/>
            <label igxLabel>Email</label>
    </igx-input-group>
    <igx-input-group type="border" class="input_1">
            <input type="password" igxInput [(ngModel)]="password"/>
            <label igxLabel>Password</label>
    </igx-input-group>
      <button (click)="onSubmit($event)" igxButton="raised" igxRipple class="button">
        Login
      </button>
</div>

Precisamos criar um AuthService que nos ajudará a decodificar o token, verificar se o usuário tem determinada função e remover a sessão. Para isso, criaremos um novo arquivo chamado auth.service.ts, que devemos importar para o app.module.ts. Para decodificar os tokens, precisamos instalar o pacote jwt-decode.

import { Injectable } from "@angular/core";
import jwt_decode from 'jwt-decode
';
type Token = {
    Id?: string,
    email?: string,
    firstName?: string,
    exp?: number,
    role?: string,
    sub?: string,
}
@Injectable({
    providedIn: 'root'
  })
  export class AuthService {
    decodeToken(token) {
        return jwt_decode(token);
    }
    getEmail() {
        const token = localStorage.getItem('hr_app_token');
        const {email}: Token = this.decodeToken(token);
        return email;
    }
    isAuthenticated() {
        const token = localStorage.getItem('hr_app_token');
        if (token) {
            const {email, role}: Token = this.decodeToken(token);
            return email != null && role != null;
        }
        return false;
    }
    isAdmin() {
        const token = localStorage.getItem('hr_app_token');
        const {role}: Token = this.decodeToken(token);
        return this.isAuthenticated() && role === "Administrator";
    }
    logout() {
        localStorage.removeItem('hr_app_token');
    }
}

Implementando proteções para endpoints para melhor segurança

Para aumentar a segurança, precisamos implementar proteções para nossos endpoints. Vamos criar três guardas, começando com o anonymous-guard.ts. Essa proteção garante que as páginas de login e registro sejam acessíveis apenas a usuários que não estão conectados. Se um usuário que já está logado tentar acessar essas páginas, ele deve ser redirecionado para a página inicial.

Para implementar essa proteção, criaremos uma pasta de guardas no diretório do aplicativo e criaremos um novo arquivo chamado anonymous-guard.ts.

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from '../services/auth.service';
 
@Injectable({
    providedIn: 'root'
})
export class AnonymousGuard implements CanActivate {
    constructor(private router: Router,
        private authService: AuthService) { }
    canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): Observable
<boolean | UrlTree>
| Promise
<boolean | UrlTree>
| boolean | UrlTree {
        if (!this.authService.isAuthenticated()) {
            return true;
        }
        return this.router.parseUrl("/");
    }
}

A próxima guarda que precisamos implementar é chamada de auth-guard. Essa proteção garantirá que determinadas páginas sejam acessíveis apenas a usuários autenticados.

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from '../services/auth.service';
@Injectable({
    providedIn: 'root'
})
export class AuthGuard implements CanActivate {
    constructor(private router: Router,
        private authService: AuthService) { }
    canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): Observable
<boolean | UrlTree>
| Promise
<boolean | UrlTree>
| boolean | UrlTree {
        if (this.authService.isAuthenticated()) {
            return true;
        }
        return this.router.parseUrl("/login-page");
    }
}

O terceiro guarda, chamado admin-guard, restringirá o acesso a determinadas páginas apenas a usuários com a função de Administrador.

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from '../services/auth.service';
 
@Injectable({
    providedIn: 'root'
  })
export class AdminGuard implements CanActivate {
    constructor(private router: Router,
        private authService: AuthService) { }
 
    canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): Observable
<boolean | UrlTree>
| Promise
<boolean | UrlTree>
| boolean | UrlTree {
        if (this.authService.isAdmin()) {
            return true;
        }
        return this.router.parseUrl("/login-page");
    }
}

Depois de criar nossos guardas, precisamos aplicá-los às rotas apropriadas. Para fazer isso, abra app-routing.module.ts e adicione uma propriedade canActivate a cada rota junto com o guard correspondente.

Por exemplo, as páginas de login e registro devem ser acessíveis apenas a usuários que ainda não estão logados, por isso adicionamos o AnonymousGuard às suas rotas. A página mestra deve ser acessível apenas a usuários autenticados, portanto, adicionamos o AuthGuard a essa rota. Por fim, as páginas add-event e add-role devem ser acessíveis apenas a usuários com função de administrador, portanto, anexamos o AdminGuard a essas rotas.

export const routes: Routes = [
  { path: '', redirectTo: 'master-page', pathMatch: 'full' },
  { path: 'error', component: UncaughtErrorComponent },
  { path: 'master-page', loadChildren: () => import('./master-page/master-page.module').then(m => m.MasterPageModule), canActivate: [AuthGuard]},
  { path: 'register-page', component: RegisterPageComponent, data: { text: 'Register Page' }, canActivate: [AnonymousGuard]},
  { path: 'login-page', component: LoginPageComponent, data: { text: 'Login' }, canActivate: [AnonymousGuard]},
  { path: 'add-event', component: AddEventComponent, data: { text: 'Add Event' }, canActivate: [AdminGuard]},
  { path: 'add-role-to-user', component: AddRoleToUserComponent, data: { text: 'Add Role' }, canActivate: [AdminGuard]},
  { path: '**', component: PageNotFoundComponent } // must always be last
];

Para garantir que os usuários sem permissões não possam acessar determinados links na navegação, devemos ocultá-los. Para fazer isso, podemos adicionar a diretiva *ngIf="isUserAdmin()" aos elementos igx-list-item que correspondem às opções ADD EVENT e ADD ROLE TO USER no arquivo master-page.component.html. Ao fazer isso, garantimos que esses links sejam visíveis apenas para usuários com privilégios de administrador.

Para implementar essa funcionalidade, também precisaremos atualizar o arquivo master-page.component.ts. Podemos criar uma função para verificar se o usuário atual é um administrador e usá-la na diretiva *ngIf que adicionamos anteriormente.

Além disso, precisamos criar uma função de logout e anexá-la ao evento de clique do igx-list-item que corresponde ao link LOGOUT. Isso permitirá que os usuários saiam do sistema quando necessário.

Deve ficar assim:

…
<igx-list-item [isHeader]="false" routerLink="/master-page/add-role-to-user" *ngIf="isUserAdmin()">
<span igxListThumbnail>
    <igx-avatar icon="people" [roundShape]="true" class="avatar_1"></igx-avatar>
</span>
<span igxListLine>
    <p class="ig-typography__subtitle-2 text_3">
              ADD ROLE TO USER
    </p>
</span>
</igx-list-item>
<igx-list-item [isHeader]="false" routerLink="/master-page/add-event" *ngIf="isUserAdmin()">
<span igxListThumbnail>
    <igx-avatar icon="stars" [roundShape]="true" class="avatar_1"></igx-avatar>
</span>
<span igxListLine>
    <p class="ig-typography__subtitle-2 text_3">
              ADD EVENT
    </p>
</span>
</igx-list-item>
<igx-list-item [isHeader]="false" (click)="logout()">
<span igxListThumbnail>
    <igx-avatar icon="exit_to_app" [roundShape]="true" class="avatar_1"></igx-avatar>
</span>
<span igxListLine>
    <p class="ig-typography__subtitle-2 text_3">
              LOGOUT
    </p>
</span>
</igx-list-item>
…
export class MasterPageComponent {
  public listItemVisible = false;
 
  constructor(private authService: AuthService,
    private router: Router){}
  isUserAdmin() {
    return this.authService.isAdmin();
  }
  logout() {
    this.authService.logout();
    this.router.navigateByUrl('/login-page');
  }
}

Nossa próxima etapa é estabelecer uma conexão entre a página de adição de evento e a API. Para conseguir isso, precisamos criar uma nova função no serviço HRDashboard que lidará com a solicitação HTTP POST para criar um novo evento.

public postEvent(data: any, contentType: string = 'application/json-patch+json, application/json, text/json, application/*+json'): Observable<any>{
    const options = {
      headers: {
        'content-type': contentType,
        Authorization: `Bearer ${localStorage.getItem('hr_app_token')}`,
      },
    };
    const body = data;
    return this.http.post(`${API_ENDPOINT}/Event`, body, options);
  }

Além disso, no arquivo add-event.component.ts, precisamos definir propriedades que vincularão os campos de entrada ao componente e adicionarão a função onSubmit. Como os e-mails serão recebidos em um único campo separado por vírgulas, precisaremos dividi-los antes de enviá-los para a API.

export class AddEventComponent {
  emails: string;
  category: string;
  title: string;
  date: string;
  errorMessage: string;
 
  constructor(private hrApiService: HRDashboardService,
    private router: Router) {}
  onSubmit(event) {
    event.preventDefault();
    const splitEmails = this.emails.split(', ');
    if (this.emails && this.category && this.title && this.date) {
      this.hrApiService.postEvent({ category: this.category, title: this.title, date: this.date, userEmails: splitEmails})
        .subscribe({
          next: (response) => {
              this.router.navigateByUrl('/');
          },
          error: (error) => {
            console.log(error)
            this.errorMessage = error.error["errors"] ? Object.values(error.error["errors"])[0] as string : error.error;
          }
        });
    }
    else {
      this.errorMessage = "All fields are required!";
    }
  }
}

Atualizando o painel

Depois que as etapas acima forem concluídas, podemos prosseguir para a atualização do painel. Antes disso, devemos modificar o HRDashboardService para substituir todas as ocorrências de 'Bearer <auth-token>' por Bearer ${localStorage.getItem('hr_app_token')} em solicitações que possuem um cabeçalho de autorização. Isso garante que busquemos dados usando o token JWT correto.

Além disso, precisamos adicionar uma nova função ao HRDashboardService que busca apenas os eventos relacionados ao usuário atual.

public getMyEvents(): Observable<any>{
    const options = {
      headers: {
        Authorization: `Bearer ${localStorage.getItem('hr_app_token')}`,
      },
    };
    return this.http.get(`${API_ENDPOINT}/Event`, options);
  }

Exibindo eventos do usuário na página do painel

Em seguida, exibiremos os eventos do usuário na página do painel usando os componentes do cartão. Para conseguir isso, precisaremos abrir o arquivo dashboard.component.html e usar a diretiva *ngFor para renderizar componentes igx-card com base na propriedade myEvents, que conterá os eventos para o usuário atual. Além disso, podemos usar *ngIf="isUserAdmin()" para garantir que a grade seja visível apenas para os administradores. Além disso, devemos atualizar a saudação no painel para exibir o e-mail do usuário atual, como "Bom dia, {{email}}!".

O arquivo resultante deve ser semelhante ao seguinte:

<div class="row-layout group">
    <div class="column-layout group_1">
        <div class="column-layout group_2">
            <div class="row-layout group_3">
                <div class="column-layout group_4">
                    <h5 class="h5">
                          Good Morning, {{email}}!
                    </h5>
                    <p class="text">
                           Your Highlights
                    </p>
                </div>
            </div>
            <div class="row-layout group_5">
                <igx-card *ngFor="let event of myEvents; index as i;"type="outlined" class="card">
                    <igx-card-media height="200px">
                                    <img src="/assets/Illustration1.svg" class="image" />
                    </igx-card-media>
                    <igx-card-header>
                        <h3 igxCardHeaderTitle>
                                 {{event.title}}
                        </h3>
                        <h5 igxCardHeaderSubtitle>
                                 {{event.category}}
                        </h5>
                        <h5 igxCardHeaderSubtitle>
                                 {{event.date}}
                        </h5>
                    </igx-card-header>
                </igx-card>
            </div>
        </div>
        <div class="row-layout group_6" *ngIf="isUserAdmin()">
            <div class="column-layout group_7">
                <h6 class="h6">
                      All Events
                </h6>
                        <igx-grid [data]="hRDashboardEventAll" primaryKey="id" displayDensity="cosy" [rowEditable]="true" [allowFiltering]="true" filterMode="excelStyleFilter" (rowEditDone)="eventRowEditDone($event)" (rowDeleted)="eventRowDeleted($event)" class="grid">
                          <igx-column field="id" dataType="string" header="id" [sortable]="true" [selectable]="false"></igx-column>
                          <igx-column field="title" dataType="string" header="title" [sortable]="true" [selectable]="false"></igx-column>
                          <igx-column field="category" dataType="string" header="category" [sortable]="true" [selectable]="false"></igx-column>
                          <igx-column field="date" dataType="date" header="date" [sortable]="true" [selectable]="false"></igx-column>
                <igx-action-strip>
                    <igx-grid-pinning-actions></igx-grid-pinning-actions>
                    <igx-grid-editing-actions [addRow]="true"></igx-grid-editing-actions>
                </igx-action-strip>
                        </igx-grid>
            </div>
        </div>
    </div>
</div>

No arquivo dashboard.component.ts, precisaremos definir duas propriedades: myEvents e email. Essas propriedades devem ser preenchidas com os dados relevantes na função ngOnInit.

export class DashboardComponent implements OnInit {
  public hRDashboardEventAll: any = null;
  myEvents: any;
  email: any;
  constructor(
    private hRDashboardService: HRDashboardService,
    private authService: AuthService,
  ) {}
  ngOnInit() {
    this.hRDashboardService.getEventAll().subscribe(data => this.hRDashboardEventAll = data);
    this.hRDashboardService.getMyEvents().subscribe(data => this.myEvents = data);
    this.email = this.authService.getEmail();
  }
  public isUserAdmin() {
    return this.authService.isAdmin();
  }
…

Agora podemos ver no painel todos os eventos do usuário atual e, na grade, se o usuário for Administrador, ele pode atualizar e excluir as entradas de lá.

Conectando a função Adicionar à página de usuário e à API

A etapa final é estabelecer uma conexão entre a função de adição à página de usuário e a API. Para conseguir isso, precisaremos criar uma função dentro do serviço HRDashboard que busque dados do usuário da API e preencha o componente de seleção de e-mails.

public getUsers(): Observable
<any>
{
    const options = {
      headers: {
        Authorization: `Bearer ${localStorage.getItem('hr_app_token')}`,
      },
    };
    return this.http.get(`${API_ENDPOINT}/User`, options);
  }
 
  public changeUserRole(data: any): Observable
<any>
{
    const options = {
      headers: {
        Authorization: `Bearer ${localStorage.getItem('hr_app_token')}`,
      },
    };
    const body = data;
    return this.http.post(`${API_ENDPOINT}/User/Role`, body, options);
  }

Assim que terminarmos com isso, podemos ir até add-role-to-user.component.ts e buscá-los. Devemos também criar a função onSubmit que chamará changeUserRole do serviço HRDashboard. O resultado final deve ficar assim:

export class AddRoleToUserComponent {
  users: any;
  email: string;
  role: string;
  constructor(private hrApiService: HRDashboardService,
    private router: Router) { }
  ngOnInit() {
    this.hrApiService.getUsers()
      .subscribe(data => {
        this.users = data;
      });
  }
 
  onSubmit(event) {
    event.preventDefault();
    if (this.email && this.role) {
      this.hrApiService.changeUserRole({ email: this.email, role: this.role})
        .subscribe({
          next: (response) => {
              this.router.navigateByUrl('/');
          },
          error: (error) => {
            console.log(error)
          }
        });
    }
  }
}
<div class="row-layout group">
    <div class="column-layout group_1">
        <h2 class="h2">
                  Add Role to user
        </h2>
        <div class="row-layout group_2">
                  <igx-select type="border" class="select"[(ngModel)]="email">
            <igx-select-item *ngFor="let user of users; index as i;" value="{{user.email}}">
                          {{user.email}}
            </igx-select-item>
                    <label igxLabel>Email</label>
                  </igx-select>
                  <igx-select type="border" class="select"[(ngModel)]="role">
            <igx-select-item value="Administrator">
                          Administrator
            </igx-select-item>
                    <label igxLabel>Role</label>
                  </igx-select>
        </div>
            <button igxButton="raised" (click)="onSubmit($event)" igxRipple class="button">
              Submit
            </button>
    </div>
</div>

Depois de seguir as etapas necessárias e concluir as tarefas necessárias, agora temos um aplicativo totalmente funcional que foi construído com App Builder e integrado a uma API. Isso significa que nosso aplicativo agora é capaz de se comunicar com a API, permitindo que os usuários executem várias ações, como criar novos eventos, adicionar funções aos usuários e visualizar seu painel personalizado.  Você pode visualizar todo o código da demonstração no GitHub.

Como criar um aplicativo no App Builder usando a API baseada em função?
Solicite uma demonstração