-
Notifications
You must be signed in to change notification settings - Fork 920
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ajax for select2 #166
Comments
Hi @maesklaas This is a pretty good idea! We've actually had to do something like this in the past as well, I'm not sure if its possible currently with the select2 fields, however if you're in urgent need of the feature, you can always copy the existing |
I did give it a try and it seams to work quit nice! Probably there are still some improvements possible. One thing that isn't working yet is when i have multiple of these ajax selects it just uses the first one. At the moment only that one will be inserted. I can get it out of the By the way an underscore in the blade file of the custom field is not working. My code is below for anyone who can use it. Controller functions public function getCities()
{
$q = Input::get("q");
$cities = \App\Models\City::where('name', 'like', '%'.$q.'%')->paginate();
return \Response::json($cities);
}
public function getCity($id)
{
$city = \App\Models\City::findOrFail($id);
return \Response::json($city);
} field init $this->crud->addField([
// 1-n relationship
'label' => "End", // Table column heading
'type' => "select2Ajax",
'name' => 'city_id', // the column that contains the ID of that connected entity;
'entity' => 'city', // the method that defines the relationship in your Model
'attribute' => "name", // foreign key attribute that is shown to user
'model' => "App\Models\City", // foreign key model
'datasource' => url("api/cities"), // url to controller search function (with /{id} should return model)
'placeholder' => "Select a city", // placeholder for the select
'minimumInputLength' => 2, // minimum characters to type before querying results
]); select2Ajax.blade.php <!-- select2 Ajax -->
<div @include('crud::inc.field_wrapper_attributes') >
<label>{!! $field['label'] !!}</label>
<?php $entity_model = $crud->model; ?>
<input type="hidden"
name="{{ $field['name'] }}" value="{{ $field['value'] }}"
@include('crud::inc.field_attributes', ['default_class' => 'form-control select2Ajax'])
>
{{-- HINT --}}
@if (isset($field['hint']))
<p class="help-block">{!! $field['hint'] !!}</p>
@endif
</div>
{{-- ########################################## --}}
{{-- 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->checkIfFieldIsFirstOfItsType($field, $fields))
{{-- FIELD CSS - will be loaded in the after_styles section --}}
@push('crud_fields_styles')
<!-- include select2 css-->
<link href="{{ asset('vendor/backpack/select2/select2.css') }}" rel="stylesheet" type="text/css" />
<link href="{{ asset('vendor/backpack/select2/select2-bootstrap-dick.css') }}" rel="stylesheet" type="text/css" />
@endpush
{{-- FIELD JS - will be loaded in the after_scripts section --}}
@push('crud_fields_scripts')
<!-- include select2 js-->
<script src="{{ asset('vendor/backpack/select2/select2.js') }}"></script>
<script>
jQuery(document).ready(function($) {
// trigger select2 for each untriggered select2 box
$('.select2Ajax').each(function (i, obj) {
if (!$(obj).data("select2"))
{
$(obj).select2({
placeholder: "{{ $field['placeholder'] }}",
minimumInputLength: "{{ $field['minimumInputLength'] }}",
ajax: {
url: "{{ $field['datasource'] }}",
dataType: 'json',
quietMillis: 250,
data: function (term, page) {
return {
q: term, // search term
page: page
};
},
results: function (data, params) {
params.page = params.page || 1;
return {
results: $.map(data.data, function (item) {
textField = "{{$field['attribute']}}";
return {
text: item[textField],
id: item["id"]
}
}),
more: data.current_page < data.last_page
};
},
cache: true
},
initSelection: function(element, callback) {
// the input tag has a value attribute preloaded that points to a preselected repository's id
// this function resolves that id attribute to an object that select2 can render
// using its formatResult renderer - that way the repository name is shown preselected
if ("{{ $field['value'] }}" !== "") {
$.ajax("{{ $field['datasource'] }}" + '/' + "{{$field['value']}}", {
dataType: "json"
}).done(function(data) {
textField = "{{$field['attribute']}}";
callback({ text: data[textField], id: data["id"] });
});
}
},
});
}
});
});
</script>
@endpush
@endif
{{-- End of Extra CSS and JS --}}
{{-- ########################################## --}} |
Hi @maesklaas , OMG - this is exactly what I was going to suggest! I do think it's the best way to achieve this and it would be a useful addition. Especially since we now have AJAX datatables - tables with millions of entries are a possibility.
$this->crud->addField([ // 1-n relationship with AJAX
'label' => "End", // Table column heading
- 'type' => "select2Ajax",
+ 'type' => "select2_multiple_ajax", // or maybe select2_ajax_multiple would be better?
'name' => 'city_id', // the column that contains the ID of that connected entity;
'entity' => 'city', // the method that defines the relationship in your Model
'attribute' => "name", // foreign key attribute that is shown to user
'model' => "App\Models\City", // foreign key model
'datasource' => url("api/cities"), // url to controller search function (with /{id} should return model)
'placeholder' => "Select a city", // placeholder for the select
'minimumInputLength' => 2, // minimum characters to type before querying results
+ 'pivot' => true,
]); and in the
$this->crud->addField([
// 1-n relationship
'label' => "End", // Table column heading
- 'type' => "select2Ajax",
+ 'type' => "select2_ajax",
'name' => 'city_id', // the column that contains the ID of that connected entity;
'entity' => 'city', // the method that defines the relationship in your Model
'attribute' => "name", // foreign key attribute that is shown to user
'model' => "App\Models\City", // foreign key model
- 'datasource' => url("api/cities"), // url to controller search function (with /{id} should return model)
+ 'data_source' => url("api/cities"), // url to controller search function (with /{id} should return model)
'placeholder' => "Select a city", // placeholder for the select
- 'minimumInputLength' => 2, // minimum characters to type before querying results
+ 'minimum_input_length' => 2, // minimum characters to type before querying results
]);
That being said - thank you for this. I really think it's a useful new feature. Cheers |
Hi @tabacitu Great that you like my try. I had an error when i used the select2_ajax name, but i just retried that and it fine now. So i will make a pull request somewhere next week. And i will add the multiple version as well, select2_ajax_multiple seems to be the best fit i believe. I agree with the name changes in 5. I am actually using the getCity request as well in the ajax call in the initSelection where i use the route api/cities/{id} to get the current model for the edit. Maybe i should create an other property in the field definition such that the route doesn't have to be similar to the data_source route, what do you think? Before i will make a pull request there is one other issue that should be solved. When you have a form in which i include multiple of these select2_ajax fields, all of these fields will use the javascript code of the first one due to the |
Hi @maesklaas Hmm... I guess we can merge the city methods then, make the $id parameter optional and return:
That would make it seem easier to implement. I think. Not super-sure, though :-) About the JS: I guess we can place the custom JS outside the |
Please check out my previous comment on github, not email. I just edited it. I'm not usually a premature commenter, but happens to all guys at one point, I guess... :-)) |
The JS does seem the way to go, i'm not sure about merging the methods either. It might also be possible that users want to reuse methods they already have for this, especially when they have an api, and by merging them we force them to create new methods. |
@maesklaas how's this coming? |
FWIW I had a play with this yesterday....I implemented it as public function autocomplete($table, $column) Route::get('search/{table}/{column}', 'SearchController@autocomplete'); |
@OwenMelbz I have been quite busy for some time and didn't find the time to make a pull request yet. I will try to do it in the next couple of weeks. I've you want to add it faster i perfectly fine if you add it yourself. |
@OwenMelbz @tabacitu I just created a pull request ;) |
awesome :) I'm sure @tabacitu will be able to give some feedback once he's got time to see if it can go into a future release! |
what would you say about this?
along with a 1-n relationship and q being a select field containing all the district objects added |
I'm just going to close this up as the original issue has a PR for it, and its been added to the new consolidation list #285 |
Update: we've had a select2_from_ajax field for a while now. |
Hi,
I really like your package. At the moment i have a CrudController in which i have an 1-n relation with an select2 field. But my edit and crete forms loading time is quite large because of the fact that the data loaded in the select2 is quite large. Is it possible to use the ajax functionality of select2 and load data in depending on typed text?
Thanks!
The text was updated successfully, but these errors were encountered: