test ajax request

This commit is contained in:
ilmedova 2022-11-22 19:29:24 +05:00
parent 6040bf6dbd
commit e5cb405012
5 changed files with 273 additions and 13 deletions

View File

@ -115,4 +115,19 @@ public function createAppTicket(Request $request){
return redirect()->route('chat',['ticket_id' => $ticket->id]);
}
public function accountForTicketsAjax(Request $request){
$search_term = $request->input('q');
if ($search_term)
{
$results = Account::where('name', 'LIKE', '%'.$search_term.'%')->paginate(10);
}
else
{
$results = Account::paginate(10);
}
return $results;
}
}

View File

@ -115,23 +115,22 @@ protected function setupCreateOperation()
// 'attribute_2' => 'surname',
// ],
[
'name' => 'client_id',
'type' => 'relationship',
'label' => 'Account',
// OPTIONALS:
'attribute' => "name", // foreign key attribute that is shown to user (identifiable attribute)
'label' => trans('app.ticket.account'), // Table column heading
'type' => "select2_from_ajax",
'name' => 'client_id', // the column that contains the ID of that connected entity
'entity' => 'account', // the method that defines the relationship in your Model
'model' => "App\Models\Account", // foreign key Eloquent model
'placeholder' => "Select account", // placeholder for the select2 input
'attribute' => "name", // foreign key attribute that is shown to user
'data_source' => backpack_url('account/fetch'),
// AJAX OPTIONALS:
'delay' => 500, // the minimum amount of time between ajax requests when searching in the field
'data_source' => url("fetch/account"), // url to controller search function (with /{id} should return model)
// OPTIONAL
// 'delay' => 500, // the minimum amount of time between ajax requests when searching in the field
'placeholder' => "Select a client", // placeholder for the select
'minimum_input_length' => 2, // minimum characters to type before querying results
'dependencies' => ['account'], // when a dependency changes, this select2 is reset to null
'model' => "App\Models\Account", // foreign key model
// 'dependencies' => ['category'], // when a dependency changes, this select2 is reset to null
'method' => 'POST', // optional - HTTP method to use for the AJAX call (GET, POST)
'include_all_form_fields' => false, // optional - only send the current field through AJAX (for a smaller payload if you're not using multiple chained select2s)
// 'include_all_form_fields' => false, // optional - only send the current field through AJAX (for a smaller payload if you're not using multiple chained select2s)
],
[
'name' => 'category_id',

View File

@ -38,4 +38,5 @@ public function export($id){
return \Response::make($content,200, $headers);
}
}

View File

