コンテンツにスキップ
ロールベース API を使用してApp Builderでアプリを作成する方法は?

ロールベース API を使用してApp Builderでアプリを作成する方法は?

このステップバイステップ ガイドでは、完全に機能し、カスタマイズ可能なアプリを作成する方法を紹介します。この記事では、ローコードとロールベースの API を使用します。

20分で読めます

このエキサイティングなチュートリアルでは、前のチュートリアルで構築したAPIApp Builder TMプラットフォームという2つの強力なツールを組み合わせて、スキルを次のレベルに引き上げます。そうすることで、さまざまなプラットフォームで使用できる完全に機能し、カスタマイズ可能なアプリケーションを作成します。

App Builderは、ユーザーが最小限のコーディング経験で堅牢なアプリケーションを作成できる強力なツールです。ユーザーフレンドリーなインターフェイスにより、さまざまな要素を簡単にドラッグアンドドロップして、洗練されたプロフェッショナルな外観のアプリケーションをすぐに作成し、Angular、Blazor、またはWeb Componentsでそのコードを生成できます。

ローコードApp Builderで初めてのアプリケーションの作成

まず、App Builderを起動し、「新しいアプリケーションの作成」を選択します。次に、「サンプルアプリ」セクションに移動し、プロジェクトの基本設計としてHRダッシュボードを選択します。そこから、特定のニーズに合わせてデザインを拡張およびカスタマイズできます。

Create new application in App Builder

サンプルを開くと、いくつかのページが既に作成されていることがわかります。ただし、プロジェクトの要件により適合させるには、これらのページの一部を変更し、新しいページも作成する必要があります。

make changes to your app in App Builder

それでは、ログインページと登録ページを作成しましょう。「ビュー」タブに移動し、プラスアイコンを選択して、「ページの登録」という名前の新しいページを作成します。

create example  login and register pages in App Builder

一貫性を維持するために、マスター ページの背景を [登録] ページにも再利用できます。列レイアウトを追加する必要があります。このレイアウト内には、コンテンツの登録を含むタイトルと、ボタンと共に 5 つの入力フィールドを含めます。すべての入力フィールドは必須であり、適切なタイプを指定する必要があることに注意してください。

Column layout in App Builder

次に、ログイン画面を作成します。この画面には、電子メール用とパスワード用の2つの入力フィールドのみが必要です。プロセスを簡素化するために、登録ページを複製し、不要な要素を削除できます。

Example login page in App Builder

両方のページが作成されたら、送信ボタンの下に各ページへのリンクを追加できます。

Add links between two pages in App Builder

ホームページにはダッシュボードが表示され、現在のユーザーが参加しているすべてのイベントがカードコンポーネントに表示されます。ユーザーが管理者ロールを持っている場合は、プラットフォーム上のすべてのイベントを含むグリッドも表示され、必要に応じて CRUD 操作を実行できます。

event actions in App Builder

今後は、新しいイベントを追加するためのページを作成します。このページには管理者ロールを持つユーザーのみがアクセスできますが、これについてはチュートリアルの後半で説明します。イベントごとに、タイトル、カテゴリ、参加するユーザーのメールアドレス、およびイベントの日付が必要です。

create a page for adding new events in App Builder

さらに、ユーザーの役割を変更するための同様のページを作成する必要があります。イベントページと同様に、この機能には管理者のみがアクセスできます。このデモでは、他のユーザーに管理者権限を付与することのみをサポートします。

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

すべてのページが作成されたら、それらをサイドバーのナビゲーションにリンクできます。

link thems into the sidebar navigation in App Builder

APIを手動で接続する必要はありません

幸いなことに、APIをデータソースとしてアップロードすることで、App Builderから直接接続できるため、APIを手動で接続する必要はありません。まず、API が実行されていることを確認してから、 [データソース] タブに移動し、プラス アイコンを選択して、 [REST API] を選択します。そこから、2つのオプションがあります。

  1. Swagger定義を追加するには
  2. またはJSON URLを使用する

ここでは、Swagger アプローチを利用して URL を追加します。

