markdown
#背景
同事在寫的應用:一個GRID裡面有子GRID
資料在展開master row時才會去抓
但不知道怎麼抓
#解法
我第一個想法是在master grid展開前先記住外面row的uid,
再用uid反推index,再用index去抓到row,再抓到裡面的grid,但很麻煩;
他研究很久後發現在master grid 的detailInit事件做detail grid宣告,
detail grid裡的databound事件
可以用
```
$(this.element[0]).data("kendoGrid");
```
來抓到裡面的grid,簡單明瞭
2018年4月9日 星期一
2018年1月25日 星期四
Kendo UI Grid Filter DatePicker 過濾時分秒 | Kendo UI Grid Filter DatePicker truncate time
markdown
#背景
當grid使用server端做分頁排序篩選時,查詢的邏輯就是靠`ToDataSourceResult`來控制,
所以改不了內容在幹嘛,
當前端Grid需要篩選某日期欄位,該欄位又有時分秒,且使用者不想設定秒數時,
預設的時間篩選欄位只會傳入年月日到後端,時分秒為零,
但這樣在做小於等於或者等於的查詢時就會遇到時分秒不相同而查不到資料的問題,
如果是自己做api,這種小地方可以調整用`System.Data.Entity.DbFunctions.TruncateTime()`來過濾時間,但用Telerik的類別處理時就不行了,
後來查到官方的解法如連結
https://docs.telerik.com/kendo-ui/controls/data-management/grid/how-to/filtering/filter-by-date
大致上就是說要在filter menu初始化時,複寫套用的按鈕的事件,
例如原本設"等於"條件時,只會傳入一個邏輯就是相等一個日期時間值,
我們要調整為兩個邏輯,
用大於等於當天的零點零分零秒與 小於等於當天的23點59分59秒兩個條件傳入後端,
這樣就可以避免對不上時間的問題了
```
filterMenuInit: function (e) { //當日期條件設定為小於/等於時 只會傳入年月日 不會傳入時分秒 //但這樣會撈不到當天0點之後的資料 所以要幫他加到23:59:59來方便處理 //(因為沒辦法調整語法為trunc time) var menu = $(e.container); if (e.field === "ColumnDateTime") { var firstDropDown = $('[data-bind="value: filters[0].operator"]').data('kendoDropDownList'); menu.find('button[type="submit"]').click(function (ev) { if (firstDropDown.value() === 'eq') { ev.preventDefault(); var selectedDate = menu.find('[data-role="datepicker"]').first().data('kendoDatePicker').value(); if (!selectedDate) { $(ev.target).closest('[data-role="popup"]').data('kendoPopup').close(); return; } var startOfFilterDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate()); var endOfFilterDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate(), 23, 59, 59); var filter = { logic: "and", filters: [ { field: "ColumnDateTime", operator: "gte", value: startOfFilterDate }, { field: "ColumnDateTime", operator: "lte", value: endOfFilterDate } ] }; e.sender.dataSource.filter(filter); $(ev.target).closest('[data-role="popup"]').data('kendoPopup').close(); return; } else if (firstDropDown.value() === 'le') { ev.preventDefault(); var selectedDate = menu.find('[data-role="datepicker"]').first().data('kendoDatePicker').value(); if (!selectedDate) { $(ev.target).closest('[data-role="popup"]').data('kendoPopup').close(); return; } var endOfFilterDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate(), 23, 59, 59); var filter = { logic: "and", filters: [ { field: "ColumnDateTime", operator: "lte", value: endOfFilterDate } ] }; e.sender.dataSource.filter(filter); $(ev.target).closest('[data-role="popup"]').data('kendoPopup').close(); return; } }); } }, ```
#背景
當grid使用server端做分頁排序篩選時,查詢的邏輯就是靠`ToDataSourceResult`來控制,
所以改不了內容在幹嘛,
當前端Grid需要篩選某日期欄位,該欄位又有時分秒,且使用者不想設定秒數時,
預設的時間篩選欄位只會傳入年月日到後端,時分秒為零,
但這樣在做小於等於或者等於的查詢時就會遇到時分秒不相同而查不到資料的問題,
如果是自己做api,這種小地方可以調整用`System.Data.Entity.DbFunctions.TruncateTime()`來過濾時間,但用Telerik的類別處理時就不行了,
後來查到官方的解法如連結
https://docs.telerik.com/kendo-ui/controls/data-management/grid/how-to/filtering/filter-by-date
大致上就是說要在filter menu初始化時,複寫套用的按鈕的事件,
例如原本設"等於"條件時,只會傳入一個邏輯就是相等一個日期時間值,
我們要調整為兩個邏輯,
用大於等於當天的零點零分零秒與 小於等於當天的23點59分59秒兩個條件傳入後端,
這樣就可以避免對不上時間的問題了
```
filterMenuInit: function (e) { //當日期條件設定為小於/等於時 只會傳入年月日 不會傳入時分秒 //但這樣會撈不到當天0點之後的資料 所以要幫他加到23:59:59來方便處理 //(因為沒辦法調整語法為trunc time) var menu = $(e.container); if (e.field === "ColumnDateTime") { var firstDropDown = $('[data-bind="value: filters[0].operator"]').data('kendoDropDownList'); menu.find('button[type="submit"]').click(function (ev) { if (firstDropDown.value() === 'eq') { ev.preventDefault(); var selectedDate = menu.find('[data-role="datepicker"]').first().data('kendoDatePicker').value(); if (!selectedDate) { $(ev.target).closest('[data-role="popup"]').data('kendoPopup').close(); return; } var startOfFilterDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate()); var endOfFilterDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate(), 23, 59, 59); var filter = { logic: "and", filters: [ { field: "ColumnDateTime", operator: "gte", value: startOfFilterDate }, { field: "ColumnDateTime", operator: "lte", value: endOfFilterDate } ] }; e.sender.dataSource.filter(filter); $(ev.target).closest('[data-role="popup"]').data('kendoPopup').close(); return; } else if (firstDropDown.value() === 'le') { ev.preventDefault(); var selectedDate = menu.find('[data-role="datepicker"]').first().data('kendoDatePicker').value(); if (!selectedDate) { $(ev.target).closest('[data-role="popup"]').data('kendoPopup').close(); return; } var endOfFilterDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate(), 23, 59, 59); var filter = { logic: "and", filters: [ { field: "ColumnDateTime", operator: "lte", value: endOfFilterDate } ] }; e.sender.dataSource.filter(filter); $(ev.target).closest('[data-role="popup"]').data('kendoPopup').close(); return; } }); } }, ```
2017年12月8日 星期五
Kendo UI Date Picker 民國年格式 | Kendo UI Date Picker Taiwan calander format
markdown
#背景
一個Grid,在編輯時用popup,內容是template,
有個日期欄位,
使用者想要輸入1060101或者10601011735這種日期或日期時間格式
不想要選取也不想要打「-」、空白或「:」
研究了一下也提問在官方討論區了,官方是說不支援民國年這種格式,
實際上你輸入1900年之前的日期,也會無法set,
所以也不能用民國106年直接套上DatePicker/DateTimePicker,而且萬年曆也會不對,
這裡就用textbox自幹一個字串轉日期的方法
(如果想要讓後端收到的值仍然有「-」、空白或「:」,是可以搭配mask)
首先在原本的template的時間輸入框前面加入一個input textbox
```
```
然後準備好字串轉日期、日期轉字串的處理,
這裡列的方法是我很直觀的去寫,沒有做什麼效能分析
```
//傳入值與格式,分析與轉換成JS日期物件 function parseTWDate(val, format) { var result = { result: true, msg: "", DateObj: null }; if (typeof val === "undefined") { result.result = false; return result; } //只接受數字與字串型態 if (typeof val !== "number" && typeof val !== "string") { result.result = false; return result; } //檢查格式字串 if ( format !== "yyyMMdd" && format !== "yyyMMddHHmm" && format !== "yyyMMddHHmmss" ) { result.result = false; result.msg = "不支援的日期格式設定"; return result; } //只接受數字不接受符號 if (/^\d+$/.test(val) === false) { result.result = false; return result; } var str = ""; //數字型態轉文字 if (typeof val === "number") { str = val.toString(); } else { str = val; } //從後往前兩位兩位取出字串,轉數字後做驗證 var sec = 0; var min = 0; var hr = 0; var day = 0; var mon = 0; var year = 0; var movingCount = 0; if (format === "yyyMMddHHmmss") { if (str.length < 11) { result.result = false; return result; } sec = parseInt( str.substring(str.length - movingCount - 2, str.length - movingCount), 10 ); if (sec === NaN || sec > 59 || sec < 0) { result.result = false; return result; } movingCount += 2; } if (format === "yyyMMddHHmm" || format === "yyyMMddHHmmss") { if (str.length < 9) { result.result = false; return result; } min = parseInt( str.substring(str.length - movingCount - 2, str.length - movingCount), 10 ); if (min === NaN || min > 59 || min < 0) { result.result = false; return result; } movingCount += 2; hr = parseInt( str.substring(str.length - movingCount - 2, str.length - movingCount), 10 ); if (hr === NaN || hr > 23 || hr < 0) { result.result = false; return result; } movingCount += 2; } if (str.length < 5) { result.result = false; return result; } day = parseInt( str.substring(str.length - movingCount - 2, str.length - movingCount), 10 ); if (day === NaN || day > 31 || day < 1) { result.result = false; return result; } movingCount += 2; mon = parseInt( str.substring(str.length - movingCount - 2, str.length - movingCount), 10 ); if (mon === NaN || mon > 12 || mon < 1) { result.result = false; return result; } movingCount += 2; year = parseInt(str.substring(0, str.length - movingCount), 10); if (year === NaN || year < 1) { result.result = false; return result; } //JS的日期的月份是0 base result.DateObj = new Date(year + 1911, mon - 1, day, hr, min, sec); return result; } //將日期選擇轉成民國年 function getTWDate(val, format) { var rawYear = val.getFullYear(); var twYear = rawYear - 1911; var rawMonth = val.getMonth() + 1; var twMonth = rawMonth.toString().padStart(2, "0"); var rawDay = val.getDate(); var twDay = rawDay.toString().padStart(2, "0"); var strTWDate = twYear + twMonth + twDay; if (format === "yyyMMddHHmm" || format === "yyyMMddHHmmss") { var hr = val .getHours() .toString() .padStart(2, "0"); var min = val .getMinutes() .toString() .padStart(2, "0"); strTWDate = strTWDate + hr + min; if (format === "yyyMMddHHmmss") { var sec = val .getSeconds() .toString() .padStart(2, "0"); strTWDate = strTWDate + sec; } } return strTWDate; } ```
然後在原本的datasource的schema中加入一個自訂的民國年欄位,類型是字串
這個欄位不會回傳值給API,只是用來data bind,
裡面做自定義驗證方法,在民國年字串輸入框跳開時,去跑日期解析,
成功就把日期物件帶回model,失敗就給予錯誤訊息並回傳false;
原本的欄位也給他一個驗證是如果跑到了驗證就檢查他的值是否可以解析成日期,
這裡弄了很久是不知如何避免偶爾會出現原欄位跳出必填的問題,
還有編輯時無法透過model.set讓他自己data bind去改變前端DOM的值,
set下去model的值竟然不會改,只能手動去塞值&改DOM,
改值的時候也要先改DOM在做SET,不然也會有怪現象
```
var dataSource = { schema: { model: { fields: { myDate: { type: "date", validation: { required: true, dateFormat: function(input, option) { if (input.is("[name='myDate']")) { if (Date.parse(input.val()) !== NaN) { $("#myDateTW").removeAttr("data-TWdate-msg"); $("#myDate").removeAttr("data-required-msg"); return true; } else { $("#myDateTW").attr( "data-TWdate-msg", "格式民國年yyyMMdd" ); return false; } } else { return true; } } } }, myDateTW: { type: "string", validation: { required: true, TWdate: function(input, option) { if (input.is("[name='myDateTW']")) { var val = input.val(); var format = "yyyMMdd"; var result = parseTWDate(val, format); if (result.result) { input.removeAttr("data-TWdate-msg"); //帶回model var source = $("#myDateTW")[0].kendoBindingTarget .source; $("#myDate").val(result.DateObj); source.set("myDate", result.DateObj); return true; } else { input.attr("data-TWdate-msg", "格式民國年" + format); //帶回model var source = $("#myDateTW")[0].kendoBindingTarget .source; $("#myDate").val(val); source.set("myDate", val); return false; } } else { return true; } } }, } } } }, }; }; ```
再來是grid新增或編輯時需要把model的date欄位清空與轉換
```
edit: function(e) { var arg = e; if (e.model.isNew()) { //日期型態先清空 e.model.set("myDate", null); } else { //民國年要先轉好 var myDate = e.model.get("ㄗㄩDate"); var strMyDateTW = getTWDate(myDate, "yyyMMdd"); e.model.myDateTW = strMyDateTW; e.model.set("myDateTW", strMyDateTW); $("#myDateTW").val(strMyDateTW); } } ```
這樣就可以輸入民國年日期轉成西元年日期,編輯時也可以把西元年日期轉回民國年日期了
#背景
一個Grid,在編輯時用popup,內容是template,
有個日期欄位,
使用者想要輸入1060101或者10601011735這種日期或日期時間格式
不想要選取也不想要打「-」、空白或「:」
研究了一下也提問在官方討論區了,官方是說不支援民國年這種格式,
實際上你輸入1900年之前的日期,也會無法set,
所以也不能用民國106年直接套上DatePicker/DateTimePicker,而且萬年曆也會不對,
這裡就用textbox自幹一個字串轉日期的方法
(如果想要讓後端收到的值仍然有「-」、空白或「:」,是可以搭配mask)
首先在原本的template的時間輸入框前面加入一個input textbox
```
```
然後準備好字串轉日期、日期轉字串的處理,
這裡列的方法是我很直觀的去寫,沒有做什麼效能分析
```
//傳入值與格式,分析與轉換成JS日期物件 function parseTWDate(val, format) { var result = { result: true, msg: "", DateObj: null }; if (typeof val === "undefined") { result.result = false; return result; } //只接受數字與字串型態 if (typeof val !== "number" && typeof val !== "string") { result.result = false; return result; } //檢查格式字串 if ( format !== "yyyMMdd" && format !== "yyyMMddHHmm" && format !== "yyyMMddHHmmss" ) { result.result = false; result.msg = "不支援的日期格式設定"; return result; } //只接受數字不接受符號 if (/^\d+$/.test(val) === false) { result.result = false; return result; } var str = ""; //數字型態轉文字 if (typeof val === "number") { str = val.toString(); } else { str = val; } //從後往前兩位兩位取出字串,轉數字後做驗證 var sec = 0; var min = 0; var hr = 0; var day = 0; var mon = 0; var year = 0; var movingCount = 0; if (format === "yyyMMddHHmmss") { if (str.length < 11) { result.result = false; return result; } sec = parseInt( str.substring(str.length - movingCount - 2, str.length - movingCount), 10 ); if (sec === NaN || sec > 59 || sec < 0) { result.result = false; return result; } movingCount += 2; } if (format === "yyyMMddHHmm" || format === "yyyMMddHHmmss") { if (str.length < 9) { result.result = false; return result; } min = parseInt( str.substring(str.length - movingCount - 2, str.length - movingCount), 10 ); if (min === NaN || min > 59 || min < 0) { result.result = false; return result; } movingCount += 2; hr = parseInt( str.substring(str.length - movingCount - 2, str.length - movingCount), 10 ); if (hr === NaN || hr > 23 || hr < 0) { result.result = false; return result; } movingCount += 2; } if (str.length < 5) { result.result = false; return result; } day = parseInt( str.substring(str.length - movingCount - 2, str.length - movingCount), 10 ); if (day === NaN || day > 31 || day < 1) { result.result = false; return result; } movingCount += 2; mon = parseInt( str.substring(str.length - movingCount - 2, str.length - movingCount), 10 ); if (mon === NaN || mon > 12 || mon < 1) { result.result = false; return result; } movingCount += 2; year = parseInt(str.substring(0, str.length - movingCount), 10); if (year === NaN || year < 1) { result.result = false; return result; } //JS的日期的月份是0 base result.DateObj = new Date(year + 1911, mon - 1, day, hr, min, sec); return result; } //將日期選擇轉成民國年 function getTWDate(val, format) { var rawYear = val.getFullYear(); var twYear = rawYear - 1911; var rawMonth = val.getMonth() + 1; var twMonth = rawMonth.toString().padStart(2, "0"); var rawDay = val.getDate(); var twDay = rawDay.toString().padStart(2, "0"); var strTWDate = twYear + twMonth + twDay; if (format === "yyyMMddHHmm" || format === "yyyMMddHHmmss") { var hr = val .getHours() .toString() .padStart(2, "0"); var min = val .getMinutes() .toString() .padStart(2, "0"); strTWDate = strTWDate + hr + min; if (format === "yyyMMddHHmmss") { var sec = val .getSeconds() .toString() .padStart(2, "0"); strTWDate = strTWDate + sec; } } return strTWDate; } ```
然後在原本的datasource的schema中加入一個自訂的民國年欄位,類型是字串
這個欄位不會回傳值給API,只是用來data bind,
裡面做自定義驗證方法,在民國年字串輸入框跳開時,去跑日期解析,
成功就把日期物件帶回model,失敗就給予錯誤訊息並回傳false;
原本的欄位也給他一個驗證是如果跑到了驗證就檢查他的值是否可以解析成日期,
這裡弄了很久是不知如何避免偶爾會出現原欄位跳出必填的問題,
還有編輯時無法透過model.set讓他自己data bind去改變前端DOM的值,
set下去model的值竟然不會改,只能手動去塞值&改DOM,
改值的時候也要先改DOM在做SET,不然也會有怪現象
```
var dataSource = { schema: { model: { fields: { myDate: { type: "date", validation: { required: true, dateFormat: function(input, option) { if (input.is("[name='myDate']")) { if (Date.parse(input.val()) !== NaN) { $("#myDateTW").removeAttr("data-TWdate-msg"); $("#myDate").removeAttr("data-required-msg"); return true; } else { $("#myDateTW").attr( "data-TWdate-msg", "格式民國年yyyMMdd" ); return false; } } else { return true; } } } }, myDateTW: { type: "string", validation: { required: true, TWdate: function(input, option) { if (input.is("[name='myDateTW']")) { var val = input.val(); var format = "yyyMMdd"; var result = parseTWDate(val, format); if (result.result) { input.removeAttr("data-TWdate-msg"); //帶回model var source = $("#myDateTW")[0].kendoBindingTarget .source; $("#myDate").val(result.DateObj); source.set("myDate", result.DateObj); return true; } else { input.attr("data-TWdate-msg", "格式民國年" + format); //帶回model var source = $("#myDateTW")[0].kendoBindingTarget .source; $("#myDate").val(val); source.set("myDate", val); return false; } } else { return true; } } }, } } } }, }; }; ```
再來是grid新增或編輯時需要把model的date欄位清空與轉換
```
edit: function(e) { var arg = e; if (e.model.isNew()) { //日期型態先清空 e.model.set("myDate", null); } else { //民國年要先轉好 var myDate = e.model.get("ㄗㄩDate"); var strMyDateTW = getTWDate(myDate, "yyyMMdd"); e.model.myDateTW = strMyDateTW; e.model.set("myDateTW", strMyDateTW); $("#myDateTW").val(strMyDateTW); } } ```
這樣就可以輸入民國年日期轉成西元年日期,編輯時也可以把西元年日期轉回民國年日期了
2017年12月4日 星期一
Kendo UI Grid + datasource 錯誤處理 | Kendo UI Grid datasource error handle
markdown
(我的Kendo版本是2017.3.913)
最常用的CRUD應用元件,KendoUI Grid + Datasource transport,
可以簡單串起Restful API,
但錯誤處理上有一些地方要注意
使用transport時API如果不拋出500或者404之類的錯誤,
而是用處理完成,但處理結果有誤,錯誤訊息放在一個字串屬性裡面的這種模式,
datasource無法去抓出那個物件秀出來,
這時就要用因為有錯誤所以要拋exception的概念,
讓API拋出HttpStatusCode.InternalServerError,
這樣前端ajax呼叫時就會抓到錯誤,
然後丟給datasource裡的error屬性事件處理,
就可以用e.xhr.responseJSON.Message抓出錯誤內容,
但也要加上undefined偵測,不是只有API邏輯錯的時候才會丟錯
所以error物件裡面也不是常常都有xhr
如果是自己寫的介面,例如另外寫kendo window,
並且自訂按鈕送出ajax,你就可以控制ajax的邏輯,
要用「有錯就是要拋錯」或者「你成功執行那就給我200,商業邏輯錯誤再另外包」
哪一種抓錯方式都可以處理了。
另外如果新增刪除修改的API用void類型,datasource的transport會拋一個JSON parsererror的錯,但若是給他回傳值,則不會有這個錯
我用的回傳物件格式:
```
public class OperationOutModel { ///執行結果
public bool result { get; set; }
///錯誤訊息
public string msg { get; set; }
}
```
(我的Kendo版本是2017.3.913)
最常用的CRUD應用元件,KendoUI Grid + Datasource transport,
可以簡單串起Restful API,
但錯誤處理上有一些地方要注意
使用transport時API如果不拋出500或者404之類的錯誤,
而是用處理完成,但處理結果有誤,錯誤訊息放在一個字串屬性裡面的這種模式,
datasource無法去抓出那個物件秀出來,
這時就要用因為有錯誤所以要拋exception的概念,
讓API拋出HttpStatusCode.InternalServerError,
這樣前端ajax呼叫時就會抓到錯誤,
然後丟給datasource裡的error屬性事件處理,
就可以用e.xhr.responseJSON.Message抓出錯誤內容,
但也要加上undefined偵測,不是只有API邏輯錯的時候才會丟錯
所以error物件裡面也不是常常都有xhr
如果是自己寫的介面,例如另外寫kendo window,
並且自訂按鈕送出ajax,你就可以控制ajax的邏輯,
要用「有錯就是要拋錯」或者「你成功執行那就給我200,商業邏輯錯誤再另外包」
哪一種抓錯方式都可以處理了。
另外如果新增刪除修改的API用void類型,datasource的transport會拋一個JSON parsererror的錯,但若是給他回傳值,則不會有這個錯
我用的回傳物件格式:
```
public class OperationOutModel { ///
2017年10月13日 星期五
開發 Kendo UI for JQuery 時遇到的問題
markdown
最近公司導入這個框架,盡量要用它來做功能,
第一眼看上去覺得不錯,簡單功能做都很快,
不過要加上細節時問題就出來了,用一篇文章來記錄。
版本:2017 R3
#CRUD資料來源 datasource使用transport方法時,不可混用function/object,要一致
出現的bug現象為:
在local做的資料處理,刪除/更新之後loading動畫不會解除
ref:官網文件 https://docs.telerik.com/kendo-ui/framework/datasource/crud
#前端驗證validation自訂驗證方法bug
前端驗證validation,寫在datasource的schema裡每個欄位field下,除了預設的方法如required外,自訂的方法會在每個欄位做驗證時被觸發,所以要加上
```
if (input.is("[name='該欄的名稱']")){ //驗證邏輯.... } ```
來確保進來的是該欄而不是其他欄,但這樣就變成每個欄位可能都要自己寫一個funciton,就會變得很亂。
而且若是多個欄位有相同的驗證類別,也不太能寫共用方法,
例如有三個自訂input格式的金額欄位,驗證規則都是數字且3位數內,
自訂是因為不要預設的小數點與上下箭頭,所以要用自訂,
但因為這個自訂驗證方法最後需要手動塞入錯誤訊息:
```
$(input).attr("data-自訂驗證名稱-msg", "最多10位數!");
```
以這個例子,這三個欄位都得自己寫一個自訂驗證方法,把中間的邏輯抽出,
然後外面把function name傳入,如下:
```
//schema.model.fields< fields: { Article: { type: "number", validation: { required: { message: "必填!" }, ArticleMaxlength: function (input) { return vldRuleMaxLength(input,"ArticleMaxlength"); } } }, //另外寫的方法 function vldRuleMaxLength(input, vldFunctionName) { if ((input.is("[name='Article']") || input.is("[name='Section']") || input.is("[name='Item']")) && input.val().length > 3) { $(input).attr("data-" + vldFunctionName + "-msg", "最多3位數!"); return false; } return true; } ```
ref:stackoverflow https://stackoverflow.com/questions/24671452/kendo-grid-column-field-validation
#前端驗證validation,若在自訂editor的欄位使用required,需要在自訂editor的方法裡面把required加入元素TAG內,只用預設屬性沒有作用
ref:官網討論區 http://www.telerik.com/forums/validator-not-firing-for-custom-popup-editor
#前端驗證的BUG
在grid popout editor做新增編輯時的驗證,先輸入符合驗證條件的值,再改成錯誤的值來觸發第一次錯誤訊息後,
再改回之前的值,會發現驗證方法不會被觸發,
目前的處理方法只想到按下存檔前再手動處理一次驗證,只是UX很怪
ref:http://www.telerik.com/forums/validation-in-grid's-schema-only-fire-once
#前端驗證用remote類型(做AJAX)的處理
只能做同步ajax,不能做非同步,不然出錯時無法return false給validator,錯誤訊息就秀不出來,
目前也沒支援非同步
# Grid中使用template做自訂的新增編輯窗版型很麻煩
在grid做popup類型的編輯新增layout時,若不想用預設的一欄一行排版,就要用獨立區塊的template來套在editor上,
ref:官網文件-editable.template那段 https://docs.telerik.com/kendo-ui/api/javascript/ui/grid#editable.template-string
但是官網很難找到你應該要用什麼class來做這些排版,雖然說有引用bootstrap css,
可是套用bootstrap的grid system類css上去,也跟原來單純用BS有差別,都要做調整,
這些k-xxx-class也沒有看到有像BS一樣有個官網區域做介紹,目前還是得用google找討論,然後挖出討論串中的code裡可用的部分拿來用,
#grid的source用Kendo MVC的類別DataSourceRequest取進來值要用post
get抓不到東西會null
#kendoWindow在close之後需要重bind,就要在失效(deactivate)事件做銷毀
ref: https://www.telerik.com/forums/destroy-window-on-close
情境:按下GRID上tool bar某custom按鈕後用$("<div></div>")的方式建立window,
以mvvm方式去kendo bind內容,key欄位有綁blur事件讓他做ajax帶值,
第一次可以work,但在按下右上角x關閉後再次打開就沒有blur事件了,
解決方式是在kendoWindow({})設定中加入deactivate事件處理,
把這個window給destory掉就可以了
#Telerik Report的HTML5的report viewer串date picker的時區問題
kendo ui的datepicker接上REPORT VIEWER有個時區的問題,
在GRID系統裡抓API或送API的時間資料都是正常的,
但送到report viewer的API,會沒有處理時區,造成送去後端時變成GMT+0的時間,
C#後端可以用toLocalTime來轉回,
但報表上的變數沒辦法用toLocalTime,
暫時先在report design裡的變數expression裡面用AddHour(value,hour) +8來處理。
#Kendo UI datasource的date類型資料再轉回asp.net web api2時要用符合格式的日期字串轉回
情境:一個grid配上獨立的datasource操作,不是用grid裡面的datasource給值,也沒有auto bind,
schema裡面有個欄位是date型別,USER不會去編輯他;
在call API後,此欄的值還是WEB API吐出的日期字串格式,`yyyy-MM-ddThh24:mm:ss`,
但在編輯別的欄位後,就因為datasource的schema是date,而轉型為日期物件,
可是在做更新ajax時,並不能直接把日期物件放在data:
```
$.ajax({ url: "your api url", type: "POST", dataType: "json", data: {date=new Date()}, cache: false, async: true, }); ```
後端API會抓不到,所以還是要把日期轉成日期字串,
轉日期字串的方法根據這篇建議是用 `.toISOString()` 來轉
最近公司導入這個框架,盡量要用它來做功能,
第一眼看上去覺得不錯,簡單功能做都很快,
不過要加上細節時問題就出來了,用一篇文章來記錄。
版本:2017 R3
#CRUD資料來源 datasource使用transport方法時,不可混用function/object,要一致
出現的bug現象為:
在local做的資料處理,刪除/更新之後loading動畫不會解除
ref:官網文件 https://docs.telerik.com/kendo-ui/framework/datasource/crud
#前端驗證validation自訂驗證方法bug
前端驗證validation,寫在datasource的schema裡每個欄位field下,除了預設的方法如required外,自訂的方法會在每個欄位做驗證時被觸發,所以要加上
```
if (input.is("[name='該欄的名稱']")){ //驗證邏輯.... } ```
來確保進來的是該欄而不是其他欄,但這樣就變成每個欄位可能都要自己寫一個funciton,就會變得很亂。
而且若是多個欄位有相同的驗證類別,也不太能寫共用方法,
例如有三個自訂input格式的金額欄位,驗證規則都是數字且3位數內,
自訂是因為不要預設的小數點與上下箭頭,所以要用自訂,
但因為這個自訂驗證方法最後需要手動塞入錯誤訊息:
```
$(input).attr("data-自訂驗證名稱-msg", "最多10位數!");
```
以這個例子,這三個欄位都得自己寫一個自訂驗證方法,把中間的邏輯抽出,
然後外面把function name傳入,如下:
```
//schema.model.fields< fields: { Article: { type: "number", validation: { required: { message: "必填!" }, ArticleMaxlength: function (input) { return vldRuleMaxLength(input,"ArticleMaxlength"); } } }, //另外寫的方法 function vldRuleMaxLength(input, vldFunctionName) { if ((input.is("[name='Article']") || input.is("[name='Section']") || input.is("[name='Item']")) && input.val().length > 3) { $(input).attr("data-" + vldFunctionName + "-msg", "最多3位數!"); return false; } return true; } ```
ref:stackoverflow https://stackoverflow.com/questions/24671452/kendo-grid-column-field-validation
#前端驗證validation,若在自訂editor的欄位使用required,需要在自訂editor的方法裡面把required加入元素TAG內,只用預設屬性沒有作用
ref:官網討論區 http://www.telerik.com/forums/validator-not-firing-for-custom-popup-editor
#前端驗證的BUG
在grid popout editor做新增編輯時的驗證,先輸入符合驗證條件的值,再改成錯誤的值來觸發第一次錯誤訊息後,
再改回之前的值,會發現驗證方法不會被觸發,
目前的處理方法只想到按下存檔前再手動處理一次驗證,只是UX很怪
ref:http://www.telerik.com/forums/validation-in-grid's-schema-only-fire-once
#前端驗證用remote類型(做AJAX)的處理
只能做同步ajax,不能做非同步,不然出錯時無法return false給validator,錯誤訊息就秀不出來,
目前也沒支援非同步
# Grid中使用template做自訂的新增編輯窗版型很麻煩
在grid做popup類型的編輯新增layout時,若不想用預設的一欄一行排版,就要用獨立區塊的template來套在editor上,
ref:官網文件-editable.template那段 https://docs.telerik.com/kendo-ui/api/javascript/ui/grid#editable.template-string
但是官網很難找到你應該要用什麼class來做這些排版,雖然說有引用bootstrap css,
可是套用bootstrap的grid system類css上去,也跟原來單純用BS有差別,都要做調整,
這些k-xxx-class也沒有看到有像BS一樣有個官網區域做介紹,目前還是得用google找討論,然後挖出討論串中的code裡可用的部分拿來用,
#grid的source用Kendo MVC的類別DataSourceRequest取進來值要用post
get抓不到東西會null
#kendoWindow在close之後需要重bind,就要在失效(deactivate)事件做銷毀
ref: https://www.telerik.com/forums/destroy-window-on-close
情境:按下GRID上tool bar某custom按鈕後用$("<div></div>")的方式建立window,
以mvvm方式去kendo bind內容,key欄位有綁blur事件讓他做ajax帶值,
第一次可以work,但在按下右上角x關閉後再次打開就沒有blur事件了,
解決方式是在kendoWindow({})設定中加入deactivate事件處理,
把這個window給destory掉就可以了
#Telerik Report的HTML5的report viewer串date picker的時區問題
kendo ui的datepicker接上REPORT VIEWER有個時區的問題,
在GRID系統裡抓API或送API的時間資料都是正常的,
但送到report viewer的API,會沒有處理時區,造成送去後端時變成GMT+0的時間,
C#後端可以用toLocalTime來轉回,
但報表上的變數沒辦法用toLocalTime,
暫時先在report design裡的變數expression裡面用AddHour(value,hour) +8來處理。
#Kendo UI datasource的date類型資料再轉回asp.net web api2時要用符合格式的日期字串轉回
情境:一個grid配上獨立的datasource操作,不是用grid裡面的datasource給值,也沒有auto bind,
schema裡面有個欄位是date型別,USER不會去編輯他;
在call API後,此欄的值還是WEB API吐出的日期字串格式,`yyyy-MM-ddThh24:mm:ss`,
但在編輯別的欄位後,就因為datasource的schema是date,而轉型為日期物件,
可是在做更新ajax時,並不能直接把日期物件放在data:
```
$.ajax({ url: "your api url", type: "POST", dataType: "json", data: {date=new Date()}, cache: false, async: true, }); ```
後端API會抓不到,所以還是要把日期轉成日期字串,
轉日期字串的方法根據這篇建議是用 `.toISOString()` 來轉
訂閱:
文章 (Atom)