*ngForのネスト (テストプレイ用サンプルリンク付き)
ちょこちょこ問題発生ですが前進はしているゲームブックプロジェクトです。
大きく変更させるのは文章(選択肢も含む)の自由度の確保です。
今までのバージョンは、ページごとのテキスト行数や選択肢の数などに制約があったので、これを取り外すべく作業中です。
さて、そこで技術的実装で配列の中身をHTML上で連続して書きだすことができる*ngForの入れ子は可能かと言う点で躓いていました。
結論から言えば可能ですが、躓いた点も含めて書いていきます。
大前提としてionicはTypeScriptで書いて、これをjavascriptにコンパイルします。
(*ngForの話なのでAngularモデルでの話です)
*ngForが記述されるhtmlファイルの部分も、もちろんコンパイルされるわけですが、ここで使う配列(中がobjectでさらに配列を持つ入れ子構造になっている)は、あらかじめ(中身はともかく)homepage.tsで定義されていなければいけません。
例えば、こんなデータ構造ですね。
{
text:['これがこのページ1行目のテキスト','これが2行目のテキスト'],
select:[
{
text:['選択肢1の1行目', '選択肢1の1行目']
buttontext:'選択肢1のボタン'
},
{
text:['バッドエンド選択肢',] //2行目は無い
buttontext:'選ばない方がいいボタン'
},
]
}
ここで上のデータの内、ページのテキストと選択肢のテキスト表示を実装してみると問題なく動きました。
ただページテキストも選択肢テキストもキー名が"text"で被っているのが、気になってそれぞれキーの名前を"page_text"、"select_text"と変更して、同時に選択肢ボタン名を実装する事にしました。
この時、横着してどうせ配列の中身はページごとに書き換える訳だから、テストデータのキー名のみを変更し、homepage.tsでの定義の事は忘れていた訳です。
その結果、意味不明(とその時は思った)なエラーや現象が起き、結果、迷走を続けることになった訳です。
最終的(先ほど)にhomepage.tsでの定義とデータの中身のキー名を揃える事で、意図する動きになりました。
上の例とは異なりますが、テスト用のコードを下記に記します。
(以下のサイトのコードを参考に配列の中身がobjectの場合も含めるよういじっています。
https://stackblitz.com/edit/angular-nested-ng-for?file=src%2Fapp%2Fapp.component.html
)
例によって、タブ表現のためにシングルスペース2つを倍角スペースに変換していますのでご注意ください。
home.page.ts
---------------------------------------------------------------
import { Component } from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
userResults = [
{ key: 'example@example.com', value: ['message1', 'message2'], arrv:[{a:'a0', b:'b0', c:'c0'},{a:'a1', b:'b0', c:'c0'},{a:'a2', b:'b0', c:'c0'},{a:'a3', b:'b0', c:'c0'},] },
{ key: 'test@test.com', value: ['message1', 'message2', 'message3', 'message4', 'message5'], arrv:[{a:'a2', b:'b0', c:'c0'}] },
{ key: 'example@example.com', value: ['message1', 'message2'], arrv:[{a:'a3', b:'b0', c:'c0'}] },
];
displayedColumns = ['Email', 'Message'];
constructor() {
}
}
---------------------------------------------------------------
home.page.html
---------------------------------------------------------------
<div class="container" style="text-align:center">
<br />
<h1>Results</h1>
<table style="width:50%" align="center" border="1">
<tr>
<th *ngFor="let col of displayedColumns">
{{ col }}
</th>
<th>test</th>
</tr>
<tr *ngFor="let item of userResults">
<td>{{ item.key }}</td>
<td>
<div *ngFor="let value of item.value">
{{ value }}
</div>
</td>
<td>
<div *ngFor="let arrv of item.arrv">
{{ arrv['a'] }}
</div>
</td>
</tr>
<tr>
</table>
---------------------------------------------------------------
実際の動きを見ると*ngForのネストの意味が分かると思いますので、サンプルアプリのリンクを以下に記します。
選択肢の中のテキストが内部の*`ngForになっているのが判るかと思います。
https://aticlab.com/webapp/gamebook/home