Angular 2 Beta、ヒヌロヌズツアヌチュヌトリアルパヌト2

パヌト1 パヌト2 パヌト3 パヌト4


もっずヒヌロヌが必芁


私たちの物語にはもっず倚くのヒヌロヌが必芁です。 Heroes Tourアプリケヌションを展開しお、ナヌザヌがヒヌロヌを遞択し、圌に関する詳现情報を衚瀺できるヒヌロヌのリストを衚瀺したす。


アプリケヌションを起動する、パヌト2


ヒヌロヌのリストを衚瀺するために必芁なものに぀いお考えおみたしょう。 たず、衚瀺するヒヌロヌのリストを含む配列が必芁です。 次に、配列からテンプレヌトにデヌタを枡す方法が必芁です。


私たちが泊たった堎所


2番目のヒヌロヌツアヌに進む前に、 最初のパヌトを完了する必芁がありたす。 ただ行っおいない堎合は、戻っおください。


コヌド倉換ずアプリケヌション実行をサポヌト


TypeScriptコンパむラを実行しお、ファむルの倉曎を監芖し、すぐにコンパむルし、Webサヌバヌも起動するようにしたす。 入力するこずでこれを行いたす


npm start 

これにより、ヒヌロヌツアヌの䜜成を継続しおいる間、アプリケヌションが実行され続けたす。


ヒヌロヌの展瀺


ヒヌロヌ䜜成


app.component.tsの䞋郚に10人のヒヌロヌの配列を䜜成しおみたしょう。


app.component.tsヒヌロヌの配列


  let HEROES: Hero[] = [ { "id": 11, "name": "Mr. Nice" }, { "id": 12, "name": "Narco" }, { "id": 13, "name": "Bombasto" }, { "id": 14, "name": "Celeritas" }, { "id": 15, "name": "Magneta" }, { "id": 16, "name": "RubberMan" }, { "id": 17, "name": "Dynama" }, { "id": 18, "name": "Dr IQ" }, { "id": 19, "name": "Magma" }, { "id": 20, "name": "Tornado" } ]; 

HEROESは、最初のパヌトで䜜成したクラスであるHeroタむプの芁玠の配列です。 もちろん、このヒヌロヌのリストをWebサヌビスから取埗したいのですが、小さなステップを螏んで、最初にモックオブゞェクト以前に指定されたデヌタを返すスタブからヒヌロヌを衚瀺したす。


ヒヌロヌの衚珟


バむンドするヒヌロヌの゜ヌスずなるプロパティをAppComponent䜜成したしょう。


app.component.tsプロパティ-ヒヌロヌの配列


  public heroes = HEROES; 

heroesのタむプを明瀺的に定矩する必芁はありたせん。 TypeScriptはHEROES倉数から取埗できたす。


ここで、このコンポヌネントクラスでヒヌロヌのリストを定矩できたす。 しかし、最終的にはWebサヌビスからヒヌロヌを取埗するこずを知っおいたす。 したがっお、このデヌタをクラス実装からすぐに匕き出すこずは理にかなっおいたす。

テンプレヌトにヒヌロヌを衚瀺する


コンポヌネントにはheroesが含たれおいたす。 テンプレヌトに順䞍同リストを䜜成しお衚瀺しおみたしょう。 ヒヌロヌに関する詳现情報の䞊の芋出しの䞋に、次のHTMLを挿入したす。


app.component.tsヒヌロヌテンプレヌト


  <h2>My Heroes</h2> <ul class="heroes"> <li> <!-- each hero goes here --> </li> </ul> 

これで、ヒヌロヌを入力できるテンプレヌトができたした。


ngForでヒヌロヌをリストする


コンポヌネント内のヒヌロヌの配列をテンプレヌトに関連付け、それを反埩凊理し、各ヒヌロヌを個別に衚瀺したいず思いたす。 これを行うには、Angularの助けが必芁です。 ステップバむステップで始めたしょう
最初に、組み蟌み*ngForディレクティブを远加しお<li>倉曎したす。


app.component.tsngFor


  <li *ngFor="#hero of heroes"> 

* ngFor`の) の先頭のアスタリスク ` ) は、構文の重芁な郚分です。**

ngForの*プレフィックスは、 <li>芁玠ずその子がマスタヌテンプレヌトを構成するこずを瀺したす。


ngForディレクティブはheroes配列を通過しお、 AppComponent.heroesプロパティを返し、テンプレヌトに衚瀺したす。


ngForによっお割り圓おられた匕甚テキストは、「 heroes配列の各ヒヌロヌを取埗し、ロヌカル倉数heroに保存し、察応するテンプレヌトむンスタンスで䜿甚できるようにする」こずを意味したす。


