jquery.validate.unobtrusive ไม่ทำงานกับองค์ประกอบที่แทรกแบบไดนามิก


100

ฉันกำลังทำงานASP.Net MVC3อยู่วิธีที่ง่ายกว่าในการใช้การตรวจสอบความถูกต้องของไคลเอ็นต์คือการเปิดใช้งานไฟล์jquery.validate.unobtrusive. ทุกอย่างทำงานได้ดีสำหรับสิ่งที่ถูกต้องจากเซิร์ฟเวอร์

แต่เมื่อฉันพยายามฉีด 'อินพุต' ใหม่ด้วยจาวาสคริปต์และฉันรู้ว่าฉันต้องเรียกร้อง$.validator.unobtrusive.parse()ให้ทำการตรวจสอบความถูกต้องอีกครั้ง แต่ถึงกระนั้นเขตข้อมูลที่ฉีดแบบไดนามิกเหล่านั้นทั้งหมดจะไม่ทำงาน

ที่แย่กว่านั้นคือฉันพยายามผูกด้วยตนเองโดยใช้jquery.validateและมันก็ใช้ไม่ได้เช่นกัน ความคิดใด ๆ ?


1
หากคุณมาที่นี่จาก Google คุณอาจกำลังมองหาคำตอบของ @Sundara Prabu เนื่องจากคำตอบอื่น ๆ ที่ได้รับการโหวตอย่างหนาแน่นนั้นเก่า
The Muffin Man

คำตอบ:


65

ฉันได้สร้างส่วนขยายสำหรับไลบรารี jquery.validate.unobtrusive ที่แก้ไขปัญหานี้สำหรับสถานการณ์ของฉัน - อาจเป็นที่สนใจ

http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/


ฉันคิดว่าฉันควรโหวตคำตอบของคุณว่าถูกต้อง BTW ห้องสมุดของคุณใช้งานได้กับ MVC RC ล่าสุดหรือไม่ หรือพวกเขาแค่แก้ไข?
xandy

1
เมื่อใช้โค้ดที่ลิงก์ด้านบนตรวจสอบให้แน่ใจว่าคุณอัปเดตเพื่อรวมโค้ดไว้ในความคิดเห็นมิฉะนั้นอาจเสียหายได้ โดยเฉพาะอย่างยิ่งเปลี่ยนบรรทัดตัวเลือกสองบรรทัดเพื่ออ้างถึงรหัสสองครั้ง
Ryan O'Neill

1
ในที่สุดก็สามารถทำให้สิ่งนี้ใช้ได้กับสถานการณ์ของฉันหลังจากการดีบักบางอย่าง แต่ดูเหมือนว่ามันไม่ควรผ่านในตัวเลือกรับสัญญาณ $.validator.unobtrusive.parse()แต่พ่อแม่ป้อนข้อมูลหรือรูปแบบเนื่องจากการเรียกร้องให้ นอกจากนี้ดูเหมือนว่าจะเพิ่มกฎใหม่เท่านั้น แต่ไม่ได้รับการอัปเดตกฎที่มีอยู่?
lambinator

5
คำตอบนี้ควรมีกระดูกหมีของบทความในบล็อกเป็นอย่างน้อย คำตอบเฉพาะลิงก์มักไม่อยู่ในหัวข้อสำหรับ SO
Liam

8
แม้ว่าคำตอบนี้จะมีอายุ 3 ปีขึ้นไป แต่ก็จะมีประโยชน์อย่างยิ่งหากคุณสามารถโพสต์ส่วนสำคัญของคำตอบที่นี่บนเว็บไซต์นี้หรือโพสต์ของคุณมีความเสี่ยงที่จะถูกลบดูคำถามที่พบบ่อยซึ่งกล่าวถึงคำตอบที่ 'แทบจะไม่เกินลิงค์ '. คุณยังสามารถใส่ลิงก์ได้หากต้องการ แต่เป็นเพียง "ข้อมูลอ้างอิง" เท่านั้น คำตอบควรอยู่ในตัวเองโดยไม่ต้องใช้ลิงก์
Taryn

161

