顯示具有 JQuery 標籤的文章。 顯示所有文章
顯示具有 JQuery 標籤的文章。 顯示所有文章

2018年5月22日 星期二

Kendo UI MVVM 自訂Validator規則的問題 | Kendo UI MVVM custom required Validator problem

markdown

# 情境

一個Grid,裡面的row是template,
按鈕除了編輯刪除,其他按鈕案出來的視窗也是template,
在template裡面還有套template,然後都是MVVM去設定事件,
在最尾端的一個表單,要做表單驗證,
有一個欄位是radio button,多選一,當選到某值時另一文字輸入框欄位就變必填

# 問題

如何在MVVM的model中套用這個特定的required驗證

# 解題過程

我原本找到去擴充model binding的binder方法的方向
https://stackoverflow.com/questions/15945755/set-tag-attribute-based-on-variable-value-with-kendo-binding/15947852#15947852
但他要做一個html元件的跟一個widget的,名字還有邏輯,沒搞太懂;

後來轉向套用validator在表單上,雖然不太MVVM,但是可解的方法,
可是這個必填欄位不知為何在執行驗證時會跳
`n[t].call is not a function`
錯誤,後來發現 **不能把validator用的物件放在你的MVVM ViewModel**,
他在執行遍歷驗證時會抓到observable的一些屬性但無法辨識(例如`_events`)然後就跳那個錯誤,
我本來以為MVVM就是你用到的東西都塞MODEL裡就對了,不過這個情境應該不是這樣放...
再來是自訂驗證規則名稱的雷,
我原本取名`PayAccountRequired`,結果竟然讓input不是required也套上required屬性,整個鬼打牆找了很久,後來把規則名稱改成`PayAccountRule`,竟然就正常了....

從來沒想到這個驗證會讓我卡好幾個小時....

