آموزش پروژه محور درج رکورد

چاپ

آموزش پروژه محور درج رکورد

در مطلب قبل، نحوه ی ویرایش اطلاعات جدول اصلی، آموزش داده شد، حالا می خواهیم کاربران قادر باشند، یک بخش فروش جدید (Territory) را برای یک کارمند اضافه کنند.

برای انجام این کار، فعالیت های زیر باید انجام شود:

  1. پیکربندی DataSource جدول داخلی
  2. اضافه کردن ComboBox در بالای جدول داخلی
  3. پیاده سازی فایل PHP سمت سرور

پیکربندی DataSource جدول داخلی

در DataSource مربوط به Grid داخلی، باید گزینه create از transport و همچنین گزینه model از schema پیکربندی شود:

index.php - پیکربندی DataSource جدول داخلی

function detailInit(e) {
    // get a reference to the current row being initialized
    var detailRow = e.detailRow;
    employeeTerritoriesDS = new kendo.data.DataSource({
            transport: {
                    read: "data/employeeTerritories.php",
                    create: {
                        url: "data/employeeTerritories.php",
                        type: "PUT"
                    }
            },
            schema: {
                data: "data",
                model: {
                    id: "EmployeeTerritoryID"
                }
            },
            serverFiltering: true,
            filter: { field: "EmployeeID", operator: "eq", value:e.data.EmployeeID }
        });
    // create a subgrid for the current detail row, getting territory data for this employee
    detailRow.find(".subgrid").kendoGrid({
        dataSource: employeeTerritoriesDS,
        columns: [{ title: "Territories", field: "TerritoryDescription" }],
        toolbar: [ "save" ],
editable: true,
        navigable: true
    });
};                            

در ادامه متوجه خواهید شد که چرا فایل territories.php را به employeeTerritories.php تغییر نام داده ایم.

بدلیل اینکه بتوانیم به اطلاعات DataSource مربوط به جدول داخلی، دسترسی داشته باشیم، پیکربندی آنرا خارج از Grid انجام می دهیم و در متغیر employeeTerritoriesDS ذخیره می کنیم:

توجه: هنگام تعریف متغیرها در JavaScript، اگر از کلمه کلیدی "var" استفاده نشود آن متغیر، عمومی در نظر گرفته می شود. اما انجام این کار بصورت کلی صحیح نیست، و در این تمرین بدلیل سادگی انجام کار، از آن استفاده شده است.

با تنظیم گزینه toolbar با مقدار "save"، دکمه "save" در نوار بالایی جدولِ داخلی، نمایش داده خواهد شد.


اضافه کردن ComboBox در بالای جدول داخلی

در این نقطه، احتیاج داریم که روشی را برای اضافه کردن یک بخش فروش جدید، پیاده کنیم.

ما یک جدول Territories داریم که اطلاعات بخش های فروش در آن ذخیره می شود و یک جدول Employees برای کارمندان و ارتباط بین آنها در جدول EmployeeTerritories ذکر شده است.

حالا اگر اجازه دهیم که کاربر، هر متنی را وارد کند، ابتدا باید آنرا در جدول Territories درج کنیم و سپس باید جدول EmployeeTerritories ویرایش شود. اما نمی توانیم به کاربران اجازه دهیم که هر متنی را وارد کنند. چون ممکن است کاربر، یک متن تکراری را برای بخش های فروش وارد کند. راه حلی که برای این موضوع در نظر گرفته ایم، استفاده از یک لیست انتخابی است.

نحوه ی اضافه کردن ComboBox به جدول داخلی قبلاً ذکر شده است. همان طور که می دانید روش انجام کار، استفاده از Template هاست.

Template جدید ما شامل: یک <input> و یک <button> است.

تگ <input> را به یک ComboBox تبدیل می کنیم و برای رویداد onclick دکمه <button> تابعی می نویسیم که مقدار انتخاب شده ComboBox را برای کارمند انتخابی، به جدول EmployeeTerritories اضافه کند.

index.php - اضافه کردن comboBox و دکمه "Add" به جدول داخلی

<script type="text/x-kendo-template" id="template">
    <div>
        <div style="margin-bottom: 10px;">
            <input id="territory_#= data.EmployeeID #" class="comboBox" />
            <button class="k-button add-territory" data-employee-id="#= data.EmployeeID #" onclick="addTerritory(this)" >Add</button>
        </div>
        <div class="subgrid"></div>
    </div>
</script>

سینتکسی که در بالا مشاهده می کنید، ساختار Template نویسی در Kendo UI است. در نتیجه اجرای سنتکس # data.EmployeeID =#، کد کارمند (EmployeeID)، جایگزین خواهد شد.

 همان طور که در آموزش قبلی (آموزش پروژه محور جداول تودرتو) متوجه شدید، هنگام پیکربندی Grid داخلی، گزینه detailInit را با تابع ()detailInit تنظیم کردیم. این تابع زمانی که یکی از ردیف ها باز می شود، فراخوانی می شود.