ฉันลองใช้แนวทางของ Xhalent แต่น่าเสียดายที่มันไม่ได้ผลสำหรับฉัน แนวทางของโรบินได้ผลและไม่ได้ผล มันใช้งานได้ดีสำหรับองค์ประกอบที่เพิ่มแบบไดนามิก แต่ถ้าคุณพยายามใช้ JQuery เพื่อลบแอตทริบิวต์การตรวจสอบความถูกต้องและระยะเวลาทั้งหมดออกจาก DOM ไลบรารีการตรวจสอบความถูกต้องจะพยายามตรวจสอบความถูกต้อง

อย่างไรก็ตามหากคุณลบข้อมูล "unobtrusiveValidation" ของแบบฟอร์มออกไปนอกเหนือจาก "validationData" ก็จะเป็นเหมือนเสน่ห์สำหรับการเพิ่มและลบองค์ประกอบแบบไดนามิกที่คุณต้องการตรวจสอบความถูกต้องหรือไม่ผ่านการตรวจสอบ

$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");

2
Xhalent ไม่ได้ผลสำหรับฉันในตอนแรกเช่นกันจากนั้นฉันสังเกตว่าการแยกวิเคราะห์ควรถูกส่งผ่านคอนเทนเนอร์สำหรับองค์ประกอบใหม่ไม่ใช่องค์ประกอบในตัวเอง - การแก้ไขอย่างรวดเร็วคือการส่งผ่านรูปแบบทั้งหมดแทนที่จะเป็นองค์ประกอบ - จากนั้นมัน ทำงานเหมือนมีเสน่ห์
Per Hornshøj-Schierbeck

1
มีความคิดว่าทำไมถึงบอกว่าvalidatorไม่ถูกกำหนด? ฉันมีทั้งการตรวจสอบความถูกต้องและการตรวจสอบการอ้างอิงที่ไม่สร้างความรำคาญ การตรวจสอบจะใช้ได้จนกว่าฉันจะเรียกรหัสเหล่านี้ว่า
Shawn Mclean

4
ขอบคุณ. ใช้งานได้กับเนื้อหาที่เพิ่มลงในเพจในมุมมองบางส่วนของ ASP.MVC ที่เพิ่มผ่านการโทร AJAX
Maksym Kozlenko

ขอบคุณสิ่งนี้ช่วยได้ แต่ฉันกำลังประสบปัญหาที่ฉันใช้หีบเพลงบนหน้ากระดาษและถ้าหีบเพลงยุบก็ไม่ได้เริ่มการตรวจสอบความถูกต้อง ฉันจะแก้ไขปัญหานี้ได้อย่างไร? ฉันรู้ว่าฉันใช้ปลั๊กอินตรวจสอบ jquery ปกติแทน MVC3 หรือไม่ฉันต้องบอกว่า$('#form').validate({ignore: ""})
parsh

1
มันใช้ได้กับฉันใน PHP เพียงแค่เพิ่มข้อมูลนี้เนื่องจากทุกความคิดเห็นชี้ไปที่. NET MVC : P
finnTheHumin

43

จริงๆแล้วฉันชอบความเรียบง่ายของโซลูชัน @viggity และ @Robins ดังนั้นฉันจึงเปลี่ยนเป็นปลั๊กอินเล็ก ๆ น้อย ๆ :

(function ($) {

    $.fn.updateValidation = function () {
        var $this = $(this);
        var form = $this.closest("form")
            .removeData("validator")
            .removeData("unobtrusiveValidation");

        $.validator.unobtrusive.parse(form);

        return $this;
    };
})(jQuery);

ตัวอย่างการใช้งาน:

$("#DischargeOutcomeNumberOfVisits")
    .attr("data-val-range-min", this.checked ? "1" : "2")
    .updateValidation();

แทนที่ $ .validator.unobtrusive.parse ("#" + form.attr ("id")); ด้วย $ .validator.unobtrusive.parse (แบบฟอร์ม);
Softlion

คุณยังสามารถลบ. first () ได้อย่างปลอดภัยเนื่องจากค่าที่ใกล้เคียงที่สุดจะส่งกลับเพียง 1 องค์ประกอบ
Softlion

ดีฉันชอบวิธีง่ายๆนี้
nixon

ทำงานได้อย่างสวยงามสำหรับทั้งการเพิ่มและลบแอตทริบิวต์ data-val
Julian Dormon

34

