File: /var/www/ivs.kaunokolegija.lt/laravel/resources/views/components/form/select2-with-modal.blade.php
<div class="form-group">
@if ($label)
<label {{ $required ? 'class=required' : '' }} for="{{ $name }}">{{ $label }}</label>
@endif
<div class="d-flex align-items-center">
<select
class="form-control select2 {{ $errors->has($name) ? 'is-invalid' : '' }}"
name="{{ $name }}"
id="{{ $name }}"
{{ $required ? 'required' : '' }}
{{ $disabled ? 'disabled' : '' }}
{{ $attributes }}
>
@foreach ($options as $id => $entry)
<option value="{{ $id }}" {{ (string) $id === (string) old($name, $value) ? 'selected' : '' }}>
{{ $entry }}
</option>
@endforeach
</select>
<button type="button" class="btn btn-outline-primary ms-2" data-bs-toggle="modal" data-bs-target="#{{ $modalId }}">
<i class="fa fa-plus"></i>
</button>
</div>
@if ($errors->has($name))
<div class="invalid-feedback">
{{ $errors->first($name) }}
</div>
@endif
@if ($helpLabel)
<span class="help-block">{{ $helpLabel }}</span>
@endif
</div>
{{-- Include the slot for modal --}}
{{ $slot }}
{{-- Include JavaScript for handling form submission --}}
<script>
document.addEventListener("DOMContentLoaded", () => {
const modalId = "{{ $modalId }}"; // Dynamically set modal ID
const actionUrl = '{{ $modalAction }}'; // Action URL for the modal form
const selectElement = document.querySelector("#{{ $name }}"); // Select element
// Find the modal save button
const saveButton = document.querySelector(`#${modalId}SaveBtn`);
// Prevent duplicate submissions by setting a flag
let isSubmitting = false;
// Handle the second modal's Save button click event
saveButton.addEventListener("click", (event) => {
// Prevent multiple submissions by checking the flag
if (isSubmitting) return;
isSubmitting = true;
// Dynamically find all input elements within the modal
const modalElement = document.getElementById(modalId);
const formData = new FormData();
// Collect all input fields inside the modal
modalElement.querySelectorAll("input, textarea").forEach(input => {
const name = input.name;
const value = input.value.trim();
// Only append fields that have values
if (name && value !== "") {
formData.append(name, value);
}
});
// Check if there's at least one required value
if (!formData.has("name") || formData.get("name").trim() === "") {
alert("Please enter a name.");
isSubmitting = false;
return;
}
// Append CSRF token to formData
formData.append("_token", document.querySelector("meta[name='csrf-token']").content);
// Send the AJAX request
fetch(actionUrl, {
method: "POST",
headers: {
"X-Requested-With": "XMLHttpRequest",
},
body: formData,
})
.then((response) => response.text())
.then((data) => {
try {
const jsonData = JSON.parse(data);
if (jsonData.success) {
// Add the new option to the select2 dropdown
const option = new Option(jsonData.text, jsonData.id, true, true);
$(selectElement).append(option).trigger('change');
$('#' + modalId).modal('hide'); // Hide the modal
} else {
alert("Error: " + jsonData.message);
}
} catch (error) {
console.error("Error parsing JSON:", error);
alert("The response is not valid JSON.");
}
// Reset the flag after request completion
isSubmitting = false;
})
.catch((error) => {
console.error("Error:", error);
alert("An error occurred while saving the new option.");
isSubmitting = false; // Reset flag on error
});
});
function toggleModalFields() {
const modalElement = document.getElementById(modalId);
const modalInputs = modalElement.querySelectorAll("input, textarea");
// If modal is open, enable the inputs
if (modalElement.classList.contains("show")) {
modalInputs.forEach(input => input.removeAttribute("disabled"));
} else {
// If modal is closed, disable the inputs
modalInputs.forEach(input => input.setAttribute("disabled", "true"));
}
}
// Add event listeners for when the modal is shown or hidden
const modal = document.getElementById(modalId);
modal.addEventListener('shown.bs.modal', toggleModalFields);
modal.addEventListener('hidden.bs.modal', toggleModalFields);
// Initially disable the inputs in the modal
toggleModalFields();
});
</script>
{{--
public function __construct(
$name,
$options = [],
$selected = null,
$modalName = null,
$modalLabel = null,
$modalRoute = null,
$modalButton = true
) {
$this->name = $name;
$this->options = $options;
$this->selected = $selected;
$this->modalName = $modalName;
$this->modalLabel = $modalLabel;
$this->modalRoute = $modalRoute;
$this->modalButton = $modalButton;
}
<div class="d-flex align-items-center">
<select class="form-control select2 {{ $errors->has($name) ? 'is-invalid' : '' }}" name="{{ $name }}" id="{{ $name }}" required>
@foreach ($options as $id => $label)
<option value="{{ $id }}" {{ $selected == $id ? 'selected' : '' }}>{{ $label }}</option>
@endforeach
</select>
@if ($modalName)
<x-modal.create-name-modal
compName="{{ $modalName }}"
title="{{ trans('global.add') }}"
name="name"
label="{{ $modalLabel }}"
route="{{ $modalRoute }}"
/>
@endif
@if ($modalButton)
<button type="button" data-select-id="{{ $name }}" class="btn btn-outline-primary ms-2" id="open{{ $modalName }}Modal">
<i class="fa fa-plus"></i>
</button>
@endif
@if ($errors->has($name))
<span class="text-danger">{{ $errors->first($name) }}</span>
@endif
<span class="help-block">{{ trans("cruds.{$name}.fields.{$name}_helper") }}</span>
</div>
//usage:
<x-select-with-modal
name="state_id"
:options="$states"
:selected="old('state_id')"
modalName="CoopAgreementType"
modalLabel="{{ trans('cruds.coopAgreementType.fields.name') }}"
modalRoute="{{ route('admin.coop-agreement-types.store') }}"
modalButton="true"
/> --}}