jqGrid חלק 2 – עריכה ועריכה בתוך השורה

18 בינואר 2012

תגיות: , ,
2 תגובות


בפוסט הקודם ראינו איך עובדים ברמה הבסיסית עם הגריד הג’אווה-סקריפטי jqGrid. הכוח הגדול של הגריד הוא בכך שהוא עושה את המקסימום בצד הלקוח והולך לשרת כמה שפחות, כפי שנראה כשנוסיף לו עריכה בצד הלקוח.


שינוי הקוד של הפוסט הקודם בשביל שישמור מחיקה/עריכה/הוספה


על מנת שנוכל להוסיף פונקציונאליות של מחיקה/עריכה/הוספה, נצטרך שצד השרת ישמור את הנתונים שלנו ולא סתם יגיש לנו כל פעם את אותה רשימת מוצרים כפי שהיה בפוסט הקודם.
בפוסט הקודם כל פעם שהיינו צריכים את רשימת המוצרים ניגשנו למתודה שייצרה רשימת מוצרים סתם תוך כדי ריצה. זה היה נראה כך:



private List<Product> GetProductsMock()
        {
            var products = new List<Product>();
 
            products.Add(new Product { ID = 1, Name = "חציל", Price = 4 });
            products.Add(new Product { ID = 2, Name = "קישוא", Price = 6.5 });
            products.Add(new Product { ID = 3, Name = "מלפפון", Price = 3.3 });
            products.Add(new Product { ID = 4, Name = "עגבניה", Price = 5 });
            products.Add(new Product { ID = 5, Name = "אפרסמון", Price = 12 });
            products.Add(new Product { ID = 6, Name = "אבטיח", Price = 24 });
            products.Add(new Product { ID = 7, Name = "ענבים", Price = 22 });
            products.Add(new Product { ID = 8, Name = "תפוח", Price = 13.2 });
            products.Add(new Product { ID = 9, Name = "תפוז", Price = 6 });
            products.Add(new Product { ID = 10, Name = "קלמנטינה", Price = 5.5 });
            products.Add(new Product { ID = 11, Name = "בטטה", Price = 8 });
            products.Add(new Product { ID = 12, Name = "תפוח אדמה", Price = 5 });
            products.Add(new Product { ID = 13, Name = "בצל", Price = 4.4 });
            products.Add(new Product { ID = 14, Name = "גזר", Price = 6.2 });
            products.Add(new Product { ID = 15, Name = "אפונה", Price = 19.9 });
            products.Add(new Product { ID = 16, Name = "כרובית", Price = 18 });
            products.Add(new Product { ID = 17, Name = "פומלה", Price = 14.7 });
 
            return products;
        }
        


את הקוד הזה נשנה טיפה. במקום כל פעם ליצור אותם מחדש, נשנה את הקוד ונשמור את הרשימה בזכרון במשתנה סטאטי (שלפיכך תמיד יחזיר את אותה רשימה ולא יתאפס כל פעם מחדש). נגדיר:



private static List<Product> products;

ונאתחל אותם בקונסטרקטור רק פעם אחת:



public DemoGridController()
{
    if (products == null)
        products = GetProductsMock();
}

כך, היות והרשימה הזו היא סטאטית, היא תדמה לנו מסד נתונים שמחזיק רשימה של מוצרים (באפליקציה אמיתית היינו באמת מביאים ממסד נתונים, וכרגע אנחנו “מכסתחים” את זה).


הוספת מחיקה/עריכה/הוספה לגריד


על מנת להוסיף אפשרויות עריכה לגריד, נשנה את קוד היצירה שלו, ונוסיף את השורה הבאה:



$("#list").jqGrid('navGrid', "#pager", { edit: true, add: true, del: true, search: false });

השורה הזו מוסיפה כפתורים של עריכה, הוספה ומחיקה:


image


אם נלחץ על הכפתור הראשון, הוספה, יקפוץ לנו חלון הוספה (ללא פוסט-בק כמובן – צד לקוח לחלוטין):


image


רק שהיות ולא הגדרנו לו באיזה כתובת לשמור בשרת, זה כמובן לא יעבוד:


image


על מנת להגדיר כתובת לשמירה בשרת, נשנה את יצירת הגריד, ונוסיף את השורה הבאה



