In my Laravel App I have a form that may contain dynamic fields. On "Add Contact" button click group of fields is added from template. Some of the fields have to be validated so I added rules dynamically for each of this fields with .rules()
method. When I create a new entity that these dynamic fields should be part of it`s working fine for me:
When I edit an entity, I create these field groups from the json string that I get from the controller. Fields with values are created, but for some reason, the rules do not apply to these dynamically created fields. When I try to apply a rule to such a field, I get an error:
Uncaught TypeError: Cannot read property 'settings' of undefined
I found out that this happens when I add rules to dynamic fields:
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
});
My code:
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>
`;
}
So, creating new fields and generating existing ones from json strings fulfills the same function.
JSON example:
[{
"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"
}]