データソースの名前を指定して、次の手順に進む必要があります。次に、どのエンドポイントを含めるかを特定する必要があります。このデモでは、使用可能なすべてのエンドポイントを選択します。ただし、イベントのすべてのエンドポイントが成功するには承認が必要であることに注意することが重要です。したがって、APIでユーザーからJWTトークンを取得し、それを[承認]タブに追加する必要があります。

チュートリアルの後半で、これを現在のユーザーのトークンに置き換えます。認証を設定したら、[データの選択]に進み、すべてのフィールドが選択されていることを確認して、[完了]をクリックします。

Select data in App Builder

データソースが正常にアップロードされたら、ダッシュボード ページでグリッドの接続に進むことができます。まず、グリッドを選択し、[データ] フィールドからデータソースを更新します。そこから、API のエンドポイントにリンクされる更新操作と削除操作を追加して、グリッドとの対話を通じてデータをライブで変更することができます。

すべてのページが作成されたら、右上隅にある緑色のボタンを選択してアプリケーションをプレビューできます。次に、アプリケーションをダウンロードして、さらにカスタマイズを容易にする必要があります。

preview the application by selecting the green button 

作成したアプリをローカルで実行する

アプリケーションがダウンロードされたら、プロジェクトを解凍し、Visual Studio Code で開きます。ターミナルで、「npm install」を実行してから「npm run start」を実行して、アプリケーションの実行を開始します。

次のステップは、ログインページと登録ページをAPIに接続することです。これを実現するには、API を呼び出す関数を追加する必要があります。これらの関数は、すべてのサービスが保存されている services/hrdashboard.service.ts ファイルに追加する必要があります。さらに 2 つの関数、1 つはログイン用、もう 1 つは登録用を追加する必要があります。

…
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);
  }
…

次の手順では、register-page.component.ts ファイルに移動し、入力プロパティのバインディングを追加します。エラーメッセージを格納し、要求が失敗した場合に検証をユーザーに表示する変数を作成します。また、フォームが送信されたときにトリガーされる関数を追加します。この関数は、すべてのフィールドが必須かどうかをチェックし、必須の場合は、JWTトークンをlocalStorageに保存して、ホームページに移動します。フィールドが欠落している場合、関数はユーザーにエラー メッセージを表示する必要があります。

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!";
    }
  }
}

また、入力をバインドするためにregister-page.component.htmlを更新する必要があります。

<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>

errorMessageのスタイルを設定するには、register-page.component.scssにスタイルを追加する必要があります。

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

登録ページと同様に、入力をバインドするプロパティと、ログインページにフォームが送信されたときに実行される関数を作成する必要があります。この関数は、ログインサービスを呼び出し、電子メールとパスワードを送信してユーザーを認証します。認証が成功すると、jwtトークンがlocalStorageに保存され、ホーム ページに移動します。失敗した場合は、ユーザーにエラーメッセージが表示されます。また、入力をバインドするためにlogin-page.component.htmlを更新する必要があります。

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>

トークンをデコードし、ユーザーが特定のロールを持っているかどうかを確認し、セッションを削除するのに役立つAuthServiceを作成する必要があります。これを行うには、auth.service.tsという名前の新しいファイルを作成し、app.module.tsにインポートする必要があります。トークンをデコードするには、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');
    }
}

セキュリティ向上のためのエンドポイントのガードの実装

セキュリティを強化するには、エンドポイントにガードを実装する必要があります。anonymous-guard.tsから始めて、3人の警備員を作成します。このガードにより、ログイン ページと登録ページは、ログインしていないユーザーのみがアクセスできるようになります。すでにログインしているユーザーがこれらのページにアクセスしようとすると、ホームページにリダイレクトされます。

このガードを実装するには、appディレクトリ内にguardsフォルダーを作成し、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("/");
    }
}

次に実装する必要があるガードは、auth-guardと呼ばれます。このガードにより、認証されたユーザーのみが特定のページにアクセスできるようになります。

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");
    }
}

admin-guard と呼ばれる 3 番目のガードは、特定のページへのアクセスを管理者ロールを持つユーザーのみに制限します。

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");
    }
}

ガードを作成したら、適切なルートに適用する必要があります。これを行うには、app-routing.module.tsを開き、対応するガードとともに各ルートにcanActivateプロパティを追加します。