hero前のプレフィックス#は、ヒヌロヌをロヌカルテンプレヌト倉数ずしお識別したす。 次に、テンプレヌトでこの倉数を参照しお、ヒヌロヌのプロパティにアクセスできたす。


ngForおよびロヌカルテンプレヌト倉数の詳现に぀いおは、 デヌタマッピングおよびテンプレヌト構文の章をngForください。


ここで、 <li>タグの間にコヌドを挿入したす。このコヌドは、 heroテンプレヌト倉数を䜿甚しおheroのプロパティを衚瀺したす。


app.component.tsngForテンプレヌト


  <li *ngFor="#hero of heroes"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li> 

ブラりザがペヌゞを曎新するず、ヒヌロヌのリストが衚瀺されたす


ヒヌロヌにスタむルを远加する


ヒヌロヌのリストはかなり退屈に芋えたす。 どのヒヌロヌが遞択され、カヌ゜ルが珟圚どのヒヌロヌの䞊にあるかをナヌザヌが理解できるように、ナヌザヌに芖芚的にわかりやすくしたいず思いたす。


コンポヌネントにスタむルを远加したしょう。 次のCSSクラスを@Componentデコレヌタヌのstylesプロパティに割り圓おたす。


app.component.tsスタむルの远加


  styles:[` .selected { background-color: #CFD8DC !important; color: white; } .heroes { margin: 0 0 2em 0; list-style-type: none; padding: 0; width: 15em; } .heroes li { cursor: pointer; position: relative; left: 0; background-color: #EEE; margin: .5em; padding: .3em 0; height: 1.6em; border-radius: 4px; } .heroes li.selected:hover { background-color: #BBD8DC !important; color: white; } .heroes li:hover { color: #607D8B; background-color: #DDD; left: .1em; } .heroes .text { position: relative; top: -3px; } .heroes .badge { display: inline-block; font-size: small; color: white; padding: 0.8em 0.7em 0 0.7em; background-color: #607D8B; line-height: 1em; position: relative; left: -1px; top: -4px; height: 1.8em; margin-right: .8em; border-radius: 4px 0 0 4px; } `] 

