ITの隊長のブログ

ITの隊長のブログです。Rubyを使って仕事しています。最近も色々やっているお(^ω^ = ^ω^)

【Angular2】Formを動的に扱うコードを書いてみた

ここまで来るのに時間かかったよ!!!

github.com

コードは全部こっちにあります。コミットログを追ったら情報わかるかも。もしわからないなら質問ください。ただ私も初心者に近いので答えられる範囲ですが(^^;

まずやりたいこととして、jQueryみたいにdomを動的に作ってviewに流し込みしたり、イベントを用意してバリデーションとかしたかった。

AngularJS1.xでは、そういうことを実装したことがなかったので、どうやってやればいいんだろ?って悩んでいたのね。

んで、色々試行錯誤したり、チュートリアルを試してみたりなどやっていくと。

情報少なすぎ、チュートリアル少なすぎワロタ。壁にぶち当たり。泣いた(´;ω;`)ブワッ

このままjQueryに戻って実装してやろうかなと思った。

しかしダメだ・・・! お前はまた4000行以上のコードを書きたいのか。。。!メンテしたいのか・・・!と、思い踏みとどまった。

思いだけでは解決しなかった。我慢ならなかったので、ぐぐって本を購入しました。 www.ng-book.com

洋書なので、もちろんよめませんでした(´;ω;`)ブワッ

んで、最近賢くなったと聞いたGoogle翻訳を使ってみました。

すると、これがすごく有能。使いながら読むとコードを理解しながら英語の勉強にもなった。Googleすげえぇええええ!!!

で、読んだ内容はFormの基礎。簡単にまとめる。

Angular2のFormは、入力フォームにFormControlを使い、FormGroupでグルーピングする。

使い方ざっくり

  • moduleで、FormsModuleimportしてね。
  • FormControlはこうやって使う => <input type="text" name="name" ngModel>
  • FormGroupは、<form #f="ngForm" (ngSubmit)="onSubmit(f.value)">...</form>
    • onSubmitのメソッドを用意したら、FormGroupにセットされているFormControlの値にアクセスすることができる

#f="ngForm"とかngModelとかなにこれ?と思うかもしれないが、どうやらFormsModuleを呼ぶと暗黙的に値がセットされるらしい。

初期値渡したいの。どうすればいい?

  1. FormBuilderを使った方法があります。

当初はこれが細かい設定の方法だと思っていましたが、どうやらこのクラスもFormGroupFormControlのためのシンタックスシュガーっぽい。

本当に細かくしたいならnew FormControl()とかnew FormGroup()のように、インスタンス化から自分で手続きしなけいけない。

さて、FormBuilderの話に戻る。こちらも使い方ざっくり

  • さっきのFormsModuleに、ReactiveFormsModuleも追加でimport
  • 使いたいComponentで、FormBuilderをDIする
  • FormBuilderのメソッドに、groupがあるので、KeyValueでFormControlになる値を渡してあげる。
private myForm: FormGroup;
constructor(formBuilder: FormBuilder) {
  this.myForm = formBuilder.group({
    'myName': ['初期値だお']
  })
}
  • view側では、<form [formGroup]="myForm">...</form>にすること。このmyFormComponentのメンバー名と同じしないとダメよ!
  • また、<input>では、属性に[formControl]="myForm.controls['myName']"を使う。

これでおk。初期値が入るはず。

このFormBuilderは、ValidateやCustom Validateでも利用できるので、こっちの方を使ったほうがいいかも知れないです。

Validateは?

はい。書きます。

バリデーションは、FormControlの第二引数にセットすればおk.FormBuilderを使っているのなら、こう書けば良い。

import { FormGroup, FormControl, FormBuilder, Validators} from '@angular/forms';
// ...
private myForm: FormGroup;
constructor(formBuilder: FormBuilder) {
  this.myForm = formBuilder.group({
    'myName': ['初期値だお', Validator.required] // <- 第2引数に追加
  })
}

こうすると、requried(必須)のバリデーションが動いてくれる。

また、エラーも表示したいよね? view側でこう書いて。

<div *ngIf="myForm.controls['myName'].hasError('required')"
  class="ui error message">myName is required</div>

複数バリデートしたい場合は? 絶対あるよねー。

第2引数に配列で渡せばいいでしょ?って思うかもしれないがそれはできない。

なので、Validator.compose()というメソッドを使って値を合成(?)して渡す。

private myForm: FormGroup;
constructor(formBuilder: FormBuilder) {
  this.myForm = formBuilder.group({
    'myName': ['初期値だお', Validator.compose([
      Validator.required,     // 必須
      Validators.minLength(5) // 5文字以上
    ])]
  })
}

view側もさっきと同様に追加してね。これでよし。

全部書こうと思ったけど、疲れたからまた今度追記する。Githubのログを追ったら一応わかるはずだけど。

残り

  • Custom Validator
  • Watch Value Changes
  • 本には乗っていなかった自分で試したやつ
    • Enter keyを無効にしたい
    • Datepickerとの組み合わせ
    • 動的にFormを追加

本の感想

すごくわかりやすいよ!!

英語なので、ストレス溜まっていたけど、Google翻訳のおかげで今ならすっと入ってきます。英語が綺麗なのもあるのかな。

まだFormの章しか読んでいないので、ちゃんとオススメはできませんが、基礎はしっかり、後半はチャットアプリデモの作り方みたいな章もあるのですごく楽しみです。

ちと高めですが、勉強したい人はぜひー。 www.ng-book.com

【Perl】macでワンライナーで置換する

1時間もはまったよ!!!!!!(´;ω;`)ブワッ

こんなにむずかしかったっけ?ぐらいハマった。

$ find {src/views,src/models} -type f} | grep -e '.*\.\(php\|html\)$' | xargs perl -i -pe 's/company/companies/g;'

参考URL

404 Blog Not Found:perl - ワンライナーの書き方入門

【Angular2】Cannot find control with unspecified name attribute

怒られた。

FormGroupで、viewにngModelを増やしたら怒られた。

export class ScheduleForm {

    private startDatetime:string;
    private endDatetime:string;

    constructor(private datetimeForm:DatetimeFormService, formBuilder:FormBuilder) {
        this.myForm = formBuilder.group({
            'startDatetime':  ['', Validators.required],
            'endDatetime':  ['', Validators.required] // こっちが抜けていた
        });
    }
}

stackoverflow.com

For every one else with problem "Cannot find control with unspecified name attribute" the problem is you forgot to define formControlName on your form input elemnts.

なるほど。viewには追加したのはいいが、FormBuilderにも渡さないといけないのね。理解しました。

【Angular2】ComponentからComponentを動的に作成してみました

タブ機能を自作してみたけど、タブComponentとその下の子Componentとどうやってやり取りさせいようかと悩んでいました。

世界に聞いてみましたが、説明が足りないのか返事は来ませんでした(´・ω・`)

stackoverflow.com

つーわけで、色々調べて試したんですよ。できました。

github.com

すげー時間食いました。でもできた!ばんざーい!!

しかし、当初の目的はタブのComponetとのデータのやり取りなのよね。これはまだ解決していない(´・ω・`)

ふーむ。

ちなみに、電子書籍買いました。しかも洋書。人生初。

www.ng-book.com

とりあえずこれをちょっとずつ読んで見る。

【Angular2】Angular2でモーダルを自作しました

自作っつーかパクリなんですけどね

github.com

元はこちら。ありがとうございます。

qiita.com

概要はgithubのREADME.mdに詰めましたので、そこをみてほしい。

ちなみに、感想としては、Angular2のバージョンアップの速度早すぎ。

個人的な感触として、3ヶ月前の記事は使えないと思っている。使い方が変わっているのでコピペプログラマにはキツイはず。

なので、情報に操作されないためには、Google検索を1ヶ月以内で絞り、英語の記事をあさってみることだね。

本当はドキュメントでもいいと思うんだけど、ドキュメント読みづらくて見る気がしない。

今ふとおもったんだけど、そういえばControllerってなくなったな。全部Component(バージョン1でいうDirectiveに近い)になっている。

わかりやすいっちゃーわかりやすいけど、もはや1.xとは全くの別ものである。別のフレームワークだと思う。ってか、同じ名前にする必要がなかった。