たとえば、ログインページと登録ページは、まだログインしていないユーザーのみがアクセスできる必要があるため、ルートにAnonymousGuardを追加します。マスター ページは認証されたユーザーのみがアクセスできる必要があるため、そのルートにAuthGuardを追加します。最後に、add-event ページと add-role ページは、管理者ロールを持つユーザーのみがアクセスできるようにする必要があるため、これらのルートにAdminGuardをアタッチします。

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
];

アクセス許可のないユーザーがナビゲーション内の特定のリンクにアクセスできないようにするには、それらを非表示にする必要があります。これを行うには、*ngIf="isUserAdmin()"ディレクティブを、master-page.component.html ファイルの ADD EVENT および ADD ROLE TO USER オプションに対応するigx-list-item要素に追加します。そうすることで、これらのリンクは管理者権限を持つユーザーにのみ表示されます。

この機能を実装するには、master-page.component.tsファイルも更新する必要があります。現在のユーザーが管理者であるかどうかを確認する関数を作成し、前に追加した*ngIfディレクティブで使用できます。

さらに、ログアウト関数を作成し、LOGOUT リンクに対応するigx-list-itemのクリック イベントにアタッチする必要があります。これにより、ユーザーは必要に応じてシステムからログアウトできます。

次のようになります。

…
<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');
  }
}

次のステップは、イベントの追加ページとAPI間の接続を確立することです。これを実現するには、新しいイベントを作成するためのHTTP POSTリクエストを処理する新しい関数をHRDashboardサービス内に作成する必要があります。

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);
  }

さらに、add-event.component.tsファイルでは、入力フィールドをコンポーネントにバインドするプロパティを定義し、onSubmit関数を追加する必要があります。メールはカンマで区切られた単一のフィールドで受信されるため、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!";
    }
  }
}

ダッシュボードの更新

上記の手順が完了したら、ダッシュボードの更新に進むことができます。これに先立って、HRDashboardServiceを変更して、認可ヘッダーを持つリクエストで「Bearer <auth-token>」のすべての出現箇所をBearer ${localStorage.getItem('hr_app_token')}に置き換える必要があります。これにより、正しいJWTトークンを使用してデータを取得することができます。

さらに、現在のユーザーに関連するイベントのみを取得する新しい関数をHRDashboardServiceに追加する必要があります。

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

ダッシュボードページでのユーザのイベントの表示

次に、カードコンポーネントを使用して、ユーザーのイベントをダッシュボードページに表示します。これを実現するには、dashboard.component.html ファイルを開き、*ngForディレクティブを使用して、現在のユーザーのイベントを含むmyEventsプロパティに基づいてigx-cardコンポーネントをレンダリングする必要があります。さらに、*ngIf="isUserAdmin()"を使用して、グリッドが管理者にのみ表示されるようにすることができます。さらに、ダッシュボードの挨拶を更新して、「おはようございます、{{email}}!」などの現在のユーザーのメールを表示する必要があります。

結果のファイルは次のようになります。

<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>

dashboard.component.tsファイルでは、myEventsemailの 2 つのプロパティを定義する必要があります。これらのプロパティには、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();
  }
…

これで、現在のユーザーのすべてのイベントをダッシュボードに表示でき、ユーザーが管理者の場合はグリッドから、そこからエントリを更新および削除できます。

Add Role To User ページと API の接続

最後のステップは、ユーザーへのロールの追加ページとAPIの間の接続を確立することです。これを実現するには、APIからユーザーデータを取得し、メール選択コンポーネントに入力する関数をHRDashboardサービス内に作成する必要があります。

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);
  }

それが終わったら、add-role-to-user.component.tsに行ってそれらを取りに行くことができます。また、HRDashboardサービスからchangeUserRoleを呼び出すonSubmit関数を作成する必要があります。最終結果は次のようになります。

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>

必要な手順を実行し、必要なタスクを完了すると、App Builderで構築され、APIと統合された完全に機能するアプリケーションができました。つまり、アプリケーションはAPIと通信できるようになり、ユーザーは新しいイベントの作成、ユーザーへのロールの追加、パーソナライズされたダッシュボードの表示など、さまざまなアクションを実行できるようになりました。デモのコード全体は GitHub で見ることができます

ロールベース API を使用してApp Builderでアプリを作成する方法は?
デモを予約