@ -0,0 +1,244 @@
<!-- select2 from ajax -->
@php
$connected_entity = new $field['model'];
$connected_entity_key_name = $connected_entity->getKeyName();
$old_value = old(square_brackets_to_dots($field['name'])) ?? $field['value'] ?? $field['default'] ?? false;
// by default set ajax query delay to 500ms
// this is the time we wait before send the query to the search endpoint, after the user as stopped typing.
$field['delay'] = $field['delay'] ?? 500;
$field['allows_null'] = $field['allows_null'] ?? $crud->model::isColumnNullable($field['name']);
@endphp
@include('crud::fields.inc.wrapper_start')
<label>{!! $field['label'] !!}</label>
<select
name="{{ $field['name'] }}"
style="width: 100%"
data-init-function="bpFieldInitSelect2FromAjaxElement"
data-field-is-inline="{{var_export($inlineCreate ?? false)}}"
data-column-nullable="{{ var_export($field['allows_null']) }}"
data-dependencies="{{ isset($field['dependencies'])?json_encode(Arr::wrap($field['dependencies'])): json_encode([]) }}"
data-placeholder="{{ $field['placeholder'] }}"
data-minimum-input-length="{{ $field['minimum_input_length'] }}"
data-data-source="{{ $field['data_source'] }}"
data-method="{{ $field['method'] ?? 'GET' }}"
data-field-attribute="{{ $field['attribute'] }}"
data-connected-entity-key-name="{{ $connected_entity_key_name }}"
data-include-all-form-fields="{{ isset($field['include_all_form_fields']) ? ($field['include_all_form_fields'] ? 'true' : 'false') : 'false' }}"
data-ajax-delay="{{ $field['delay'] }}"
data-language="{{ str_replace('_', '-', app()->getLocale()) }}"
@include('crud::fields.inc.attributes', ['default_class' => 'form-control'])
>
@if ($old_value)
@php
if(!is_object($old_value)) {
$item = $connected_entity->find($old_value);
}else{
$item = $old_value;
}
@endphp
@if ($item)
{{-- allow clear --}}
@if ($field['allows_null']))
<option value="" selected>
{{ $field['placeholder'] }}
</option>
@endif
<option value="{{ $item->getKey() }}" selected>
{{ $item->{$field['attribute']} }}
</option>
@endif
@endif
</select>
{{-- HINT --}}
@if (isset($field['hint']))
<p class="help-block">{!! $field['hint'] !!}</p>
@endif
@include('crud::fields.inc.wrapper_end')
{{-- ########################################## --}}
{{-- Extra CSS and JS for this particular field --}}
{{-- If a field type is shown multiple times on a form, the CSS and JS will only be loaded once --}}
@if ($crud->fieldTypeNotLoaded($field))
@php
$crud->markFieldTypeAsLoaded($field);
@endphp
{{-- FIELD CSS - will be loaded in the after_styles section --}}
@push('crud_fields_styles')
<!-- include select2 css-->
<link href="{{ asset('packages/select2/dist/css/select2.min.css') }}" rel="stylesheet" type="text/css" />
<link href="{{ asset('packages/select2-bootstrap-theme/dist/select2-bootstrap.min.css') }}" rel="stylesheet" type="text/css" />
{{-- allow clear --}}
@if ($field['allows_null'])
<style type="text/css">
.select2-selection__clear::after {
content: ' {{ trans('backpack::crud.clear') }}';
}
</style>
@endif
@endpush
{{-- FIELD JS - will be loaded in the after_scripts section --}}
@push('crud_fields_scripts')
<!-- include select2 js-->
<script src="{{ asset('packages/select2/dist/js/select2.full.min.js') }}"></script>
@if (app()->getLocale() !== 'en')
<script src="{{ asset('packages/select2/dist/js/i18n/' . str_replace('_', '-', app()->getLocale()) . '.js') }}"></script>
@endif
@endpush
@endif
<!-- include field specific select2 js-->
@push('crud_fields_scripts')
<script>
function bpFieldInitSelect2FromAjaxElement(element) {
var form = element.closest('form');
var $placeholder = element.attr('data-placeholder');
var $minimumInputLength = element.attr('data-minimum-input-length');
var $dataSource = element.attr('data-data-source');
var $method = element.attr('data-method');
var $fieldAttribute = element.attr('data-field-attribute');
var $connectedEntityKeyName = element.attr('data-connected-entity-key-name');
var $includeAllFormFields = element.attr('data-include-all-form-fields')=='false' ? false : true;
var $allowClear = element.attr('data-column-nullable') == 'true' ? true : false;
var $dependencies = JSON.parse(element.attr('data-dependencies'));
var $ajaxDelay = element.attr('data-ajax-delay');
var $selectedOptions = typeof element.attr('data-selected-options') === 'string' ? JSON.parse(element.attr('data-selected-options')) : JSON.parse(null);
var $isFieldInline = element.data('field-is-inline');
var select2AjaxFetchSelectedEntry = function (element) {
return new Promise(function (resolve, reject) {
$.ajax({
url: $dataSource,
data: {
'keys': $selectedOptions
},
type: $method,
success: function (result) {
resolve(result);
},
error: function (result) {
reject(result);
}
});
});
};
// do not initialise select2s that have already been initialised
if ($(element).hasClass("select2-hidden-accessible"))
{
return;
}
//init the element
$(element).select2({
theme: 'bootstrap',
multiple: false,
placeholder: $placeholder,
minimumInputLength: $minimumInputLength,
allowClear: $allowClear,
dropdownParent: $isFieldInline ? $('#inline-create-dialog .modal-content') : document.body,
ajax: {
url: $dataSource,
type: $method,
dataType: 'json',
delay: $ajaxDelay,
data: function (params) {
if ($includeAllFormFields) {
return {
q: params.term, // search term
page: params.page, // pagination
form: form.serializeArray() // all other form inputs
};
} else {
return {
q: params.term, // search term
page: params.page, // pagination
};
}
},
processResults: function (data, params) {
params.page = params.page || 1;
var result = {
results: $.map(data.data, function (item) {
textField = $fieldAttribute;
return {
text: item[textField],
id: item[$connectedEntityKeyName]
}
}),
pagination: {
more: data.current_page < data.last_page
}
};
return result;
},
cache: true
},
});
// if we have selected options here we are on a repeatable field, we need to fetch the options with the keys
// we have stored from the field and append those options in the select.
if (typeof $selectedOptions !== typeof undefined &&
$selectedOptions !== false &&
$selectedOptions != '' &&
$selectedOptions != null &&
$selectedOptions != [])
{
var optionsForSelect = [];
select2AjaxFetchSelectedEntry(element).then(function(result) {
result.forEach(function(item) {
$itemText = item[$fieldAttribute];
$itemValue = item[$connectedEntityKeyName];
//add current key to be selected later.
optionsForSelect.push($itemValue);
//create the option in the select
$(element).append('<option value="'+$itemValue+'">'+$itemText+'</option>');
});
// set the option keys as selected.
$(element).val(optionsForSelect);
});
}
// if any dependencies have been declared
// when one of those dependencies changes value
// reset the select2 value
for (var i=0; i < $dependencies.length; i++) {
var $dependency = $dependencies[i];
//if element does not have a custom-selector attribute we use the name attribute
if(typeof element.attr('data-custom-selector') == 'undefined') {
form.find('[name="'+$dependency+'"], [name="'+$dependency+'[]"]').change(function(el) {
$(element.find('option:not([value=""])')).remove();
element.val(null).trigger("change");
});
}else{
// we get the row number and custom selector from where element is called
let rowNumber = element.attr('data-row-number');
let selector = element.attr('data-custom-selector');
// replace in the custom selector string the corresponding row and dependency name to match
selector = selector
.replaceAll('%DEPENDENCY%', $dependency)
.replaceAll('%ROW%', rowNumber);
$(selector).change(function (el) {
$(element.find('option:not([value=""])')).remove();
element.val(null).trigger("change");
});
}
}
}
</script>
@endpush
{{-- End of Extra CSS and JS --}}
{{-- ########################################## --}}

View File

@ -51,6 +51,7 @@
Route::get('application/accept/{id}', [ApplicationCrudController::class, 'accept'])->name('accepted_application');
Route::post('application/refine/{id}', [ApplicationCrudController::class, 'refine'])->name('refine_application');
Route::post('application/approve/{id}', [ApplicationCrudController::class, 'approveApplication'])->name('approve_application');
Route::post('account/fetch', [TicketController::class, 'accountForTicketsAjax']);
Route::crud('department', 'DepartmentCrudController');
Route::crud('resolution', 'ResolutionCrudController');
Route::crud('resolutionbasis', 'ResolutionbasisCrudController');