ฉันมีปัญหาเดียวกัน ฉันค้นพบว่าไม่สามารถเรียก $ .validator.unobtrusive.parse () ในแบบฟอร์มเดียวกันสองครั้ง เมื่อโหลดฟอร์มจากเซิร์ฟเวอร์ในขั้นต้นฟอร์มจะถูกแยกวิเคราะห์โดยอัตโนมัติโดยไลบรารีที่ไม่สร้างความรำคาญ เมื่อคุณเพิ่มองค์ประกอบอินพุตลงในฟอร์มแบบไดนามิกและเรียก $ .validator.unobtrusive.parse () อีกครั้งจะไม่ทำงาน เช่นเดียวกับ parseElement ()

lib ที่ไม่สร้างความรำคาญเรียกวิธีการตรวจสอบความถูกต้องของปลั๊กอิน jquery validate เพื่อตั้งค่ากฎและข้อความทั้งหมด ปัญหาคือเมื่อเรียกอีกครั้งปลั๊กอินจะไม่อัปเดตชุดกฎใหม่ที่ได้รับ

ฉันพบวิธีแก้ปัญหาอย่างหยาบอย่างหนึ่ง: ก่อนที่จะเรียกวิธีการแยกวิเคราะห์บน lib ที่ไม่สร้างความรำคาญฉันทิ้งตัวตรวจสอบแบบฟอร์ม:

$('yourForm').removeData("validator");

ตอนนี้เมื่อวิธีการตรวจสอบถูกเรียกโดย lib ที่ไม่สร้างความรำคาญกฎและข้อความทั้งหมดจะถูกสร้างขึ้นใหม่รวมถึงอินพุตที่เพิ่มแบบไดนามิก

หวังว่านี่จะช่วยได้


สมควรได้รับ +1 - มันเป็นวิธีแก้ปัญหาที่หยาบคายอย่างที่คุณพูดเอง แต่มันค่อนข้างชัดเจนว่ามันทำอะไรและคุณจะอยู่ในสถานะอะไรในภายหลัง
Per Hornshøj-Schierbeck

2
จากบล็อกของ Brad Wilsons: "คุณยังสามารถเรียกใช้ฟังก์ชัน jQuery.validator.unobtrusive.parseElement () เพื่อแยกวิเคราะห์องค์ประกอบ HTML เดียว" ความช่วยเหลือใด ๆ
jamesfm

@Per Hornshøj-Schierbeck: @Robin van der Knaap: ฉันใช้เวลา 2-3 ชั่วโมงที่ผ่านมาเพื่อคิดออก !! อย่างไรก็ตาม - สิ่งนี้ใช้งานได้อย่างยอดเยี่ยม น้ำมันดิบทำให้ฉันรู้สึกว่าฉันไม่ควรใช้ - ทำไมฉันถึงไม่อยากทำแบบนี้ล่ะ?
KTF

2
วิธีแก้ปัญหานี้ค่อนข้างหยาบเนื่องจากตัวตรวจสอบความถูกต้องทั้งหมดจะถูกลบออกและคืนสถานะอีกครั้งรวมถึงตัวตรวจสอบที่เพิ่มแบบไดนามิก จะดีกว่าถ้ามีการอัปเดตเฉพาะตัวตรวจสอบความถูกต้องที่เพิ่มแบบไดนามิกเท่านั้น @ Xhalent มีวิธีแก้ปัญหาที่สะอาดกว่าในคำตอบของเขา แต่โดยพื้นฐานแล้วไลบรารีที่ไม่สร้างความรำคาญจาก MS ควรได้รับการอัปเดตสำหรับสถานการณ์นี้
Robin van der Knaap

9

ฉันใช้MVC 4 และ JQuery 1.8ดูเหมือนว่าจำเป็นต้องใช้โค้ดต่อไปนี้เพื่อเปิดใช้งาน Jquery เพื่อตรวจสอบความถูกต้องของเนื้อหาที่แทรกแบบไดนามิกผ่าน Ajax หรือ Jquery ลงใน DOM

ฉันได้สร้างฟังก์ชันโมดูลาร์ซึ่งยอมรับวัตถุ Jquery ขององค์ประกอบที่เพิ่มใหม่ หากคุณโคลนตารางใหม่ด้วย id tblContactsโดยใช้ Jquery เมื่อคลิกปุ่มจากนั้นรวมฟังก์ชันด้านล่างในไฟล์ js ของคุณ

