インフラジスティックス・ジャパン株式会社Blog

インフラジスティックス・ジャパン株式会社のチームメンバーが技術トレンド、製品Tips、サポート情報からライセンス、日々の業務から感じることなど、さまざまなトピックについてお伝えするBlogです。

Ignite UI for Angular と CData API Server を使って Salesforce データをグリッドに表示しよう

https://cdn-ak.f.st-hatena.com/images/fotolife/I/IGJP/20190918/20190918211058.png

Angular はデータバインディング、ルーティング、サービスなど業務用のモダン Web アプリケーション構築に適している Web アプリケーションフレームワークです。 この記事では CData Software Japan が提供する CData API Server と連携し、取得したデータを Ignite UI for Angularデータグリッドへ表示する方法をご紹介します。

CData API Server の設定

まずは下記の記事を参考に API サーバーのインストールをを完了してください。

Azure SQL Database を CData API Server で Web API(OData)アクセスできるように構成してみる その1 Web Apps 構成編

接続情報の設定

「設定」→「接続」→「+接続の追加」をクリックし、接続するソースを選択します。

接続の追加

このスクリーンショットでは「Salesforce」を選択しています。

Salesforceを選択

次に接続情報を入力します。「Salesforce」の場合は、次の情報を入力します。

項目
User ログインするユーザーアカウント
Password ログインするユーザーアカウントのパスワード
Security Token Salesforce から取得した API 接続用のトークン

接続ユーザーの情報を登録

リソースの定義

接続情報を設定したのち、データソースから取得したいリソースを定義します。

「設定」→「リソース」→「リソースを追加」をクリックします。

リソースの追加

先程追加した接続先を選択します。

接続先を選択

取得したいテーブルを選択し、次へをクリックします。

取得するテーブルを選択

「リソースの編集」はデフォルトのままで OK です。これで設定を保存すれば、リソースの構成は完了です。API サーバーから Salesforce に接続できるようになりました。

アプリケーションから API サーバーに接続するユーザーを定義する

最後に API アクセス用のユーザーを追加し、認証トークンを控えておきます。

ユーザーは「設定」→「ユーザー」画面から追加可能です。

APIアクセス用のユーザー

クロスオリジンリソースシェアリング (CORS)

Ajax などのアプリケーションから複数の異なるドメインへのアクセス・接続を行う場合、クロスサイトスクリプティングの制限に抵触する可能性があります。

その場合は、「設定」→「サーバー」タブ内の「クロスオリジンリソースシェアリング (CORS)」の設定を行います。

項目
クロスオリジンリソースシェアリング (CORS)を有効化する ON
すべてのドメインを '*' なしで許可 ON
Access-Control-Allow-Methods: GET,PUT,POST,OPTIONS
Access-Control-Allow-Headers: authorization

CORS設定

全ての設定を終えたのち、「Save Changes」ボタンをクリックして保存します。

Ignite UI for Angular を組み込んだ Angular プロジェクトを準備

IgxGridを利用するためには、Ignite UI for Angular パッケージの組み込みやモジュールの参照が必要になります。 下記に必要パッケージを組み込んだ状態のサンプルプロジェクトを公開しています。

GitHub - IG-JP/IgxGridBasicDemo

リポジトリをクローンしたのち、下記コマンドで現時点の実行結果を確認できます。

npm install
npm start

左側のナビゲーションから igxGrid1 を選択するとローカルデータがバインドされた IgxGrid が表示されます。

f:id:pnishimura:20191202154541p:plain

API サーバーからデータを取得するサービスを作成

Angular では API サーバーのような外部リソースからデータを取得する場合、サービスを作成し View とは直接関係のないデータアクセス部分を分離させることが一般的です。 ng generateコマンドを利用し、ApiServerService を作成します。

ng generate service service/ApiServer

service フォルダーと api-server.service.spec.ts, api-server.sergice.ts ファイルがそれぞれ作成されます。

レスポンスおよび顧客データのインターフェースを宣言

API サーバーから顧客情報が value に保存されたデータが返されるため、レスポンスおよび、顧客データのインターフェースを作成された ApiServerService クラスのスコープの外側に宣言します。

//api-server.service.ts

// response
interface CustomersResponse {
  value: Customer[];
}

// Customer
export interface Customer {
  rowguid: string; // "3f5ae95e-b87d-4aed-95b4-c3797afcb74f"
  LastName: string; // "Gee"
  PasswordHash: string; // "L/Rlwxzp4w7RWmEgXX+/A7cXaePEPcp+KwQhl2fJL7w="
  Suffix: string; // null
  Title: string; // "Mr."
  EmailAddress: string; // "orlando0@adventure-works.com"
  Phone: string; // "245-555-0173"
  CustomerID: string; // 1
  PasswordSalt: string; // "1KjXYs4="
  SalesPerson: string; // "adventure-works\\pamela0"
  GUID: string; // "3F5AE95EB87D4AED95B4C3797AFCB74F"
  CompanyName: string; // "A Bike Store"
  FirstName: string; // "Orlando"
  NameStyle: boolean;    // false
  MiddleName: string; // "N."
  ModifiedDate: Date; // "2005-08-01T00:00:00.0000+00:00"
}

必要なモジュールをインポート

api-server.service.ts ファイルの先頭に戻り、通信、データ処理にに必要なモジュールをそれぞれインポートします。