زمان فراخوانی این تابع، آرگومان e که شامل اطلاعات ردیف انتخاب شده است، علاوه براینکه به تابع ()detailInit ارسال می شود به Template نیز ارسال می شود. بنابراین با استفاده از شیء data از پارامتر e می توانید به EmployeeID دسترسی داشته باشید.

در کد بالا، برای تنظیم مقدار id در تگ <input> و همچنین data-employee-id در تگ <button>، از کد کارمند انتخاب شده یا data.EmployeeID استفاده شده است، دلیل این کار را در ادامه متوجه خواهید شد.

ما همچنین برای تگ <button> رویداد onclick را با تابع ()addTerritory تنظیم کردیم که البته با استفاده از کلمه کلیدی this یک نمونه از خودش را به تابع ارسال می کند.

در تابع ()detailInit نیاز داریم که یک DataSource برای کامبوباکس مان تعریف کرده و با استفاده از متد ()kendoComboBox کامبوباکس را ایجاد کنیم. ما همچنین به یک فایل PHP، برای بخش های فروش، نیاز داریم.

همان طور که در ابتدای این مطلب متوجه شدید، فایل territories.php را به employeeTerritories.php تغییر نام دادیم و حالا فایل territories.php را همان طور که از اسمش پیداست برای برگرداندن لیست بخش های فروش در نظر می گیریم.

توجه: در فایل territories.php، باید تمام بخش های فروش، باستثنای آنهایی که قبلاً برای کارمند انتخاب شده است را لیست کنیم.

با توجه به مورد بالا، باید آی دی کارمند انتخاب شده از جدول اصلی را به فایل territories.php ارسال کنیم، این کار را هنگام پیکربندی گزینه read با تنظیم پارامتر EmployeeID بعد از علامت سوال (؟) انجام می دهیم:

index.php - ساخت ComboBox مربوط به بخش های فروش

function detailInit(e) {
    // get a reference to the current row being initialized
    var detailRow = e.detailRow;
    
    //کدهای مربوط به جدول داخلی یعنی جدول بخش های فروش در این قسمت قرار دارد
    
    // پیکربندی دیتا سورس
    territoriesDS = new kendo.data.DataSource({
        transport: {
            read: "data/territories.php?EmployeeID=" + e.data.EmployeeID
        },
        schema: {
            data: "data",
            model: {
                id: "TerritoryID"
            }
        }
    });
    
    // ایجاد کامبو باکس
    detailRow.find(".comboBox").kendoComboBox({
        dataSource: territoriesDS,
        dataTextField: "TerritoryDescription",
        dataValueField: "TerritoryID"
    });            
};           

 حالا در شاخه data، فایل territories.php را ایجاد می کنیم.

territories.php - برگرداندن لیست بخش های فروش

<?php

    $link = mysql_pconnect("localhost", "root", "3411") or die("Could not connect");

    mysql_select_db("northwind") or die("Could not select database");

    $arr = array();

    // DISCLAIMER: It is better to use PHP prepared statements to communicate with the database.
    //             this provides better protection against SQL injection.
    //             [http://php.net/manual/en/pdo.prepared-statements.php][4]

    // get the parameters from the get. escape them to protect against sql injection.
    $employeeId = mysql_real_escape_string($_REQUEST["EmployeeID"]);

    $rs = mysql_query("SELECT t.TerritoryID, TRIM(t.TerritoryDescription) AS TerritoryDescription
                        FROM Territories T
                        WHERE TerritoryID NOT IN (SELECT et.TerritoryID FROM EmployeeTerritories et WHERE et.EmployeeID = " .$employeeId.")"
                        ." ORDER BY t.TerritoryDescription ASC");
    while($obj = mysql_fetch_object($rs)) {

        $arr[] = $obj;

    }

    header("Content-type: application/json");

    echo "{\"data\":" .json_encode($arr). "}";

?>

حالا اگر پروژه را اجرا نمایید، و یکی از ردیف ها را باز کنید، یک کامبو باکس همراه با یک دکمه در بالای Grid بخش های فروش، نمایش داده می شود:


اضافه کردن، گزینه انتخاب شده از کامبو باکس به جدول بخش های فروش

تا اینجای کار، موفق شدیم که لیست، بخش های فروش را در کامبو باکس نمایش دهیم، در ادامه می خواهیم زمانی که روی دکمه "Add" کلیک شد، دو مورد زیر انجام شود:

  1. گزینه انتخاب شده از کامبو باکس به جدول بخش های فروش اضافه شود.
  2. گزینه ی انتخاب شده از کامبو باکس از لیست کامبو باکس حذف شود.

index.php - پیاده سازی رویداد onclick دکمه Add

var addTerritory = function(sender) {

    // get the employee id off the data-employee-id attribute of the button
    var employeeId = $(sender).data("employee-id");

    // get a reference to the combobox which contains the selected item
    var comboBox = $("#territory_" + employeeId).data("kendoComboBox");

    // add the item to the datasource - it is thusly added to the grid
    employeeTerritoriesDS.add({ EmployeeID: employeeId, TerritoryDescription: comboBox.text(),  TerritoryID: comboBox.value() });

    // remove the current item from the combobox - it's no longer a valid selection
    territoriesDS.remove(comboBox.value());

    // clear the text of the combobox
    comboBox.text("");
};

 توضیح کد بالا:

