Angular FormArrayで動的に変化するフォーム

こんにちは。レモンティーです。

以前、フォームについての記事を書きました。
www.sawalemontea.com

今回はFormArrayを使って動的に変化するフォームをつくります。
AngularMaterialでMatErrorのバリデーションも付けます。

Angular Docs

Angular Material



使い方はFormBuilderでFormGroupにFormArrayを入れておいて
項目を増減したい時にそのFormArrayに子FormGroupを
pushしたりremoveAtする感じです。


以下、複数のリンクを入力するフォームを例に見ていきます。


FormBuilderでFormArrayを入れておく
(ついでにgetで後々呼びやすくしておきます。)

  exampleForm:FormGroup;

  constructor(private fb:FormBuilder) { 
    this.exampleForm = this.fb.group({
      links:this.fb.array([]),
    });
  }

  get f() {return this.exampleForm.controls;}
  get linksArray():FormArray {return this.f.links as FormArray;}


項目を増やす

  addLinks(){
    this.linksArray.push(
      this.fb.group({
        linkName:["",[Validators.required]],
        linkUrl:["",[Validators.required]]
      })
    );
  }

項目を減らす

  removeLink(index:number){
    this.linksArray.removeAt(index);
  }

値の参照

  onSave(){
    for(let group of this.linksArray.controls){
      console.log(group.get("linkName").value);
      console.log(group.get("linkUrl").value);
    }
  }


テンプレート側は次のようになります

<form [formGroup]="exampleForm">

  <div formArrayName="links">
    <div *ngFor="let linksGroup of linksArray.controls; let i = index" [formGroupName]="i">
      <mat-form-field>
        <input matInput formControlName="linkName" placeholder="link name">
        <mat-error *ngIf="linksGroup.controls.linkName.invalid">{{getErrorMessage(linksGroup.controls.linkName)}}</mat-error>
      </mat-form-field>
      <mat-form-field>
        <input matInput formControlName="linkUrl" placeholder="link url">
        <mat-error *ngIf="linksGroup.controls.linkUrl.invalid">{{getErrorMessage(linksGroup.controls.linkUrl)}</mat-error>
      </mat-form-field>
      <button mat-button (click)="removeLink(i)">Delete</button>
    </div>
  </div>

  <button mat-flat-button color="primary" (click)="addLinks()" type="button">Add Links</button>
  <button mat-flat-button color="primary" (click)="onSave()" type="button" [disabled]="exampleForm.invalid">Save</button>

</form>

getErrorMessage()は前回のものと同じです。


これで項目を自由に増減できるフォームができます。
AngularMaterialでバリデーションも効いていますね。


今回はこれでおしまいです。
www.sawalemontea.com

Firebase CloudFirestoreで条件にあっているのにERROR Error: Missing or insufficient permissions.が起こるとき

こんにちは。レモンティーです。

今回はFirebaseのCloudFirestoreのルールについてです。
普通に公式ドキュメントに書いてあるのに見落としていたことなので多くの人には問題ないかもしれません。

ちょうどここに書いてあります。
https://firebase.google.com/docs/firestore/security/rules-query?authuser=0


例えば

allow read :if request.auth.uid == resource.data.author;

のようなルールできちんとルールを満たしているのに
ERROR Error: Missing or insufficient permissions.
が起こる場合は、クエリ側で

.where("author","==",user.uid)

のようにし忘れている可能性があります。


これを書き加えた時、インデックスを追加してくださいという旨の
リンク付きエラーがでる場合は
素直にリンク先にとんでインデックスを作成すれば
期待した動作になります。

インデックスについての公式ページ
https://firebase.google.com/docs/firestore/query-data/index-overview?authuser=0


今回はこれでおしまいです。