完成的範例
http://jsfiddle.net/o8ym26jj/2/

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()` 來轉

2015年12月23日 星期三

blockUI jQuery配bootstrap無法置中 | blockUI with jQuery bootstrap not center properly

問題情境:
一個表單,上半部要先填條件後帶出資料,才繼續填下半部
下半部的ui先用blockUI罩起來,中間顯示「請填上半部的資料」
結果那個顯示文字在BOOTSTRAP的表單置中樣式套用後就歪掉了

解法:
顯示訊息的時候指定
centerX: false,
centerY: false

參考:
Why does my div not center properly?http://stackoverflow.com/questions/2518465/why-does-my-div-not-center-properly


2015年12月4日 星期五

ASP.NET GridView Header flow by scroll up and down use JQuery | WebForm的Gridview 欄標題 以JQuery置頂的方法

WebForm的Gridview元件想要讓欄標題可以置頂的方法

我的Gridview是用template做版面的,資料很多很長,捲下去時就看不見欄標題,很不方便,

解法參考來源:
http://stackoverflow.com/questions/2177983/how-to-make-div-follow-scrolling-smoothly-with-jquery
answered by ajax333221

1.原本是只有設定HeaderText,現在要加上HeaderTemplate,然後用div包起來標題文字


<asp:TemplateField HeaderText="標題" HeaderStyle-HorizontalAlign="Left">

                                <HeaderTemplate>

                                    <div class="divTH">

                                        <label>標題</label>

                                    </div>

                                </HeaderTemplate>

                                <ItemTemplate>

                                   ......

                                </ItemTemplate>

</asp:TemplateField>


2.div給一個css class,這個class加上fixed時就會固定置頂


.divTH.fixed {

                position: fixed;

                top: 0;

            }


3.JQUERY


$(document).ready(function () {

if (!($.browser == "msie" && $.browser.version < 7)) {

            var target = ".divTH", top = $(target).offset().top - parseFloat($(target).css("margin-top").replace(/auto/, 0));

            $(window).scroll(function (event) {

                if (top <= $(this).scrollTop()) {

                    $(target).addClass("fixed");

                } else {

                    $(target).removeClass("fixed");

                }

            });

        }

});

2015/12/25 追記:
如果有GridView是不要一進網頁就databinding的,那網頁ready的時候就沒有欄位標題可以註冊,
這樣就讓效果無效了,我想到的兩種解決方法:

一種是把Jquery部分改放到function pageLoad() { }事件,
這個事件會在aspx postback回來後觸發
但要判斷有沒有註冊過window scroll 才去註冊那個事件
不然每次post back都會註冊一次 就會有問題
我沒有把這方法做完,改用我想到的第二種方法

第二種比較簡單的方法是,設定gridview屬性ShowHeaderWhenEmpty="true"
然後在page load事件給gridview空的source後bind
gv.DataSource = new DataTable();
gv.DataBind();
這樣就會沒資料但顯示標頭,就可以讓javascript註冊事件

2015年9月25日 星期五

How jquery.validate.js do multi remote rule

使用jquery.validate做前端驗證,搭配remote做AJAX到後端驗證

有一個需求
新增紀錄時驗證客戶編號欄位:
1.存在資料庫
然後新需求的驗證是
2.本月份紀錄中若有成交紀錄則不可新增

我試著對一個欄位加兩個remote屬性,他會取最後加的那個,所以不行這樣,
於是就把原本的方法改成


if (資料庫存在此客編)
{
   if(本月此客編無成交紀錄)
   {
      return JsonConvert.SerializeObject(true);
   }
   else
   {
      return  JsonConvert.SerializeObject("本月此客編已有成交紀錄");
   }
}
else
{
   return  JsonConvert.SerializeObject("此客編不存在");
}

然後把原本的ERROR MESSAGE拿掉,
這樣回傳是字串時,jquery.validate就會把字串當成錯誤訊息
回傳TRUE時,就會判定驗證通過了

2015年9月7日 星期一

jquery.validate.js的數字驗證沒有驗證逗點跟小數點

早上又被call程式出錯...又是數字欄位塞了逗點進去

我用jquery.validate.js作前端驗證,不過後端的驗證只有insert寫了,
在update事件忘了寫整數驗證
就那麼剛好user使用了update事件去塞了錯誤的內容
程式就當了

參考
http://blog.rebuildall.net/2011/03/02/jquery_validate_and_the_comma_decimal_separator

他是寫成js去include
我直接把他的方法寫在document ready事件裡面
然後正規表達式改成


//接受不限長度的整數

/^\d*$/


這樣逗點跟小數點都過濾掉了

2015年4月22日 星期三

textarea focus 在最後面

textarea有一串定型字串與提示字串
focus之後要移掉提示字串但是游標要在最後面
原本
$("#textarea").focus(function () {
if( $(this).val()=='定型字串:(提示字串)')
             $(this).val('定型字串');
});

結果效果變成focus後游標會跑到最前面去
改用jquery的focusin事件就解決了
$("#textarea").focusin(function () {
if( $(this).val()=='定型字串:(提示字串)')
             $(this).val('定型字串');
});

2015年3月31日 星期二

SPA專案架構

MVC書一次都教一堆東西...
RAZOR語法、實體資料庫模型、LINQ語法、IENUMERABLE型態...
實在有點懶的學

20150403補充:原來這個叫做SPA架構
前輩教的類MVC架構
1.Modal-就只是個Modal,放屬性欄位而已
2.DAL-資料庫存取相關功能(Data Access Level)
3.主要專案-前端功能

應用在網站專案、Console專案、winform等等都可

1.Visuao Studio建立空白解決方案
2.建立類別庫專案-Modal,想到再加入類別即可
3.建立類別庫專案-DAL
4.建立主要專案,以一般ASP.NET網站專案為例
網站專案加入參考Modal與DAL
DAL加入Modal參考
Modal不參考任何專案,獨立

5.假設要做一個客戶主檔維護功能,有新增刪除修改顯示(CRUD)基本功能
客戶主檔資料表:
SID、客戶名稱、客戶電話三個欄位就好

Modal底下建立客戶主檔類別
public class Customer
{
    ///<summary>流水號</summary>
    public int SID{get;set;}
    ///<summary>客戶名稱</summary>
    public string Name {get;set;}
    ///<summary>客戶電話</summary>
    public string PhoneNumber {get;set;}
}

新增、更新、刪除時的訊息類別
public class msgCRUD
{
    public static const string STATUS_SUCCESS="success";
    public static const string STATUS_ERROR="error";
    public string status {get;set;}
    public string msg {get;set;}
}

DAL底下建立類別
using Modal;
public class CustomerController
{
     public List<Customer> searchData(out msgCRUD msg)
    {
         msg=new msgCRUD();
         List<Customer> list=new List<Customer>();
         DataTable dt=new DataTable();
         try
        {
             //資料庫處理,結果塞到DataTable
             if(dt.Rows.Count>0)
             {
                   foreach(DataRow dr in dt.Rows)
                  {
                       list.Add(new Customer(){
                           SID = dr["SID"].ToString(),
                           Name = dr["Name"].ToString(),
                           PhoneNumber = dr["PhoneNumber"].ToString()
                       });
                  }
             }
         }
         catch(Exception ex)
        {
             msg.status=msgCRUD.STATUS_ERROR;
             msg.msg="搜尋時發生錯誤:"+ex.ToString();
         }
         return list;
    }
}

網站專案底下建立ASP網頁
後端Customer.aspx.cs
[WebMethod]
protected string searchData()
{
    CustomerController cc=new CustomerController();
    List<Customer> list=cc.searchData();
    string myJson=JsonConvert.SerializeObject(list);
    return myJson;
}

前端Customer.aspx
使用JQuery AJAX語法取得資料
...
</form>
<script type="javascript">
function searchData()
{
 if (!window.ajaxValidPass) {
            var sdata = { };
            $.ajax({
                type: "POST",
                async: true,
                url: "Customer.aspx/searchData",
                data: JSON.stringify(sdata),
                contentType: "application/json; charset=UTF-8",
                dataType: 'json',
                success: function (data) {
                    var ary = $.parseJSON(data.d);
                    if (ary) {
                        //處理撈回來的東西
                        }
                        else {
                            alert('找不到資料');
                        }
                    }
                },
                error: function (response) {
                    console.log('error:' + response.responseText);
                    alert('error:' + response.responseText);
                }
            });
        }
}
</script>

到此即為基本的前端到後端,後端到資料存取層的資料傳輸方式
可以擺脫Server Control夾帶的垃圾CODE
又可以保持架構上的彈性