editurl: "/DemoGrid/EditItem/"

כך שהקוד המלא של יצירת הגריד יראה עכשיו כך:



<script type="text/javascript">
    $(function () {
        $("#list").jqGrid({
            direction: 'rtl',
            url: '/DemoGrid/GetAllItems/',
            datatype: 'json',
            mtype: 'GET',
            colNames: ['#', 'שם', 'מחיר'],
            colModel: [
                  { name: 'Id', index: 'Id', width: 60, align: 'right' },
                  { name: 'Name', index: 'Name', width: 300, align: 'right', editable: true },
                  { name: 'Price', index: 'Price', width: 200, align: 'right', editable: true}],
            pager: $('#pager'),
            rowNum: 10,
            rowList: [5, 10, 20, 50],
            sortname: 'Id',
            sortorder: "desc",
            viewrecords: true,
            caption: 'הגריד הראשון שלי',
            editurl: "/DemoGrid/EditItem/"
        });
 
        $("#list").jqGrid('navGrid', "#pager", { edit: true, add: true, del: true, search: false });
    }); 
</script>


בצד הלקוח עקרונית סיימנו. הגריד עכשיו יודע לערוך ולשמור לשרת, רק שהשרת לא יודע לטפל בפנייה הזו עדיין. במידה וננסה לערוך או להוסיף רשומות עכשיו, נקבל באופן די צפוי את הודעת השגיאה הזו:


image


בשלב הזה נרצה להוסיף מתודה נוספה לשרת – EditItem שתדע לקבל פקודות עריכה/הוספה/מחיקה, אבל בשביל זה צריך לדעת מה הגריד מנסה לשלוח לשרת. בשביל לראות את בקשת האג’קס שלו, נפתח פידלר, או פיירבאג, ונראה את הבקשה מאחורי הקלעים:


image


לכל אחת מהפעולות עריכה/הוספה/מחיקה, הגריד ישלח את כל הפרטים של המוצר שלנו, ובנוסף פרמטר בשם oper שיכיל את סוג הפעולה (add / edit / del). לפיכך כתיבת המתודה בצד השרת תהיה מאוד פשוטה (כאמור, אני כותב ב-asp.net mvc שמקל קצת על הסיפור. זה אפשרי גם ב-asp.net webforms אבל זה יותר מסורבל).


נוסיף את המתודה הבאה לשרת:



public JsonResult EditItem(GridEditOperations Oper, Product item)
{
 
}

המתודה תקבל את המוצר, ואת הפעולה Oper שהיא הפעולה שהגריד שלח. במקום לקבל את הפעולה כמחרוזת פשוטה, בחרתי לקבל אינומרציה במקום – יהיה יותר נוח לפתח מול אינומרציה ו- asp.net mvc יודע אוטומאטית להמיר בין מחרוזת ששולח הגריד לבין אינומרציה בצד השרת. את האינומרציה הגדרתי כך:



public enum GridEditOperations
{
    Edit,
    Del,
    Add
}

מה שיאפשר לנו לממש את המתודה EditItem ע”י פקודת switch פשוטה:



public JsonResult EditItem(GridEditOperations Oper, Product item)
{
    switch (Oper)
    {
        case GridEditOperations.Edit:
            break;
        case GridEditOperations.Del:
            break;
        case GridEditOperations.Add:
            break;
    }
}

כל מה שחסר זה מימוש המחיקה/עריכה/הוספה שזה מן הסתם ישתנה מאפליקציה לאפליקציה. בדוגמא שלנו פשוט אפשר לשנות את המשתנה הסטאטי products שמחזיק את כל המוצרים:



public JsonResult EditItem(GridEditOperations Oper, Product item)
{
    switch (Oper)
    {
        case GridEditOperations.Edit:
            var oldProduct = products.Single(p => p.ID == item.ID);
            oldProduct.Name = item.Name;
            oldProduct.ID = item.ID;
            break;
 
        case GridEditOperations.Del:
            products.Remove(products.Single(p => p.ID == item.ID));
            break;
 
        case GridEditOperations.Add:
            item.ID = products.Count +1;
            products.Add(item);
            break;
    }
 
    // return true to signify success.
    return Json(true);
}


