はじめに
前回の続きで、今回は項目を増やす。そのため、データモデルであるRecipeクラスを修正する。
これまで、「id」「name」「miniute」「feature」の4項目だったが、「manner」「serve」「ingre」の3つの項目を加える。また、今回は検索機能も追加する。
レシピのようなデータ構造を正確に検索するのは大変であるが、簡易的なもので良いのであれば、オブジェクトをJSON文字列に変換してします方法が簡単である。JSON文字列にすると、どのようなオブジェクトであれ、「{プロパティ:値、プロパティ:値・・・}」のように文字列になる。この文字列に対して、「検索したいものが含まれているかどうか」を検索すれば、簡易的に検索を実現できる。
追加するレシピ項目
項目名 | 意味 | ||||
manner | 「和」「洋」「中」 | ||||
serve | 何人分か | ||||
ingre | 材料。配列として構成する
|
このような構造にする。
import {ArgumentOutOfRangeError }from“rxjs”;
export classRecipe {
id:number;
name:string;
minute:number;
feature:string;
manner: string;
serve: number;
ingre: {
name:string,
amount:string
}[];
一覧ページで表形式で表示する
レシピの詳細情報が増えたため、一覧では料理のな目だけでなく、「キャッチコピー」「調理時間」「主な材料」も表示できるようにする。
<h2>レシピ検索システム</h2>
<table>
<tr><th>名前</th><th>所要時間</th><th>一言</th><th>主な材料</th></tr>
<tr*ngFor=“let recipe of recipedata”>
<td>
<arouterLink=“/recipe-data/{{recipe.id}}”>{{recipe.name}}</a>
</td>
<td>{{recipe.minute}}</td>
<td>{{recipe.feature}}</td>
<td>
<span*ngFor=“let item of recipe.ingre; let i=index”>{{item.name}} </span>
</td>
</tr>
</table>
一部の材料だけ表示する
横幅が長くて見づらいので、材料を先頭3つだけ表示するようにする。
そのため、recipe.ingreを取得して、*ngForを繰り返し表示しているところで、表示回数をカウントし、「3つ以上になったら表示しなし」というようにする。
<h2>レシピ検索システム</h2>
<table>
<tr><th>名前</th><th>所要時間</th><th>一言</th><th>主な材料</th></tr>
<tr*ngFor=“let recipe of recipedata”>
<td>
<arouterLink=“/recipe-data/{{recipe.id}}”>{{recipe.name}}</a>
</td>
<td>{{recipe.minute}}</td>
<td>{{recipe.feature}}</td>
<td>
<span*ngFor=“let item of recipe.ingre; let i=index”>
<ng-container *ngIf=”i<3″>{{item.name}} </ng-container></span>
</td>
</tr>
</table>
詳細ページを修正する
**レシピ詳細**
<div*ngIf=“recipe”>
<b>調理時間:</b>{{recipe.minute}}分<br><br>
<h2>{{recipe.name}}</h2>
<p>{{recipe.feature}}</p>
<table>
<tr>
<td>
<imgwidth=“200”src=“/assets/img/pict{{recipeid}}.png”>
</td>
<td>
<b>調理時間:</b>{{recipe.minute}}分<br><br>
<b>材料 ({{recipe.serve}}人分) :</b>
<ul>
<li *ngFor=”let item of recipe.ingre”>
{{item.name}} {{item.amount}}
</li>
</ul>
</td>
</tr>
</table>
</div>
<button(click)=“backToList()”>リストに戻る</button>
検索機能を作る JSONデータにして文字列として比較する
レシピのようなデータ構造を正確に検索するのは大変であるが、簡易的なもので良いのであれば、オブジェクトをJSON文字列に変換してします方法が簡単である。JSON文字列にすると、どのようなオブジェクトであれ、「{プロパティ:値、プロパティ:値・・・}」のように文字列になる。この文字列に対して、「検索したいものが含まれているかどうか」を検索すれば、簡易的に検索を実現できる。
検索機能を実装する
①テキストボックスと検索洋のボタンを用意する
一覧ページにテキストボックスと検索用のボタンを用意する。ボタンがクリックされたら、コンポーネントの検索用のメソッドが実行されるように構成する。
このメソッドは、②で実装するもので、serchRecipeというメソッド名とする。このメソッドには、入力されたテキストを渡す。
②検索機能を実装する
コンポーネントにserchRecipeというメソッドというメソッドを実装し、①から実行可能なようにし、そこに、検索機能を実装する。検索機能はこのserchRecipeに実装するのではなく、サービスであるRecipeServiceの方に実装し、それを間接的に事項するものとする。
検索結果は、コンポーネントのrecipeプロパティに設定する。テンプレートでは、このレシピプロパティの値を見て表として表示しているため、recipeプロパティの値を変更すればそれに伴い、表示されている表も変わる。
テンプレートに検索用のテキストボックスとボタンをつける
**レシピ詳細**
検索:
<input #keyword size = “20” />
<button (click)=”serchRecipe(keyword.value)”>Serch</button>
<div*ngIf=“recipe”>
<b>調理時間:</b>{{recipe.minute}}分<br><br>
<h2>{{recipe.name}}</h2>
<p>{{recipe.feature}}</p>
<table>
<tr>
<td>
<imgwidth=“200”src=“/assets/img/pict{{recipeid}}.png”>
</td>
<td>
<b>調理時間:</b>{{recipe.minute}}分<br><br>
<b>材料 ({{recipe.serve}}人分) :</b>
<ul>
<li*ngFor=“let item of recipe.ingre”>
{{item.name}} {{item.amount}}
</li>
</ul>
</td>
</tr>
</table>
</div>
<button(click)=“backToList()”>リストに戻る</button>
検索機能をつける
recipe.service.ts
import {Injectable }from‘@angular/core’;
import {Recipe }from‘./recipe/recipe’;
import {RECIPEDATA }from‘./recipe/recipedata’;
@Injectable({
providedIn: ‘root’
})
export classRecipeService {
recipedata:Recipe[]=RECIPEDATA;
constructor() { }
getRecipedata():Recipe[]{
return this.recipedata;
}
getRecipe(id:string):Recipe{
return this.recipedata.find(recipe=>recipe.id.toString()==id);
}
serachRecipe(keyword: string): Recipe[] {
let resultArr: Recipe[] = [];
for (let recipe of this.recipedata) {
let dataStr = JSON.stringify(recipe);
if (dataStr.search(keyword) >= 0) {
resultArr.push(recipe);
}
}
return resultArr;
}
}
コンポーネント側から検索機能を実装する
いま作成した検索機能を実行して、キーワードに合致したものだけをコンポーネント側に実装していく。
recipe-list.component.ts
import {Component,OnInit }from‘@angular/core’;
import {Recipe }from‘../recipe/recipe’;
import {RecipeService }from‘../recipe.service’;
@Component({
selector: ‘app-recipe-list’,
templateUrl: ‘./recipe-list.component.html’,
styleUrls: [‘./recipe-list.component.css’]
})
export classRecipeListComponentimplementsOnInit {
recipedata:Recipe[];
constructor(privatersv:RecipeService) { }
ngOnInit() {
this.recipedata =this.rsv.getRecipedata();
}
searchRecipe(keyword:string){
this.recipedata = this.rsv.serachRecipe(keyword);
}
}
終わりに
①サービスオブジェクトを導入する
データ管理するためには、サービスオブジェクトを作る。そのサービスオブジェクトに検索などのメソッドを実装して、コンポーネントから呼び出すことで検索機能を実装する。
②<ng-container>で要素なしの出力になる
要素なしで繰り返しの出力をしたいときは、*ngForsでループのときに<ng-container>を使う。
③ループのインデックス
*ngForを使って処理するときにindexを指定すると、ループ回数を取得できます。
<span *ngFor=”let item of recipe.ingre; let i=index”>
<ng-container *ngIf=”i<3″>{{item.name}} </ng-container></span>
これまででAngularのプログラミングの話は終わる。
最後に作成したアプリケーションをインターネットのレンタルサーバーに乗せるときにどのようにしなればならないかを学ぶ。
一覧ページと詳細ページともに、RecipeServiceを経由してデータを取得できるようになった。
次回はレシピデータを増やし、レシピの項目を増やす。
コメント