12/08/2018, 14:39

Xử lý Popup với Jquery UI trên MVC asp.net

JQueryUI là viết tắt của jQuery GUI. Nó là một bộ sưu tập các hiệu ứng hoạt hình hình ảnh, vật dụng GUI, và chủ đề thực hiện với jQuery, CSS, HTML và JavaScript. Các plug-ins mới thêm rất nhiều chức năng mới trong các thư viện lõi jQuery. Để tìm hiểu chi tiết mọi người truy cập vào link : ...

JQueryUI là viết tắt của jQuery GUI. Nó là một bộ sưu tập các hiệu ứng hoạt hình hình ảnh, vật dụng GUI, và chủ đề thực hiện với jQuery, CSS, HTML và JavaScript. Các plug-ins mới thêm rất nhiều chức năng mới trong các thư viện lõi jQuery. Để tìm hiểu chi tiết mọi người truy cập vào link : https://jqueryui.com/

Trong phần trước mình đã giới thiệu về JQueryUI để tạo 1 dialog và xử lý các function callback. Hôm nay mình sẽ tiếp tục với việc sử dụng JQueryUI để thực hiện tạo các Popup từ các partial view trong mô hình MVC.

Hiện tại thì có rất nhiều plugin hỗ trợ để xử lý Dialog và Popup, ví dụ như boostrap. Nhưng hôm nay mình giới thiệu JQuery với các bạn vì khi đã hiểu rõ cách thức hoạt động của JqueryUi thì các bạn sẽ nắm vững hơn về Jquery. cũng như có thể dễ dàng custom code theo cách mà các bạn muốn

Quy trình xử lý Popup như sau.

  • sử dụng ajax load partial view và trả về là code html
  • sử dụng JqueryUI để để bung popup
  • handle các function call back theo mong muốn

