Kendo UI 支援 Angular,手上 Angular 寫的專案幾乎都用 Kendo UI 網頁控制項刻介面。在KendoGrid的欄位設定中,欄位模版也可以嵌入 Angular 語法,挺好用的,如以下的例子:
將第一欄的template設定為字串"{{dataItem.CostCenter}}({{dataItem.CostCenterName}})",KendoGrid將執行Angular繫結,在欄位顯示"分公司代碼(分公司名稱)"。第二欄的template則使用另一種做法,撰寫函式接收dataItem參數,在其中讀取dataItem.Manager1,轉換成特定的HTML內容。網頁執行結果如下:
測試OK。但後方欄位較多排版擠不下,想起KendoGrid有個好用的欄位凍結功能,所以我在第一欄加上locked: true設定,讓後方過長的部分透過水平捲動呈現。
結果欄位是凍結了,列高卻莫名增高近一倍。
使用Chrome開發者工具偵察,發現指定 locked: true 後,<tr>會多出style="height: 53px"樣式,至於 53px 這個數字怎麼來?原因成謎。
又到了 Use the source, Luke!的時刻,找到相關函式設定中斷點,很快真相大白!
啟用欄位凍結功能時,KendoGrid實際上需要建立兩個<table>,左邊的Table放被凍結的欄位,右邊則是未凍結的欄位,以實現左邊欄位固定,右邊欄位可以左右捲動的效果。表格上下捲動時,得靠JavaScript讓左右Table同步位移。(對!就是這麼搞剛)。程式庫裡有個_adjustRowHeight函式,負責比較左右<table>同一列的高度,讓兩邊的列高一致(以數字較大者為準),才能無縫接合,一切聽起合理,問題是文字內容沒變,欄寬充裕,一列絕對放得下,監看offsetHeight1、offsetHeight2變數為何出現39跟54的懸殊對比?
將焦點移到中斷當下的網頁畫面(如下圖),答案揭曉。Angular繫結發生時機較晚,故在_adjustRowHeight()執行的當下,左方的{{dataItem.CostCenter}}({{dataItem.CostCenterName}})尚未置換成資料值,文字過長造成折行,撐大了列高。此時使用 template 函式的第二欄已產生繫結後的內容,高度正常,經_adjustRowHeight()同步,右方列高也放大到54px。之後左側第一欄Angular繫結完成出現分公司名稱,但被撐大的列高已回不去了。
知道問題根源,修改便非難事,將第一欄的template改成ng-bind,就可避免列高被冗長的{{…}}表示式撐大。
template: "<span ng-bind=\"dataItem.CostCenter + '(' + dataItem.CostCenterName + ')'\"></span>",
不過,這次觀察也讓我發現,KendoGrid支援Angular繫結,但執行順序為:template函式完成繫結 –> _adjustRowHeight() –> template Angular語法完成繫結。故 _adjustRowHeight() 抓不到Angular繫結後的真正列高,在某些情況可能形成誤差。若遇到這類問題,改用template函式應可避免。