function fnValidateDynamicContent(element) {
    var currForm = element.closest("form");
    currForm.removeData("validator");
    currForm.removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse(currForm);
    currForm.validate(); // This line is important and added for client side validation to trigger, without this it didn't fire client side errors.
}

และเรียกแบบนี้ว่า

fnValidateDynamicContent("#tblContacts")

currform.validate (); ควรเป็น currForm.validate (); (พิมพ์ผิด). ขอบคุณสำหรับการแบ่งปัน แต่สิ่งนี้ใช้ได้กับฉัน
John Mc

1
@JohnMc แก้ไขการพิมพ์ผิดตอนนี้
Sundara Prabu

นี่เป็นสิ่งเดียวที่ใช้ได้กับฉัน (mvc 4 และ jquery 1.10)
The Muffin Man

4

ทำไมไม่ใช้ฟังก์ชันกฎโดยตรงจากเอกสารการตรวจสอบความถูกต้องของ jquery แบบนี้:

$('#newField0').rules('add', {
    required: true,
    minlength: 2
});
//use Html.ValidationMessage will renders a span element, unobtrusive need it to display errors
$('@Html.ValidationMessage("newField0")').insertAfter('#newField0');

2

จากการแก้ปัญหาของ Xhalent ที่ทำเครื่องหมายเป็นคำตอบด้านบนฉันขยายความอีกเล็กน้อย

$.validator.unobtrusive.parseDynamicContent = function (selector) {
    var $selector = $(selector),
        $jqValUnob = $.validator.unobtrusive,
        selectorsDataValAttr = $selector.attr('data-val'),
        $validationInputs = $selector.find(':input[data-val=true]');

    if ((selectorsDataValAttr !== 'true') && 
        ($validationInputs.length === 0)) { 
        return; 
    }

    if (selectorsDataValAttr === 'true') {
        $jqValUnob.parseElement(selector, true);
    }

    $validationInputs.each(function () {
        $jqValUnob.parseElement(this, true);
    });

    //get the relevant form
    var $form = $selector.first().closest('form');

    $jqValUnob.syncValdators($form);
};

/* synchronizes the unobtrusive validation with jquery validator */
$.validator.unobtrusive.syncValdators = function ($form) {
    if ($.hasData($form[0])) {
        var unobtrusiveValidation = $form.data('unobtrusiveValidation'),
            validator = $form.validate();

        // add validation rules from unobtrusive to jquery
        $.each(unobtrusiveValidation.options.rules, function (elname, elrules) {
            if (validator.settings.rules[elname] == undefined) {
                var args = {};
                $.extend(args, elrules);
                args.messages = unobtrusiveValidation.options.messages[elname];
                $("[name='" + elname + "']").rules("add", args);
            } else {
                $.each(elrules, function (rulename, data) {
                    if (validator.settings.rules[elname][rulename] == undefined) {
                        var args = {};
                        args[rulename] = data;
                        args.messages = unobtrusiveValidation.options.messages[elname][rulename];
                        $("[name='" + elname + "']").rules("add", args);
                    }
                });
            }
        });
        // remove all validation rules from jquery that arn't in unobtrusive
        $.each(validator.settings.rules, function (elname, elrules) {
            if (unobtrusiveValidation.options.rules[elname] === undefined) {
                delete validator.settings.rules[elname];
            } else {
                $.each(elrules, function (rulename, data) {
                    if (rulename !== "messages" && unobtrusiveValidation.options.rules[elname][rulename] === undefined) {
                        delete validator.settings.rules[elname][rulename];
                    }
                });
            }
        });
    }        
};

$.validator.unobtrusive.unparseContent = function (selector) {
    var $selector = $(selector);

    // if its  a text node, then exit
    if ($selector && $selector.length > 0 && $selector[0].nodeType === 3) {
        return;
    }

    var $form = $selector.first().closest('form'), 
        unobtrusiveValidation = $form.data('unobtrusiveValidation');

    $selector.find(":input[data-val=true]").each(function () {
        removeValidation($(this), unobtrusiveValidation);
    });
    if ($selector.attr('data-val') === 'true') {
        removeValidation($selector, unobtrusiveValidation);
    }
    $.validator.unobtrusive.syncValdators($form);
};

