Simple implementation of Select2 for Nette Framework.
How to use:
- register extension in config:
extensions:
selectt: Selectt\DI\SelecttExtension- add some configuration
selectt:
single:
class: select2-ajax
jsAttributes:
allowClear: true
placeholder: Please select option
width: 100%
multi:
class: select2-ajax-multi
jsAttributes:
allowClear: true
placeholder: Please select
width: 100%Section jsAttributes contains any Slelect2 parameter you like. If you want to use that parameter only on one select, you can also use metho ->addSelect2Attribute($name, $value) on corresponding object.
- include Select2 to your project
- init Select2 for desired class
$(function(){
$('.select2-ajax').each(function () {
let params = $(this).data().select2Params;
params.ajax = {
url: $(this).data('select2-url'),
dataType: 'json'
};
$(this).select2(params);
});
$('.select2-ajax-multi').each(function () {
let params = $(this).data().select2Params;
params.ajax = {
url: $(this).data('select2-url'),
dataType: 'json'
};
$(this).select2(params);
});
});- create ajax autocomplete component with your own implementation of
Selectt\SelecttDataSource
public function createComponentAutocomplete(): SelecttAutocompleteControl
{
$a = new SelecttAutocompleteControl(new ArrayDataSource([
1 => "Praha",
2 => "Brno",
3 => "Paříž",
4 => "Hitler",
5 => "patří",
6 => "za",
7 => "mříž"
]));
$a->enableEmptyQuery();
return $a;
}- finaly add select2 or multiselect to form. As second parameter provide autocomplete component!
public function createComponentForm(): Nette\Application\UI\Form
{
$f = new Nette\Application\UI\Form();
$f->addText("text", "text");
$f->addSelect2("select2", $this['autocomplete'], "Best select in the world");
$f->addSelect2Multi("select2multi", $this['autocomplete'], "Best multiselect ever");
.
.
.
return $f;
}- profit!
An option can carry any data the JavaScript needs (a parent id, a related structure …). Return it from your data source:
public function searchTerm(?string $query, int $limit, int $offset): array
{
return array_map(
fn(Person $p) => new ResultEntity($p->id, $p->name, ['parentId' => $p->parentId, 'phone' => $p->phone]),
$this->find($query, $limit, $offset),
);
}findByKey() / findByKeys() should return the same data: a selected value (the default of the form, a refused submit)
is rendered with it too. The data must be serializable to JSON (ResultEntity::setData() / getData()).
- In the JSON of the autocomplete the item has the key
data({id, text, data: {...}}). - A selected
<option>rendered by the server has it in the attributedata-selectt(JSON).
assets/selectt.js (an ES module, needs the jQuery of select2) keeps both in one place, the attribute of the option:
import { bindSelecttData, getSelecttData, getSelecttDataAll } from '.../vendor/necris/selectt/assets/selectt.js';
bindSelecttData($); // once: copies the "data" of a picked AJAX result to its <option>
$('#frm-form-select2').on('change', function () {
const data = getSelecttData(this); // {parentId: 5, phone: '…'} or null
});
const all = getSelecttDataAll(document.getElementById('frm-form-select2multi')); // {value: data, …}Without the module: JSON.parse(select.selectedOptions[0].dataset.selectt), and in select2:select
event.params.data.data.