在Component的ngInit()內,使用Service連接遠端API,
這個遠端API會傳回一顆樹,
這顆樹的畫面被要求要像表格的奇偶列變色
假設我先在ngInit(),沒有連結遠端API取樹的值,
而是自己建立的樹狀結構變數treedata
ngOnInit() {
this.treedata = [{
"name": "A",
"submenu": [{
"name": "A-1",
"submenu":[{
"name":"A-1-1",
"submenu":[]
}]},{
"name": "A-2",
"submenu":[]},
...
]},
...
]
}
利用Compoent自己也可當子元件的特性,把這個樹狀結構元件產生出來
in app.component.html
<tree-table [data]="treedata" [level]="0"><tree-table>
in tree-table.component.thml
<div *ngFor="let item of data">
<div class="tbrow">
<div class="tbcell">{{level}}</div>
<div class="tbcell tbcell-name">
<span [style.padding-left.px]="level * 10">{{item.name}}</span>
</div>
<div class="tbcell">
<button>Save</button>
</div>
</div>
<tree-table [data]="item.submenu" [level]="level"></tree-table>
</div>
奇偶列的變色,我是使用jQuery的find方法
使用selector.tbrow:even
來找到偶數列做變色
而這個jQuery的方法,我是寫在ngAfterViewInit
這個生命週期
ngAfterViewInit() {
let $tbrowEven = $(this.elementRef.nativeElement).find(".tbrow:even");
console.log(".tbrow:even length => ",$tbrowEven.length);
$tbrowEven.addClass("tbrow-even");
}
在使用自己建立的樹狀結構變數treedata
的狀況下,
可以成功顯示樹狀表格且換行變色。
使用http.get實際串接api後,
ngOnInit() {
let url = "http://beta.json-generator.com/api/json/get/NJAMxaRNz";
this.http
.get(url)
.map((res:Response) => res.json())
.subscribe((res) => {
this.treedata = res;
console.log("Receive Treedata !!!!!")
});
}
發現表格不會變色了,而且印出.tbrow:even的length居然是0
在不斷的測試之下,我發現這個問題出在我用錯生命週期方法了
jQuery變色語法,應該要下在ngAfterViewChecked
這個生命週期
印出所有生命週期如下圖,並觀察
ngOnInit雖然是我們串接連接遠端API的地方
但是Component的ngAfterContentInit及ngAfterViewInit
會早於真正取得資料的時間點,且這二個Life Cycle Hook只會執行一次
ngAfterContentChecked及ngAfterViewChecked,會在偵測到資料或View變動時觸發。
這個範例中,ngAfterContentChecked,不是我要用jQuery做表格換行變色的地方,
因為它是偵測Content Projection更新(這邊我們沒有使用ng-content)
所以ngAfterViewChecked
才是正解!!!
現在來把程式碼換個地方
ngAfterViewInit() {
console.log("ngAfterViewInit");
let $tbrowEven = $(this.elementRef.nativeElement).find(".tbrow:even");
console.log(".tbrow:even length => ",$tbrowEven.length);
// 把換行變色語法換到ngAfterViewChecked之下
}
ngAfterViewChecked() {
console.log("ngAfterViewChecked");
let $tbrowEven = $(this.elementRef.nativeElement).find(".tbrow:even");
console.log(".tbrow:even length => ",$tbrowEven.length);
$tbrowEven.addClass("tbrow-even");
}
重新發現可以正常運作了
在開發Angular2的元件時,最好先了解Component Life Cycle
接下來的學習筆記,決定要來研讀官網的Component Life Cycle文件。
提供今天的Github專案進度檔案
ㄎㄎ,我又來了,每天一留言
https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html
https://angular.io/docs/ts/latest/api/common/index/NgClass-directive.html
ngFor本身有提供odd, even的參數可以使用, 再搭配ngClass的寫法, 應該就可以省略Jquery那段
哦哦,我可以回應了!
這個例子是把所有的樹每個節點的資料用表格的方式呈現
然後奇偶列要換行變色,
如果用ngFor就只能是當下區塊的奇偶列變色。
我目前想到的是等所有的DOM產生完
才用jQuery找到偶數的DOM做換色
不知還有沒有更好的做法,如果有的話可以一起討論一下!
這個寫法呢? 跟你的做法類似,但不利用JQuery, 然後另外再建立一個tree-row的component處理.
https://gist.github.com/chgc/d441384ae38fb34b8e8af59d56d2c44f
哦哦,你改用了原生的DOM選擇器querySelectorAll
效率會比jQuery的好!
如果是這樣的話,的確不需要特別把jQuery加進專案裡
總是會不知不覺得想用jQuery一下XDDD