خط اول: با استفاده از ویژگی data-employee-id که در <button> تعریف شد، کد کارمند را در متغیر employeeId ذخیره می کند.

خط دوم: هر کدام از ردیف های اطلاعاتی کارمندان را که باز کنید یک کامبوباکس منحصر بفرد که از طریق id قابل شناسایی است، نمایش داده می شود، حالا با استفاده از این id می توانیم براحتی به کامبو باکس دسترسی داشته باشیم و از آیتم انتخاب شده آن، باخبر شویم.

توجه: می توانیم به تمام widgetها یا ابزارهای Kendo UI از طریق دستور زیر اشاره کنیم، البته بعد از اینکه آنها را initialize کردیم:

ارجاع به ابزارهای Kendo UI

data(“kendoWidgetName”)

خط سوم: این خط در واقع، یک آیتم داده به DataSource تعریف شده برای Grid داخلی یعنی employeeTerritoriesDS اضافه می کند. ما قصد نداریم داده ها را برای ذخیره به سرور ارسال کنیم، و در این لحظه، آیتم داده اضافه شده فقط سمت کاربر نمایش داده می شود (برای ذخیره اطلاعات روی سرور، باید دکمه "save" از نوار بالایی grid، کلیک شود)

خط چهارم و پنجم: دو خط آخر، آیتم انتخاب شده را از کامبوباکس حذف می کند.


نوع متد PUT و DELETE در PHP

در این لحظه اجاز دهید تا متد نوع PUT را به فایل employeeTerritories.php اضافه کنیم. برخلاف متدهای نوع GET و POST که می توانیم براحتی مقادیر ارسال شده از فرم را با استفاده از متغیرهای GET_$ و POST_$ سمت سرور دریافت کنیم برای نوع PUT و یا DELETE چنین ظرفی وجود ندارد.

در هر صورت، ما می توانیم با استفاده از متد ()file_get_contents در PHP، داده های ورودی (input) را بخوانیم و آنها را داخل یک آرایه بریزیم و به متغیرهایی که از طریق رسانه بعنوان مقادیر فرم ارسال کرده ایم، دسترسی داشته باشیم:

employeeTerritories.php

<?php
    $employeeID = $_REQUEST["filter"]["filters"][0]["value"];
            
    $link = mysql_connect("localhost", "root", "3411") or die("Unable To Connect To Database Server");
    mysql_select_db("northwind") or die("Unable To Connect To Northwind");

    // add the header line to specify that the content type is JSON
    header("Content-type: application/json");

    // determine the request type
    $verb = $_SERVER["REQUEST_METHOD"];

    // handle a GET
    if ($verb == "GET") {
        $arr = array();

        $rs = mysql_query("SELECT CONCAT(et.EmployeeID, et.TerritoryID) AS EmployeeTerritoryID, t.TerritoryID, e.EmployeeID,
                                TRIM(t.TerritoryDescription) AS TerritoryDescription
                              FROM Territories t
                              INNER JOIN EmployeeTerritories et ON t.TerritoryID = et.TerritoryID
                              INNER JOIN Employees e ON et.EmployeeID = e.EmployeeID
                              WHERE e.EmployeeID =".$employeeID);

        while($obj = mysql_fetch_object($rs)) {
               $arr[] = $obj;
        }
        
        echo "{\"data\":" .json_encode($arr). "}";
    }
    
    if ($verb == "PUT") {
        $request_vars = Array();
        parse_str(file_get_contents('php://input'), $request_vars );

        // DISCLAIMER: It is better to use PHP prepared statements to communicate with the database.
        //             this provides better protection against SQL injection.
        //             [http://php.net/manual/en/pdo.prepared-statements.php][4]

        // get the parameters from the get. escape them to protect against sql injection.

        $territoryId = mysql_real_escape_string($request_vars["TerritoryID"]);

        $employeeID = mysql_real_escape_string($request_vars["EmployeeID"]);

        $sql = "INSERT INTO EmployeeTerritories (EmployeeID, TerritoryID) VALUES (" .$employeeID ."," .$territoryId .")";

        $rs = mysql_query($sql);

        if ($rs) {
            echo true;
        }
        else {
            header("HTTP/1.1 500 Internal Server Error");
            echo false;
        }
    }
?>

حالا پروژه را اجرا کنید و یکی از ردیف های کارمند را باز کنید، از کامبوباکس بخش های فروش یکی را اضافه کنید. زمانی که روی دکمه "Save" از نوار بالایی Grid کلیک نمایید، آیتم یا آیتم هایی که اضافه کرده اید به سرور ارسال می شود.


دانلود فایل های پروژه درج رکورد

پاسورد: www.beyamooz.com

حجم: 1.57 مگا بایت