וסיימנו. הגריד עכשיו יודע לערוך/להוסיף/למחוק מוצרים.
הדבר האחרון שנרצה להוסיף לו, שישפר את חווית המשתמש מאוד, הוא לאפשר עריכה בתוך השורה. עריכה בתוך השורה תתן לנו חווית משתמש דומה לאקסל, ובמידה והמשתמש צריך לעדכן הרבה רשומות זוהי דרך מאוד מהירה ונוחה.


הוספת עריכה בתוך השורה


ה- API של jqGrid די מספק תמיכה לכל מה שנראה, אם כי התיעוד שלו לא הכי טוב. במקרה הזה, מה שנרצה לעשות זה שכשהמתמש בוחר שורה, אוטומאטית השורה תכנס למצב עריכה. במידה והמתמש ילחץ אנטר השורה תישמר, ובמידה והוא ילחץ ESC אז השינויים לא ישמרו.
בשביל להוסיף את היכולת הזו, יש להוסיף להגדרה של הגריד פונקציה שתיקרא כאשר שורה נבחרה:



onSelectRow: function (id)
{
    if (id && id !== lastSelectedRowID)
    {
        $('#list').jqGrid('restoreRow', lastSelectedRowID);
        $('#list').jqGrid('editRow', id, true);
        lastSelectedRowID = id;
    }
}

הסבר:
הפונקציה מקבלת את ה ID של השורה עליה לחצנו. במידה והשורה היא לא השורה הקודמת שנבחרה ( lastSelectedRowID ) אז, נכנס למצב עריכה בשורה החדשה ע”י הפקודה “editRow”, ונצא ממצב עריכה בשורה הישנה ע”י הפקודה “restoreRow”.
בנוסף, נצטרך להגדיר גם את lastSelectedRowID כמשתנה שישמור לנו את השורה הקודמת.
הקוד המלא נראה עכשיו כך:



<script type="text/javascript">
 
    var lastSelectedRowID = -1;
 
    $(function () {
        $("#list").jqGrid({
            direction: 'rtl',
            url: '/DemoGrid/GetAllItems/',
            datatype: 'json',
            mtype: 'GET',
            colNames: ['#', 'שם', 'מחיר'],
            colModel: [
                  { name: 'Id', index: 'Id', width: 60, align: 'right' },
                  { name: 'Name', index: 'Name', width: 300, align: 'right', editable: true },
                  { name: 'Price', index: 'Price', width: 200, align: 'right', editable: true}],
            pager: $('#pager'),
            rowNum: 10,
            rowList: [5, 10, 20, 50],
            sortname: 'Id',
            sortorder: "desc",
            viewrecords: true,
            caption: 'הגריד הראשון שלי',
            editurl: "/DemoGrid/EditItem/",
            onSelectRow: function (id)
            {
                if (id && id !== lastSelectedRowID)
                {
                    $('#list').jqGrid('restoreRow', lastSelectedRowID);
                    $('#list').jqGrid('editRow', id, true);
                    lastSelectedRowID = id;
                }
            }
 
        });
 
        $("#list").jqGrid('navGrid', "#pager", { edit: true, add: true, del: true, search: false });
    }); 
</script>

בשביל לבצע עריכה במקום, כל מה שנצטרך לעשות יהיה לבחור שורה, ואוטומאטית היא תכנס למצב עריכה:


image


הגריד שלנו כבר יודע לעשות די הרבה, אבל כרגע עריכה של תאים מתבצעת ע”י תיבת טקסט פשוטה. בפוסט הבא נראה איך אפשר להוסיף קונטרולים אחרים לעריכה, על מנת לתת חווית משתמש אפילו יותר עשירה.




הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

2 תגובות

  1. דודי25 באפריל 2012 ב 12:32

    תודה על הפוסט

    מחכה גם ליצירה דינאמית של שורות ועמודות

    הגב
  2. eladkatz25 באפריל 2012 ב 16:51

    דודי – יצירה דינאמית של שורות – כבר אפשר לעשות מהקוד של הפוסט הנוכחי.

    למה אתה מתכוון בעמודות דינאמיות? הוספת עמודות תוך כדי ריצה?

    הגב