function removeValidation($element, unobtrusiveValidation) {
    var elname = $element.attr('name');
    if (elname !== undefined) {
        $element.rules('remove');
        if (unobtrusiveValidation) {
            if (unobtrusiveValidation.options.rules[elname]) {
                delete unobtrusiveValidation.options.rules[elname];
            }
            if (unobtrusiveValidation.options.messages[elname]) {
                delete unobtrusiveValidation.options.messages[elname];
            }
        }
    }
}

โดยพื้นฐานแล้วมันยังคงใช้งานได้เหมือนกับโซลูชันของ Xhalent ด้านบน แต่ฉันได้เพิ่มความสามารถในการลบกฎสำหรับองค์ประกอบที่คุณลบออกจากโดม ดังนั้นเมื่อคุณลบองค์ประกอบออกจาก Dom และคุณต้องการให้กฎการตรวจสอบเหล่านั้นถูกลบออกด้วยให้เรียก:

$.validator.unobtrusive.unparseContent('input.something');

2

ฉันลองใช้คำตอบของ viggity และตอนแรกทุกอย่างดูเหมือนจะใช้ได้ผล แต่หลังจากนั้นไม่นานฉันสังเกตว่าการตรวจสอบความถูกต้องจะช้าลงอย่างเจ็บปวดเมื่อฉันเพิ่มรายการแบบไดนามิกมากขึ้น เหตุผลก็คือการแก้ปัญหาของเขาไม่ได้เลิกผูกตัวจัดการเหตุการณ์ แต่จะเพิ่มตัวจัดการเหตุการณ์ใหม่ทุกครั้ง ดังนั้นหากคุณเพิ่ม 5 รายการการตรวจสอบความถูกต้องจะดำเนินการ 6 ครั้งแทนที่จะเป็นเพียงครั้งเดียว ในการแก้ไขปัญหานี้คุณต้องเลิกผูกเหตุการณ์เพิ่มเติมจากการเรียก removeData

$("form").removeData("validator")
         .removeData("unobtrusiveValidation")
         .off("submit.validate click.validate focusin.validate focusout.validate keyup.validate invalid-form.validate");
$.validator.unobtrusive.parse("form");

1

ฉันพบสคริปต์รหัสของ @ Xhalent ในโค้ดของฉันและกำลังจะลบออกเพราะฉันไม่ได้ใช้มันทำให้ฉันไปสู่คำถาม SO นี้

รหัสนี้ค่อนข้างสะอาดและเรียบง่าย:

jQuery.fn.unobtrusiveValidationForceBind = function () {
    //If you try to parse a form that is already parsed it won't update
    var $form = this
       .removeData("validator") /* added by the raw jquery.validate plugin */
            .removeData("unobtrusiveValidation");  /* added by the jquery     unobtrusive plugin */

    $form.bindUnobtrusiveValidation();
}

จากนั้นหากต้องการเรียกส่วนขยาย jQuery นี้เพียงใช้ตัวเลือกเพื่อดึงแบบฟอร์มของคุณ:

$('#formStart').unobtrusiveValidationForceBind();

วิโอล่า!


1

ในกรณีของเนื้อหาไดนามิกคุณต้องอัปเดตการตรวจสอบที่ไม่สร้างความรำคาญดังต่อไปนี้และตรวจสอบว่าFormถูกต้องขณะส่งหรือไม่

function UpdateUnobtrusiveValidations(idForm) {
    $(idForm).removeData("validator").removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse($(idForm));
};


$('#idDivPage').on('click', '#idSave', function (e) {
    e.preventDefault();
    if (!$('#idForm').valid()) {
        // Form is invalid … so return
        return false;
    }
    else {
        // post data to server using ajax call
        // update Unobtrusive Validations again
        UpdateUnobtrusiveValidations('#idForm');
    }
});

0

ฉันเล่นซอกับเรื่องนี้มาระยะหนึ่งแล้วทิ้งวิธีแก้ปัญหาและลองอีกครั้งในภายหลัง (เมื่อฉันมีเวลาว่างเชื่อหรือไม่)