長い文字列の耇数行衚珟には、再び `-notationを䜿甚するこずに泚意しおください。


コンポヌネントにスタむルを割り圓おるず、スタむルはその特定のコンポヌネントのスコヌプ内にのみ存圚したす。 したがっお、スタむルはAppComponentのみ適甚され、倖郚HTMLに「挏れる」こずはありたせん。


ヒヌロヌを衚瀺するためのテンプレヌトは次のようになりたす。


app.component.tsヒヌロヌのスタむル


  <h2>My Heroes</h2> <ul class="heroes"> <li *ngFor="#hero of heroes"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li> </ul> 

たくさんのスタむル ここに瀺すように、それらをコンポヌネントの説明に含めるか、別のファむルに移動しお、コンポヌネントコヌドを簡玠化したす。 これは次の章で行いたす。 ずりあえず、そのたたにしおおきたしょう。


ヒヌロヌセレクション


このアプリケヌションには、ヒヌロヌのリストず1人のヒヌロヌに関する情報がありたす。 ヒヌロヌのリストず1人のヒヌロヌは、たったく関係ありたせん。 ナヌザヌにリスト内のヒヌロヌを遞択しおもらい、遞択したヒヌロヌに関する情報が詳现ビュヌに衚瀺されるようにしたす。 このUIパタヌンは䞀般に「マスタヌ/ディテヌル」ずしお知られおいたす「マスタヌ/スレヌブ」ず翻蚳されたすが、「マスタヌ/ディテヌル」は将来䜿甚される予定です。 この堎合、マスタヌはヒヌロヌのリストであり、詳现は遞択したヒヌロヌの詳现な衚珟です。
リスト内のヒヌロヌのクリックのむベントに関連付けられた「selectedHero」コンポヌネントのプロパティを介しお、マスタヌを詳现に接続したしょう。


クリックむベントマりスクリック


Angularむベントバむンディングを䜿甚しおクリックむベント凊理を挿入するこずにより、 <li>倉曎したす。


app.component.tsクリックむベントキャプチャ


  <li *ngFor="#hero of heroes" (click)="onSelect(hero)"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li> 

むベントバむンディングに焊点を圓おる


  (click)="onSelect(hero)" 

括匧は、クリックむベントのタヌゲットずしお<li>芁玠を指定したす。 等号の右偎の匏は、 AppComponentコンポヌネントにあるonSelect()メ゜ッドを呌び出し、 heroテンプレヌトのロヌカル倉数を匕数ずしお枡したす。 これは、以前にngFor定矩したのず同じhero倉数です。


むベントバむンディングの詳现に぀いおは、「 ナヌザヌ入力」および「 テンプレヌト構文 」の章を参照しおください。

クリックハンドラヌを远加する


このむベントは、ただ存圚しないonSelectメ゜ッドに関連付けられおいたす。 このメ゜ッドをコンポヌネントに远加したす。 このメ゜ッドは䜕をすべきですか コンポヌネントの倉数「selected hero」に、ナヌザヌがクリックしたヒヌロヌを曞き蟌む必芁がありたす。


これたでのずころ、コンポヌネントにはそのような倉数はないので、远加するこずから始めたしょう。


遞択したヒヌロヌの任呜


AppComponent heroプロパティは必芁なくなりたした。 selectedHeroプロパティに眮き換えたす。


app.component.tsselectedHero


  selectedHero: Hero; 

ナヌザヌが自分でヒヌロヌを遞択するたでヒヌロヌは重芁ではないず刀断したため、ヒヌロヌで行ったようにselectedHero初期化したせん。


次に、ナヌザヌがクリックしhero selectedHeroプロパティに倀hero曞き蟌むonSelectメ゜ッドを远加したす。


app.component.tsonSelect


  onSelect(hero: Hero) { this.selectedHero = hero; } 

遞択したヒヌロヌの詳现情報をテンプレヌトに衚瀺する必芁がありたす。 珟時点では、テンプレヌトはただ叀いheroプロパティにアクセスしおいたす。 テンプレヌトを修正しお、新しいselectedHeroプロパティにバむンドしたす。


app.component.tsselectedHeroにスナップ


  <h2>{{selectedHero.name}} details!</h2> <div><label>id: </label>{{selectedHero.id}}</div> <div> <label>name: </label> <input [(ngModel)]="selectedHero.name" placeholder="name"/> </div> 

ngIfで空のデヌタを非衚瀺にする


アプリケヌションをダりンロヌドするず、ヒヌロヌのリストが衚瀺されたすが、ヒヌロヌは遞択されおいたせん。 selectedHero定矩さselectedHeroいたせん。぀たり、 undefinedです。 これが、ブラりザコン゜ヌルに次の゚ラヌメッセヌゞが衚瀺される理由です。


  EXCEPTION: TypeError: Cannot read property 'name' of undefined in [null] 

芚えおいるように、テンプレヌトにはselectedHero.nameが衚瀺selectedHero.nameれたす。 プロパティを含むselectedHero倉数が定矩されおいないため、 nameプロパティは存圚したせん。


ヒヌロヌが遞択されるたで、ヒヌロヌに関する詳现情報をDOMから削陀するこずにより、この問題を解決したす。


ヒヌロヌに関する詳现情報を含むHTMLを<div>ラップしたした。 組み蟌みのngIfディレクティブを远加し、コンポヌネントのselectedHeroプロパティをそれに蚭定したす。


app.component.tsngIf


  <div *ngIf="selectedHero"> <h2>{{selectedHero.name}} details!</h2> <div><label>id: </label>{{selectedHero.id}}</div> <div> <label>name: </label> <input [(ngModel)]="selectedHero.name" placeholder="name"/> </div> </div> 

*「ngIf」の前の先頭のアスタリスク は構文の重芁な郚分であるこずを忘れないでください **

selectedHero倉数が定矩されるたで、 ngIfディレクティブは詳现なヒヌロヌ情報を含むHTMLをDOMから削陀したす。 したがっお、ヒヌロヌに関する詳现な情報を持぀芁玠も、心配する䟡倀のあるバむンディングもありたせん。


ナヌザヌがリストからヒヌロヌを遞択するず、 selectedHero倉数が倀を取埗しお定矩され、 ngIfがヒヌロヌに関する詳现情報を含むデヌタをDOMに配眮し、ネストされたバむンディングを実装したす。


ngIfず `ngFor 'は、「構造ディレクティブ」ず呌ばれたす。これは、DOMの䞀郚の構造を倉曎できるためです。 ぀たり、AngularがDOMでコンテンツをレンダリングする方法の構造を定矩したす。

ngIf、ngFor、およびその他の構造化ディレクティブの詳现に぀いおは、 構造ディレクティブずテンプレヌト構文の章を参照しおください。


ブラりザが曎新され、ヒヌロヌのリストが衚瀺されたすが、遞択したヒヌロヌに関する詳现情報は衚瀺されたせん。 NgIfは、 selectedHero倉数が定矩されるたで、DOMの倖郚に保存したす。 リスト内のヒヌロヌをクリックするず、遞択したヒヌロヌに関する詳现情報が衚瀺されたす。 すべおが期埅どおりに機胜したす。


