2020年6月30日火曜日

angularでの複数チェックボックスの取り扱い。


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

最近久々にAngularプロジェクトを開発する機会があり、そこでまたいろいろと勉強になったことがあったので、ご存知の方には基本的なお話しなのかとは思いますが、今回は「angularで複数のチェックボックスを使った記述方法」の一例をご紹介できればと思います。

■作りたい画面

今回作る画面のイメージとしては、下記のような登録画面で、基本情報の入力と共にチェックボックスが複数設置され、その内容をフォーム送信して登録というようなシンプルな画面構造を想定します。

画面イメージ



■コンポーネント

まずコンポーネント側の記述ですが、今回フォーム送信を行うので、Angularのリアクティブフォームから、FormControl、FormGroup、FormBuilder、FormArrayクラスをそれぞれ利用します。 各クラスの細かな説明はAngularの公式ドキュメント内のリアクティブフォームの説明を見ていただいたほうがわかりやすいかもですが、めちゃくちゃざっくり書くとこんな感じかなと思います。
FormControl:単一入力欄の制御
FormGroup:FormControlのグループ化
FormBuilder:FormControlの作成に使う(FormControlをたくさん扱う場合にインスタンス不要)
FormArray:FormGroup内の配列要素コントロールの制御
さらに、今回は入力の必須チェックも行いたいので、Validatorsクラスもインポートします。

では、実際に上記をインポートし、コンポーネント側を記述します。
export class AppComponent implements OnInit {
  favoriteFruitsList: {key: string, value: string}[] = [
    {key: '1', value: 'りんご'},
    {key: '2', value: 'バナナ'},
    {key: '3', value: 'みかん'},
    {key: '4', value: 'ぶどう'},
  ];

  checkBoxFormArray: FormArray;
  groups: FormGroup[] = [];

  form: FormGroup = this.formBuilder.group(
    {
      name: ['', [Validators.required]],
      age: ['', [Validators.required]],
      tel: ['', [Validators.required]],
      formFavoriteFruitsList: this.formBuilder.array(this.groups, [Validators.required, this.checkBoxValidator]),
    }
  );

  constructor(
    private formBuilder: FormBuilder,
    public v: UserValidator,
  ) {}

  ngOnInit() {
    this.v.formGroup = this.form;
  }

  checkBoxValidator(control: FormArray) {
    for (let i = 0, loop_cnt = control.length; i < loop_cnt; i++) {
      if (control.at(i).value) {
        return null;
      }
    }
    return { unChecked: true };
  }

  onChange(value, isChecked: boolean) {
    this.checkBoxFormArray = this.form.get('formFavoriteFruitsList') as FormArray;
    if (isChecked) {
      this.checkBoxFormArray.push(new FormControl(value));
    } else {
      const index = this.checkBoxFormArray.controls.findIndex(x => x.value === value);
      this.checkBoxFormArray.removeAt(index);
    }
  }

  onSubmit() {
   // 登録処理
  }

}

form: FormGroup = this.formBuilder.group(...
の記述で、まずはフォームの初期設定をおこないます。
ここでチェックボックスとなるformFavoriteFruitsListはarray()メソッドでフォーム配列とし、さらにその中でチェックボックスをグループ化しています。これはcheckBoxValidatorでチェックボックスの必須チェックの為にこのような記述にしておきます。
ちなみにここで作成したcheckBoxValidatorは、チェックボックスのいずれかにチェックが入っているかのバリデーションで、Validatorsクラスには無いオリジナルのバリデーションになります。
onChangeについてはhtml側の記載で説明します。

■html

<form [formGroup]="form" (ngSubmit)="onSubmit()">
  <h2>名前</h2><input type="text" formControlName="name">
  <h2>年齢</h2><input type="text" formControlName="age">
  <h2>電話</h2><input type="text" formControlName="tel">
  <h2>好きな果物</h2>
  <ng-container formArrayName="formFavoriteFruitsList">
    <ng-container *ngFor="let item of favoriteFruitsList;">
      <label>
        <input type="checkbox" [value]="item.key" (change)="onChange(item.key, $event.target.checked)"><span>{{ item.value }}</span>
      </label>
    </ng-container>
  </ng-container>
  <button type="submit">登録</button>
</form>

ここでformArrayNameにコンポーネント側で設定したformFavoriteFruitsListを記載します。
これによりこのチェックボックスは配列要素のフォームとして扱います。
またここで、コンポーネント側に作成した、チェックボックスをチェックした時に発火するonChangeを使います。
チェックをON、OFFする際に、checkBoxFormArrayの配列内で、値を追加、削除する関数になります。
これにより、submitした時に、実際にチェックした値だけフォーム送信されます。


今回記載した内容はあくまで一例で、結構他の記載方法もあるようで、もしかしたらもう少し簡単に書ける部分もあるかもしれません。
また画面的には非常にシンプルなのですが、まだAngularのリアクティブフォームの使い方をうまく把握できていないと最初は難しく、結構苦戦しました(苦笑)。

自分のようなAngular初心者の方で、もしご参考になればと思います。

2020年6月4日木曜日

nodemonを使用して、コード変更後に自動でNode.jsのアプリを再起動する方法。


オフィス狛 技術部のmmm(むー)です。

Node.jsで動いているアプリケーションのコードの修正をした後、サーバーの再起動が必要になリます。
コードを修正した後、毎回手動で再起動するのは面倒ですし、再起動し忘れることもあります。
nodemonを使用すれば、その煩わしい作業を自動化できます😶

nodemonとは
nodemonとはNode.jsベースのアプリケーションのコードの変更を監視し、変更があった際に自動でサーバーの再起動をしてくれるツールです。
参考:https://nodemon.io/

【前提条件】
Nodeとnpmがインストールされていること

1. nodemonのインストール

使用したいプロジェクト配下に移動し、下記を実行します。
devDependencies オプションは開発環境でのみ使用するため、今回つけています。
$ cd ~/<プロジェクトパス>
$ npm install nodemon --save-dev

--save-dev オプションを使用してインストールすると、 package.json に下記のように追記されます。
devDependencies 配下のパッケージは本番環境で npm install --production コマンドを実行すると除外されます。
// package.json

"devDependencies": {
    "nodemon": "^2.0.3"
  }

2. nodemonでアプリケーションを実行する

package.jsonに nodeコマンドの代わりにnodemonで起動するscriptを追加します。
script名(start-watch)は自分可変です。
   // package.json

"scripts": {
     "start": "node src/index.js",
     "start-watch": "nodemon src/index.js", // 🌟追加
     "test": "echo \"Error: no test specified\" && exit 1"
   },

nodemonを使用して、アプリを起動します。
$ npm run start-watch

下記のように起動ログが出力されれば、起動成功です。
 [nodemon] watching path(s): *.*
 [nodemon] watching extensions: js,mjs,json
 [nodemon] starting `node src/index.js`

コードに何か変更があった場合、下記のようにログが出力されます。
 [nodemon] restarting due to changes...
 [nodemon] starting `node src/index.js`

また手動で再起動したい場合は、 rs コマンドを打ってください
$ rs
 
 [nodemon] starting `node src/index.js`

以上となります。
インストールして少し設定するだけで、開発が楽になるのでまだ使用していない方はぜひお試しください🍭