今日も見に来てくださってありがとうございます。石川さんです。
先日に引き続き、Angularを勉強しています。今回はリアクティブフォームを使って、サンプルプログラムを作ってみました。
出来上がりイメージ
今回は、たまたまニュートン-ラフソン法について質問があったので、Angularで実装してみました。こんな感じになります。ルートを求めたい値「k」を入力して、Calcボタンをクリックすると、漸化式を繰り返します。二乗した結果が「k」との誤差0.01未満になったら終了します。
今回も、statsblitz.comを利用してみました。作業中に、デフォルトで用意されているコンポーネントの「hello.component.ts」を削除してみたところ、以下のエラーがでました。しばらく解決できなくて、何かの設定があるのかと、ウロウロしてしまったので、回避策をメモしておきます。
Error in src/app/hello.component.ts (1:1) File '/~/src/app/hello.component.ngtypecheck.ts' not found.
何のことはありません、おかしな状態になっているだけ、ということのようでした。画面のプロジェクトエクスプローラーの左下の「DEPENDENCIES」をポイントすると、くるりとなった矢印が登場するので、そちらをクリックしたところ、しばらく待って、エラーが消えました。
ソースコード
ソースコードは以下のとおりです。
まずは、コンポーネントのスクリプトです。リアクティブフォームのポイントは「FormGroup」ですね。TypeScript側で「myGroup」として定義しています。また、今回はFormBuilderを使って「k」を定義しました。また、Validatorsを使って、正の数をチェックするようにしました。
onSubmit()呼び出し時、漸化式で計算を実行して、二乗した結果がkに近づいて差が0.01を下回ったところで処理を完了します。
import { Component, OnInit } from '@angular/core'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; @Component({ selector: 'app-x2', templateUrl: './x2.component.html', styleUrls: ['./x2.component.css'], }) export class X2Component implements OnInit { myGroup: FormGroup; results: string[]; guess: number; constructor(private fb: FormBuilder) {} ngOnInit() { this.myGroup = this.fb.group({ k: [24, Validators.min(0)], }); } get k() { return this.myGroup.get('k'); } onSubmit() { console.log('Executed!') this.results = []; let k: number = this.k.value; let epsilon: number = 0.01; let guess: number = k / 2; let newGuess: number; while (Math.abs(guess * guess - k) >= epsilon) { newGuess = guess - (guess ** 2 - k) / (2 * guess); if (this.results.length == 0) { this.results.push(guess.toString() + ' => ' + newGuess.toString()); } else { this.results.push(' => ' + newGuess.toString()); } guess = newGuess; } this.guess = guess; } }
そして、コンポーネントのHTMLファイルです。
<p> ニュートン-ラフソン法でkの根を求めます。 </p> <p> f(x) = x<sup>2</sup> - k<br> x<sub>n + 1</sub> = x<sub>n</sub> - f(x) / f'(x) = x<sub>n</sub> - (x<sub>n</sub><sup>2</sup> - k)/2x<sub>n</sub> </p> <form [formGroup]="myGroup" (submit)="onSubmit()"> <table> <tr> <th>k</th> <td><input type="number" formControlName="k"></td> </tr> <tr> <th></th> <td *ngIf="k.invalid" [style.color]="'red'">正の数を入力してください。</td> </tr> <tr> <th></th> <td> <input type="submit" value="Calc" [disabled]="myGroup.invalid"> </td> </tr> </table> </form> <ul> <li>まず、guess = k / 2 = {{k.value}} / 2 = {{k.value / 2}} とします。<br>guess - (guess<sup>2</sup> - {{k.value}})/ (2 × guess)がより近い値になるので、計算結果の誤差が0.01になるまで繰り返します。<br> <p *ngIf="!results">Calcを押して続行します。</p></li> <li *ngFor="let ans of results">{{ans}}</li> </ul> <p *ngIf="guess">{{guess}} * {{guess}} = {{guess * guess}}</p>
WordPressへの組み込み
stackblitz.comを見ていると、「Share」メニューがあったので、クリックして見ると、「Embed」タブが出てきましたので、WordPressに組み込めるのではないか、と、調べて組み込んでみました。
組み込みブロックはあるのですが、stackblitz.com用のものがなく、調べているとここに書いてありました。iframeタグを使って、ということだったので、実験してみましたところ、以下のとおり、実行できました!
ただ、編集のプレビュー画面では「Calc」ボタンは動きませんでした。iframeではsubmitが無効になっているようです。ただ、確認画面では動作しました。こちらの原因はまた機会があったら調べてみます。公開された後に実行できるかどうかわかりませんので、stackblitz.comのソースコードはこちら、実行結果はこちらです。
まとめ
Angularのリアクティブフォームを使って、ページを作ってみました。