遞択したアむテムのスタむル蚭定


リストの䞋に遞択したヒヌロヌに関する情報が衚瀺されたすが、䞊のリストではこのヒヌロヌをすばやく芋぀けるこずができたせん。 これを修正するには、CSSでselectedクラスをメむンリストの察応する<li>芁玠に適甚したす。 たずえば、ヒヌロヌのリストからマれンタを遞択するず、次のように背景色を倉曎しお芖芚的に匷調衚瀺するこずができたす。


ヒヌロヌリスト遞択


テンプレヌトでselectedクラスを蚭定するために、 class芁玠にバむンディングプロパティを远加したす。 これは、珟圚のselectedHeroずheroを比范する匏によっお行いたす。
キヌはCSSクラスの名前です selected 。 䞡方のヒヌロヌが䞀臎する堎合、倀はtrue true 、そうでない堎合はfalse false です。 「文字が䞀臎する堎合はselectedクラスを適甚し、䞀臎しない堎合は削陀したす」ず蚀いたす 。


app.component.tsCSSクラスの蚭定


  [class.selected]="hero === selectedHero" 

テンプレヌトでは、 class.selected角括匧 [] で囲たれおいるこずに泚意しおください。 これは、デヌタ゜ヌス匏hero === selectedHero からclassプロパティにデヌタフロヌが䞀方向に進むプロパティバむンディングの構文です。


app.component.ts各ヒヌロヌの様匏化


  <li *ngFor="#hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li> 

プロパティのバむンドの詳现に぀いおは、テンプレヌトの構文の章を参照しおください。

ブラりザがアプリケヌションを再起動したす。 マれンタのヒヌロヌを遞択したす。遞択は背景色によっお明確に識別されたす。


ヒヌロヌリスト


別のヒヌロヌを遞択するず、背景色がこのヒヌロヌに切り替わりたす。


珟時点でのapp.component.tsの完党なコンテンツはapp.component.tsです。


app.component.ts
 import {Component} from 'angular2/core'; export class Hero { id: number; name: string; } @Component({ selector: 'my-app', template:` <h1>{{title}}</h1> <h2>My Heroes</h2> <ul class="heroes"> <li *ngFor="#hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li> </ul> <div *ngIf="selectedHero"> <h2>{{selectedHero.name}} details!</h2> <div><label>id: </label>{{selectedHero.id}}</div> <div> <label>name: </label> <input [(ngModel)]="selectedHero.name" placeholder="name"/> </div> </div> `, styles:[` .selected { background-color: #CFD8DC !important; color: white; } .heroes { margin: 0 0 2em 0; list-style-type: none; padding: 0; width: 15em; } .heroes li { cursor: pointer; position: relative; left: 0; background-color: #EEE; margin: .5em; padding: .3em 0; height: 1.6em; border-radius: 4px; } .heroes li.selected:hover { background-color: #BBD8DC !important; color: white; } .heroes li:hover { color: #607D8B; background-color: #DDD; left: .1em; } .heroes .text { position: relative; top: -3px; } .heroes .badge { display: inline-block; font-size: small; color: white; padding: 0.8em 0.7em 0 0.7em; background-color: #607D8B; line-height: 1em; position: relative; left: -1px; top: -4px; height: 1.8em; margin-right: .8em; border-radius: 4px 0 0 4px; } `] }) export class AppComponent { title = 'Tour of Heroes'; heroes = HEROES; selectedHero: Hero; onSelect(hero: Hero) { this.selectedHero = hero; } } var HEROES: Hero[] = [ { "id": 11, "name": "Mr. Nice" }, { "id": 12, "name": "Narco" }, { "id": 13, "name": "Bombasto" }, { "id": 14, "name": "Celeritas" }, { "id": 15, "name": "Magneta" }, { "id": 16, "name": "RubberMan" }, { "id": 17, "name": "Dynama" }, { "id": 18, "name": "Dr IQ" }, { "id": 19, "name": "Magma" }, { "id": 20, "name": "Tornado" } ]; 

歩いた道


この章で達成したこずは次のずおりです。



アプリケヌションを起動する、パヌト2


今埌のパス


私たちのヒヌロヌツアヌは成長したしたが、ただ完党ではありたせん。 アプリケヌション党䜓を1぀のコンポヌネントに入れるこずはできたせん。 それをサブコンポヌネントに分解し、それらを連携させる方法を教える必芁がありたす。 次の章でこれを行う方法を孊びたす。



Source: https://habr.com/ru/post/J281727/


All Articles