các bạn có thể xem lại phần xử lý dialog theo link sau => phần 1 (https://viblo.asia/Dattx1/posts/mrDkMMoMkzL#)

var PopupDialog = {
    Stack: []
 }

Mình khởi tạo Object PopupDialog với 1 array Stack.

  • Array "Stack" này sẽ có tác dụng đóng Popup theo đúng thứ tự mở, ví dụ khi bạn mở Popup A, trong Popup A bạn mở tiếp Popup B, nếu ko có array này thì khi các bạn Close Popup B thì popup A sẽ close theo, do 2 popup có các ID, class giống nhau. Để khắc phục việc đó, khi mở popup A thì ID của popup A sẽ đc đẩy vào Array, lần lượt từng Popup 1 sẽ đc đăng ký Id vào Array "Stack", khi close thì mình sẽ lần lượt lấy các Id ra và thực hiện close đúng popup mà mình muốn theo nguyên tắc "vào trước ra sau".
var PopupDialog = {
    Stack: [],
    Show: function (url, functionCallback, title, awidth, height, closeable, openCallback, functionBeforeClose, continueClose) {
         if (closeable == null) closeable = true;
        if (continueClose == null || continueClose == undefined) continueClose = true;
        //var div = "<div id='divDialog'></div>";
        var div = $('#divDialog' + PopupDialog.Stack.length);
        if (div.length == 0) {
            div = "<div id='divDialog" + PopupDialog.Stack.length + "'></div>";
        }
        if (awidth == null) awidth = 'auto';
        if (height == null) height = 'auto';
        $(div).html(');
        $(div).load(url, function (request, response, status, xhr) {
           if (status == 'error') {
                $(this).html(response);
            }

            PopupDialog.Result = null;
            $(this).dialog({
                modal: true,
                height: height,
                awidth: '100%',
                maxWidth: awidth,
                autoOpen: false,
                fluid: true,
                resizable: false,
                draggable: false,
                dialogClass: 'custom-dialog',
                close: function () {
                    PopupDialog.Stack.pop();
                    if (typeof (functionCallback) == 'function') {
                        functionCallback(PopupDialog.Result);
                    }
                },
                beforeClose: function () {
                    if (typeof (functionBeforeClose) === 'function') {
                        functionBeforeClose(PopupDialog.Result);
                    }
                    if (!continueClose) {
                        return false;
                    }
                },
                closeOnEscape: closeable,
                open: function (event, ui) {
                    if (typeof (fluidDialog) != 'undefined') {
                        fluidDialog();
                    }
                    $('.ui-dialog-titlebar').addClass('custom-header-dialog');
                    PopupDialog.Stack.push($(this));
                    if (!closeable) {
                        $(".ui-dialog-titlebar-close").hide();
                    }
                    if (openCallback) {
                        openCallback();
                    }

                },
                title: title
            });
            $(this).dialog('open');
        });
    }
 }

  • Mình xin giới thiệu một số parameter của function
Parameter Type Description
url String Dùng để gọi partial view "controller/action"
functionCallback Function Function sẽ chạy sau khi popup close
title String Popup title
awidth Integer Popup Max Width, nếu ko set giá trị thì sẽ để default là MaxWidth = auto
height Integer Popup Max Height, nếu ko set giá trị thì sẽ để default là MaxWidth = auto
closeable Boolean nếu bằng False thì button ở góc phải popup sẽ bị hide đi, ko set thì mặc định bằng true, được check trong event OpenPopup
openCallback Function Function sẽ chạy trong sự kiện popup open của JqueryUI
functionBeforeClose Function Function sẽ chạy trước khi popup close
continueClose Boolean khi set bằng False thì disable popup close, ko set thì mặc định bằng True, thường kết hợp với "functionBeforeClose"
  • Ngoài ra các bạn có thể tìm hiểu các option của JQueryUI theo link sau: https://api.jqueryui.com/dialog/

  • Tiếp theo mình sẽ nói về việc xử lý việc close popup, như lúc nãy mình nói có 2 vấn đề chính

    • open và close đúng popup
    • close popup theo mục đích mong muốn, ko sử dụng auto close

case số 1: open và close đúng popup

var PopupDialog = {
    .
    .
    . 
    Close: function () {
        var dialog = PopupDialog.Stack[PopupDialog.Stack.length - 1];
        $(dialog).dialog('close');
        $(dialog).dialog('destroy').remove();
    }
}

Function này đc sinh ra với mục đích sau khi xử lý xong thì chỉ cần gọi Function thì sẽ tự động đóng popup trên cùng mà ko ảnh hưởng tới các popup đã mở ở trước, mình sẽ lấy giá trị mới vừa được truyền vào Array "Stack" ra, đó chính là ID của Popup vừa mở gần nhất và thực hiện đóng nó thông qua 2 function của JqueryUI dialog là dialog('close') và dialog('destroy').remove().

case số 1: close popup theo mục đích mong muốn, ko sử dụng auto close.

  • đôi lúc có một số bài toán đưa ra yêu cầu như sau "click button close nhưng trước khi close thì bung message confirm và nếu user click cancel thì ko đóng popup". nếu như bình thường thì khi gọi dialog('close') thì Popup sẽ đóng ngay và chúng ta sẽ ko thực hiện được yêu cầu của bài toán đưa ra.

    Để giải bài toán này trong funtion PopupDialog.Show() có 1 option là "continueClose" khi set bằng false thì sẽ chặn việc Close của popup lại cho phép chạy các function call back thoải mái mà Popup vẫn sẽ đứng yên đó cho các bạn. Nhưng nó lại đẻ ra 1 bài toán khác là sau khi xử lý Function call back thì làm cách nào để close Popup. Để xử lý vấn đề đó thì mình sinh ra function sau.

var PopupDialog = {
    .
    .
    . 
    CloseAbortBeforeCloseEvent: function () {
        var dialog = PopupDialog.Stack[PopupDialog.Stack.length - 1];
        $(dialog).dialog('destroy').remove();
    }
}

Vì sao đoạn này mình lại ko thể sử dụng Function PopupDialog.Close() vì khi gọi function này thì mình đã raise sự kiện close cho Popup nhưng sự kiện Close đã bị chặn bới cờ "continueClose", vì vậy đơn giản chỉ là mình thay vì close Popup thì mình sẽ destroy nó luôn             </div>
            
            <div class=

0