Componette

Componette

necris

necris / selectt 1.0.4

Nette forms plugin to use Select2

download-cloud-line composer require necris/selectt

Selectt

Simple implementation of Select2 for Nette Framework.

How to use:

  1. register extension in config:
extensions:
    selectt: Selectt\DI\SelecttExtension
  1. 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.

  1. include Select2 to your project
  2. 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);
    });
});
  1. 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;
}
  1. 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;
}
  1. profit!

Extra data of an option

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 attribute data-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.

price-tag-2-line

Badges

guide-fill

Dependencies

php (>=8.0)
Componette Componette felix@nette.org