2018年11月15日木曜日

AngularのFormでのselect要素の使い方(selected指定の方法)


オフィス狛 技術部のKoma(Twitterアカウントの中の人&CEO)です。

何だか分かり難い題名ですいません。良い題名が思いつきませんでした。

さて、やりたい事から説明しようと思います。

Angularで、Formに入力した値をPOSTする時、ちょっとやり方迷うのがselect要素です。
プルダウンってやつですね。

こんな感じのFormは良くあるかと思います。
初期表示時に先頭を選択状態にしておくのは簡単ですが、
データの修正を行う機能などは、「APIで取得した値を選択状態に」って事は良くあります。

例えば、このようなJSONがAPIから返却されるとします。
{"list": [
        {"api-data-status": 1},
        {"api-data-status": 2},
        {"api-data-status": 3}
 ]}

まずはプルダウンに表示する値(value)と名称(name)を定義します。
【constants.ts】
export namespace testDataStatus {
  export const STATUS_1 = { value: 1, name: 'ステータス1' };
  export const STATUS_2 = { value: 2, name: 'ステータス2' };
  export const STATUS_3 = { value: 3, name: 'ステータス3' };
}

続いて、コンポーネント側でプルダウン用のリスト定義します。
先程の定義した定数を使用しています。
【test-data-status.component.ts】
  testDataStatusOption: Array<{ status: number; name: string }> = [
    {
      status: Constants.testDataStatus.STATUS_1.value,
      name: Constants.testDataStatus.STATUS_1.name
    },
    {
      status: Constants.testDataStatus.STATUS_2.value,
      name: Constants.testDataStatus.STATUS_2.name
    },
    {
      status: Constants.testDataStatus.STATUS_3.value,
      name: Constants.testDataStatus.STATUS_3.name
    }
  ];

そして、最後はView(html)側ですが・・・下記のように記載すると、うまく行きません
【test-data-status.component.html】(NGな例)
<ng-container *ngFor="let item of statusList.list">
    <select class="form-control" formControlName="testDataStatus">
        <option *ngFor="let hoge of testDataStatusOption"
              [ngValue]="hoge.status"
              [selected]="hoge.status === item.api-data-status">
              {{report.name}}
        </option>
    </select>
</ng-container>
「statusList.list」がAPIで取得したデータです。
それを最初の「ngFor」で繰り返してデータ数分のプルダウンを作り、二番目の「ngFor」からプルダウンの値(value)と名称(name)を作り、APIの値と比較して「selected」に値を設定する・・・一見うまく行きそうなんですけどね。これではダメです。

という訳で、うまく行く書き方は以下の通りです。
【test-data-status.component.html】(OKな例)
<ng-container *ngFor="let item of statusList.list">
  <select class="form-control form-control-sm" [(ngModel)]="item.api-data-status" formControlName="testDataStatus">
    <option *ngFor="let hoge of testDataStatusOption"
        [ngValue]="hoge.status">
        {{hoge.name}}
    </option>
  </select>
</ng-container>
まあ、良く考えると当たり前なのですが、
「[(ngModel)]」に値を設定する事で、APIから取得した値で選択状態とする事が出来ます。

view(html)表示だけだと、そこまで難しくないのですが、FormControlを使うと少しややこしくなるので、自分の備忘録の為に記事にしました。

それでは、良いAngularライフを!


2018年11月2日金曜日

C#でプロキシ経由でJSONデータを外部APIにわたす。


オフィス狛 技術部のHammarです。

今回も業務でちょっとハマったことについて、解決方法を書いていこうと思います。
今回はC#でプロキシ経由でAPIを呼び出す方法です。
いつもは社内のネットワーク内でAPIを呼び出していて、あるタイミングで社外のAPIを
呼び出すとなったときに、プロキシ設定しているため通常の呼び出し方ではリクエストが届かないという感じでちょっとハマりました。

まず下記のようなJSONを、あるAPIに送るとします。
{
    "id" : 1,
    "name" : "テスト"
}

プロキシ設定を考えずに書くと、HttpClientを使って下記のような感じでPOSTします。
var json = "{ \"id\" : 1, \"name\" : \"テスト\"  }";

using (var client = new HttpClient())
{
    string apiUrl = "http://hostname/testapi";
    HttpContent content = new StringContent(json, Encoding.UTF8, "application/json");
    HttpResponseMessage response = await client.PostAsync(apiUrl, content).Result;
}
※上記のJSON部分は一旦わかりやすいように書いていますが、実際にはJson.NETを使ってシリアライズしてやり取りします。

で、上記の状態でAPIをコールしてもプロキシに引っかかり、API側にリクエストが届きません。
ですので、上記に利用するプロキシ設定情報を付与してあげると外にでれます。
そのやり方が下記になります。
var json = "{ \"id\" : 1, \"name\" : \"テスト\" }";
var httpClientHandler = new HttpClientHandler
{
    Proxy = new WebProxy("http://localhost:8888", false),
    UseProxy = true
};
using (var client = new HttpClient(httpClientHandler))
{
    string apiUrl = "http://hostname/testapi";
    HttpContent content = new StringContent(json, Encoding.UTF8, "application/json");
    HttpResponseMessage response = await client.PostAsync(apiUrl, content).Result;
}
上記でわかるようにHttpClientHandlerクラスのProxyプロパティを使ってあげます。
これでこのプロキシ設定情報でリクエストされ、API側に届くようになります。

ちなみにこのやり方は認証ない場合で、認証が必要な場合は下記のようにHttpClientHandlerクラスに認証情報のCredentialsプロパティを追加するだけです。
var httpClientHandler = new HttpClientHandler
{
    Proxy = new WebProxy("http://localhost:8888", false),
    Credentials = new NetworkCredential(@"username", @"password");
    UseProxy = true
};

HttpClientHandlerクラスにはその他いろんなプロパティがあるので、HttpClientを使ったリクエストを行う際にはこちらも参考にしてみてください。
https://msdn.microsoft.com/ja-jp/library/system.net.http.httpclienthandler(v=vs.110).aspx

,