//api-server.service.ts

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { catchError, map} from 'rxjs/operators';

API サーバーへの接続に必要な AuthToken、URL、リクエストヘッダを宣言

次に最初に設定した API サーバーに接続するための AuthToken、URL、そして認証に必要なリクエストヘッダを ApiServerService のプライベート変数として宣言します。

//api-server.service.ts

  // Auth Token
  private authToken = '設定したAuthToken';
  // APIサーバーRestAPIのURL、今回は顧客データを返すRest APIのURLに固定
  private baseUrl = '顧客データのRest API URL';
  // リクエストヘッダ
  private headers = new HttpHeaders({
    'x-cdata-authtoken': this.authToken
  });

コストラクタで依存関係の注入を利用し、HttpClient のインスタンスを取得

コンストラクタの引数として、HttpClientを受け取るように変更します。クラスインスタンスは Angular フレームワークにより作成されます。

constructor(private httpClient: HttpClient) { }

リクエストの設定とレスポンスの処理

顧客データを取得する getCustomers() メソッドを宣言し、HttpClient、pipe を利用してリクエストの設定と、レスポンスの処理、エラーハンドリングを実装します。

//api-server.service.ts

  public getCustomers() {
    // HttpClientを利用し、API サーバーにアクセス
    return this.httpClient.get<CustomersResponse>(
      `${this.baseUrl}/`, {headers: this.headers})
    .pipe(
      // エラー時の処理
      catchError(this.handleError('getData:Customer', [])),
      // 返されたデータから Customer の配列を取得
      map(response =>  (response as CustomersResponse).value)
    );
  }

  // Error時の処理。デモ用に簡略化
  private handleError<T>(operation = 'operation', result?: T) {
    return (error: any): string => {
      console.error('An error occurred', error);
      return error;
    };
  }

これでサービスの準備が整いました。

グリッド画面でデータを取得

次にグリッドを表示している画面側のコードを実装します。

必要なモジュールをインポート

igxgrid1\igxgrid1.component.tsでは先ほど実装した ApiServerService と、サービス呼び出しの結果返される Observable を利用するため、必要なモジュールをインポートします。

//igxgrid1\igxgrid1.component.ts

import { ApiServerService, Customer } from '../service/api-server.service';
import { Subscription } from 'rxjs';

購読を管理するための Subscription 変数を宣言

この ApiServerService はデータを非同期で取得します。そのため、呼び出しが完了した後にロジックを実行するための購読処理を後ほど実装します。 この購読は最終的には購読解除を行う必要があるtまえ、プライベート変数を宣言します。

//igxgrid1\igxgrid1.component.ts

    subscription: Subscription;

コストラクタで依存関係の注入を利用し、ApiServerService のインスタンスを取得

//igxgrid1\igxgrid1.component.ts

  constructor(private apiServerService: ApiServerService) { }

ngOnInit でデータを取得しグリッドにデータを表示

igxgrid1\igxgrid1.component.ts には、ngOnInit() メソッドが実装されており、データグリッド画面の初期化時に、あらかじめ用意されているサンプルデータを読み込むコードが実装されています。この localData にコレクションを代入することでグリッドにデータが表示されます。 このコードをコメントアウトします。

//igxgrid1\igxgrid1.component.ts

  ngOnInit() {
    // コメントアウト
    // this.localData = employeesData;
  }

コメントアウトしたコードの代わりに、ApiServerService を利用してデータを取得し、localData に割り当てるコードを実装します。

//igxgrid1\igxgrid1.component.ts

  ngOnInit() {
    // API Server を呼び出し、顧客データを取得
    this.subscription = this.apiServerService.getCustomers()
    .subscribe( (data: Customer[]) => {
      this.localData = data;
    });
  }

ngOnDestory で購読を解除

このコンポーネントが破棄されるタイミングでメモリーリークを防ぐため、購読を解除します。

//igxgrid1\igxgrid1.component.ts

  // unsubscribe
  ngOnDestroy() {
    if (this.subscription !== undefined) {
      this.subscription.unsubscribe();
    }
  }

サービス、モジュールの登録

最後に作成したサービスや必要なモジュールをアプリケーションに登録します。

モジュール参照のインポート

app.module.ts に ApiServerService および HttpClientModule をインポートします。

//app.module.ts

import { ApiServerService } from './service/api-server.service';
import { HttpClientModule } from '@angular/common/http';

imports セクションで HttpClientModule をインポート

@NgModule の imports セクションに HttpClientModule をインポートします。

//app.module.ts

  imports: [
    ...

    ,HttpClientModule
  ],

providers セクションで ApiServerService を宣言

@NgModule の imports セクションに HttpClientModule をインポートします。

//app.module.ts

  providers: [ApiServerService],

これで設定は完了です。再度 npm start コマンドで実行してみましょう!

f:id:IGJP:20190918211058p:plain

全てのコードはこちらの Branch でご覧いただけます(AuthToken、並びに URL は空白のため適宜設定してください)

GitHub - IG-JP/IgxGridApiServerDemo

終わりに

以下製品ページにて無料でお試し頂けます。

jp.infragistics.com

CData API Server
データベース接続、公開リソース選択、アクセス設定の3ステップだけでデータベースから本格的なREST API とドキュメントを公開。
CData API Server