【问题标题】:jQuery Validation: rules do not apply to elements created dynamically from jsonjQuery 验证:规则不适用于从 json 动态创建的元素
【发布时间】:2020-09-21 02:42:32
【问题描述】:

在我的 Laravel 应用程序中,我有一个可能包含动态字段的表单。在“添加联系人”按钮上,单击从模板中添加的字段组。必须验证某些字段,因此我使用.rules() 方法为每个字段动态添加了规则。当我创建一个新实体时,这些动态字段应该是它的一部分,对我来说工作正常:

当我编辑实体时,我会根据从控制器获得的 json 字符串创建这些字段组。创建了具有值的字段,但由于某种原因,这些规则不适用于这些动态创建的字段。当我尝试将规则应用于此类字段时,出现错误:

Uncaught TypeError: Cannot read property 'settings' of undefined

我发现当我向动态字段添加规则时会发生这种情况:

let firstName = $('#first-name-' + elementNumber);
let jobTitle = $('#job-title-' + elementNumber);
let contactEmail = $('#contact-email-' + elementNumber);

firstName.rules("add", {
    required: true
});

jobTitle.rules("add", {
    required: true
});

contactEmail.rules("add", {
    required: true,
    email: true
});

我的代码:

let buildingForm = $('#building_form');
let addContactButton = $('#add_contact');
let contactsContainer = $('#contacts_container');
var elementNumber = 1;

let model = "{{ $model->building_id ?? '' }}"

if (model) {
    let buildingContacts = '{!! $buildingContacts ?? "" !!}'

    if (buildingContacts) {
        buildingContacts = JSON.parse(buildingContacts)

        $.each(buildingContacts, function (index, value) {
            addContact(value)
            elementNumber++
        });
    }
}

addContactButton.on('click', function () {
    addContact()
    elementNumber++
});

buildingForm.validate({
    ignore: ""
});

function addContact(value = null) {
    let contactLayout = getContactLayout(elementNumber, value);
    contactsContainer.prepend(contactLayout);

    let firstName = $('#first-name-' + elementNumber);
    let jobTitle = $('#job-title-' + elementNumber);
    let contactEmail = $('#contact-email-' + elementNumber);

    firstName.rules("add", {
        required: true
    });

    jobTitle.rules("add", {
        required: true
    });

    contactEmail.rules("add", {
        required: true,
        email: true
    });

    $('#delete-contact-button-' + elementNumber).on('click', function (e) {
        $.confirm({
            title: 'Confirm action',
            content: 'Are you sure you want to delete Contact?',
            buttons: {
                confirm: function () {
                    deleteContact(e.target.id);
                },
                cancel: function () {
                    $.alert('Canceled');
                },
            }
        });
    });
}

function deleteContact(buttonId) {
    let buttonOneContactContainer = $('#' + buttonId).closest('div.one-contact-container');
    buttonOneContactContainer.remove();

}

function getContactLayout(elementNumber, value = null) {
    return `
        <div class="p-t-10 p-b-10 p-l-10 p-r-10 m-t-10 border one-contact-container" id="one-contact-container-${elementNumber}">
            <div class="row">
                <div class="col-sm-6">
                    <div class="form-group row">
                        <label for="first-name-${elementNumber}" class="col-md-4 label-right">First Name <span class="required">*</span></label>
                        <div class="col-md-8">
                            <input name="contacts[first_name][${elementNumber}]" id="first-name-${elementNumber}" type="text" value="${value ? value.first_name : ''}" class="form-control first-name-input">
                        </div>
                    </div>
                </div>
                <div class="col-sm-6">
                    <div class="form-group row">
                        <label for="last-name-${elementNumber}" class="col-md-4 label-right">Last Name</label>
                        <div class="col-md-8">
                            <input name="contacts[last_name][${elementNumber}]" id="last-name-${elementNumber}" type="text" value="${value ? value.last_name : ''}" class="form-control">
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-6">
                    <div class="form-group row">
                        <label for="job-title-${elementNumber}" class="col-md-4 label-right">Job Title <span class="required">*</span></label>
                        <div class="col-md-8">
                            <input name="contacts[job_title][${elementNumber}]" id="job-title-${elementNumber}" type="text" value="${value ? value.job_title : ''}" class="form-control job-title-input">
                        </div>
                    </div>
                </div>
                <div class="col-sm-6">
                    <div class="form-group row">
                        <label for="contact-email-${elementNumber}" class="col-md-4 label-right">Email <span class="required">*</span></label>
                        <div class="col-md-8">
                            <input name="contacts[contact_email][${elementNumber}]" id="contact-email-${elementNumber}" type="text" value="${value ? value.email : ''}" class="form-control email-input">
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-6">
                    <div class="form-group row">
                        <label for="office-phone-${elementNumber}" class="col-md-4 label-right">Office Phone</label>
                        <div class="col-md-8">
                            <input name="contacts[office_phone][${elementNumber}]" id="office-phone-${elementNumber}" type="text" value="${value ? value.office_phone : ''}" class="form-control">
                        </div>
                    </div>
                </div>
                <div class="col-sm-6">
                    <div class="form-group row">
                        <label for="mobile-phone-${elementNumber}" class="col-md-4 label-right">Mobile Phone</label>
                        <div class="col-md-8">
                            <input name="contacts[mobile_phone][${elementNumber}]" id="mobile-phone-${elementNumber}" type="text" value="${value ? value.mobile_phone : ''}" class="form-control">
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-12">
                    <div class="form-group row">
                        <label for="contact-notes-${elementNumber}" class="col-md-2 label-right">Notes</label>
                        <div class="col-md-10">
                            <textarea name="contacts[contact_notes][${elementNumber}]" id="contact-notes-${elementNumber}" class="form-control">${value ? value.notes : ''}</textarea>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-12 test-right">
                    <span class="btn-danger btn pull-right delete-contact" id="delete-contact-button-${elementNumber}">Delete contact</span>
                </div>
            </div>
        </div>
    `;
}

因此,创建新字段并从 json 字符串生成现有字段具有相同的功能。

JSON 示例:

[{
    "building_contact_id": 781,
    "building_id": 76516,
    "job_title": "Officer",
    "first_name": "John",
    "last_name": "",
    "mobile_phone": "",
    "office_phone": "",
    "email": "john.doe@mail.com",
    "notes": "",
    "created_at": "2020-06-02T13:42:32.000000Z",
    "updated_at": "2020-06-02T13:42:32.000000Z"
}]

【问题讨论】:

  • firstName = $('#first-name-' + elementNumber) 不是“动态”变量 - 它获取当时存在的匹配元素。所以firstName.rules 将只适用于它运行时存在的元素。

标签: jquery laravel jquery-validate


【解决方案1】:

需要在超时中包裹:

setTimeout(function () {
    if (firstName.length) {
        firstName.rules("add", {
            required: true
        });
    }

    if (jobTitle.length) {
        jobTitle.rules("add", {
            required: true
        });
    }

    if (contactEmail.length) {
        contactEmail.rules("add", {
            required: true
        });
    }
}, 100)

【讨论】:

  • 使用一个回调函数,而不是赌注在及时完成的​​事情上的计时器,它可以保证函数在继续之前完成。见:stackoverflow.com/a/21518470/594235
  • 条件似乎完全没有意义......if (firstName.length){...} 如果这个条件失败,你仍然处于同样的情况,这些字段没有规则。
猜你喜欢
  • 2016-09-20
  • 2015-12-18
  • 1970-01-01
  • 2015-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多