ฉันไม่แน่ใจว่าพฤติกรรมนี้จะเปลี่ยนไปใน jquery เวอร์ชันใหม่กว่าหรือไม่ (เราใช้ 1.7.2) เนื่องจากเธรดนี้ถูกสร้างขึ้นหรือแสดงความคิดเห็นครั้งสุดท้าย แต่ฉันพบว่า.parseElement(inputElement)ทำงานได้ดีเมื่อฉันพยายามเพิ่มองค์ประกอบที่สร้างแบบไดนามิกลงในฟอร์ม ที่โหลดโปรแกรมตรวจสอบความถูกต้องแล้ว สิ่งนี้ได้รับการแนะนำโดย @jamesfm (15 ก.พ. 54) ในหนึ่งในความคิดเห็นด้านบน แต่ฉันมองข้ามไปสองสามครั้งแรกที่ฉันทำสิ่งนี้ ดังนั้นฉันจึงเพิ่มเป็นคำตอบแยกต่างหากเพื่อให้ชัดเจนยิ่งขึ้นและเพราะฉันคิดว่ามันเป็นทางออกที่ดีและไม่ต้องใช้ค่าใช้จ่ายมากนัก อาจไม่เกี่ยวข้องกับปัญหาทั้งหมดที่เกิดขึ้นในคำตอบที่ตามมา แต่ฉันคิดว่ามันน่าจะเป็นวิธีแก้ปัญหาสำหรับคำถามเดิม นี่คือวิธีการทำงานของฉัน:

//row & textarea created dynamically by an async ajax call further up in the code
var row = ...; //row reference from somewhere
var textarea = row.find("textarea");
textarea.val("[someValue]");

//add max length rule to the text area
textarea.rules('add', {
    maxlength: 2000
});
//parse the element to enable the validation on the dynamically added element
$.validator.unobtrusive.parseElement(textarea);

0

ประการแรกฉันคิดว่าการโทรควรเป็น. validator ไม่ใช่ตรวจสอบความถูกต้องคุณต้องส่งรหัสของแบบฟอร์ม

$.validator.unobtrusive.parse("#id");

ฉันคิดว่าคุณได้โหลดทั้ง jquery.validate & jquery.validate.unobtrusive scripts และเรียกว่า Html.EnableClientValidation () และ Html.EnableUnobtrusiveJavaScript () method? คุณสามารถโพสต์ตัวอย่างโค้ดสำหรับเพจฐานของคุณและฟอร์มที่โหลดแบบไดนามิกได้หรือไม่?
Chris Allmark

0

หากคุณต้องการเพิ่มและลบสิ่งต่างๆที่มีความเป็นไปได้ที่จะมีข้อผิดพลาดบางอย่างปรากฏขึ้นแล้วนี่คือสิ่งที่ฉันมาพร้อมกับ ขึ้นอยู่กับแนวคิดที่แตกต่างกันเป็นหลักในหน้าคำถามนี้ ฉันใช้destroy()บิวท์อินแทนที่จะลบแอตทริบิวต์ข้อมูลเพื่อตรวจสอบ JQuery

function resetValidator($form: JQuery) {
    $form.validate().destroy();

    //reset unobtrusive validation summary, if it exists
    $form.find("[data-valmsg-summary=true]")
        .removeClass("validation-summary-errors")
        .addClass("validation-summary-valid")
        .find("ul").empty();

    //reset unobtrusive field level, if it exists
    $form.find("[data-valmsg-replace]")
        .removeClass("field-validation-error")
        .addClass("field-validation-valid")
        .empty();

    $form.removeData("unobtrusiveValidation");
}

คุณเรียกมันก่อนที่จะปรับเปลี่ยนอินพุตในฟอร์มแบบไดนามิก จากนั้นคุณเริ่มต้นการตรวจสอบความถูกต้องอีกครั้งหลังจากนั้น

resetValidator($form);
//add or remove inputs here ...
$.validator.unobtrusive.parse($form);

หมายเหตุ: หากอินพุตบางส่วนหรือทั้งหมดได้รับการตรวจสอบและมีข้อผิดพลาดข้อผิดพลาดเหล่านั้นจะถูกรีเซ็ต ... แต่จะกลับมาอย่างถูกต้องในการตรวจสอบความถูกต้องครั้งถัดไป

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.