Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/acseo/select-autocomplete-bundle
https://github.com/acseo/select-autocomplete-bundle
Last synced: about 2 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/acseo/select-autocomplete-bundle
- Owner: acseo
- License: mit
- Created: 2020-11-12T13:21:38.000Z (about 4 years ago)
- Default Branch: master
- Last Pushed: 2021-01-21T23:32:02.000Z (almost 4 years ago)
- Last Synced: 2024-10-29T04:07:33.371Z (about 2 months ago)
- Language: PHP
- Size: 53.7 KB
- Stars: 3
- Watchers: 4
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ACSEO SELECT AUTOCOMPLETE BUNDLE
[![Build Status](https://travis-ci.com/acseo/select-autocomplete-bundle.svg?branch=master)](https://travis-ci.com/acseo/select-autocomplete-bundle)
- ## Table of content
* [Introduction](#introduction)
* [Installation](#installation)
* [Usage](#usage)
* [Form options](#form-options)
+ [class](#class)
+ [properties](#properties)
+ [display](#display)
+ [strategy](#strategy)
+ [multiple](#multiple)
+ [format](#format)
+ [identifier](#identifier)
+ [transformer](#transformer)
+ [autocomplete_url](#autocomplete-url)
+ [provider](#provider)
* [Providers](#providers)
## IntroductionThis bundle helps you to build autocomplete fields in your symfony forms without declaring any controller or action.
Fully configurable, you can override any part of the autocompletion process very easily.
Doctrine **ORM** & **ODM** are supported by default, but you can create your own providers for other extensions !
## Installation
Install source code with composer :
```shell script
$ composer require acseo/select-autocomplete-bundle
```Enable the bundle :
```php
// config/bundles.phpreturn [
Acseo\SelectAutocomplete\SelectAutocompleteBundle::class => ['all' => true]
];
```Use the bundle form theme globally (or locally in your templates) :
```yaml
# config/packages/twig.yamltwig:
form_themes:
- '@SelectAutocomplete/form_theme.html.twig'
```## Usage:
Let's start by a simple example :
```php
use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\User;$formBuilder
->add('example', AutocompleteType::class, [
'class' => User::class,
// The searchable properties used for query
'properties' => ['profile.firstName', 'profile.lastName'],
])
;
```With your favorite js library, transform the rendered input to autocomplete input (example with select2) :
```js
$('.acseo-select-autocomplete').each((i, el) => {
const $el = $(el);$el.select2({
minimumInputLength: 1,
ajax: {
cache: false,
url: $el.data('autocomplete-url'), // Get autocomplete url to retrieve search responses
delay: 250,
dataType: 'json',
data: params => ({
q: params.term || '', // Append the search terms to url
// response_format: 'json' // (optional, json by default, see form type options for allowed values)
}),
processResults: data => ({ // Transform entrypoint resuls
results: Object.keys(data).map(value => ({
id: value,
text: data[value]
}))
})
}
});
});
```Please note 3 important things in this js example :
- The rendered input has a `data-autocomplete-url` attribute and the value inside can be used to retrieve search results.
- The query param `q`, which represents the search terms, has to be added to data-autocomplete-url value.
- By default search results are returned by entrypoint like `[{ "value": "label" }]`.Your autocomplete is now functional !
## Form options
| Name | Type | Required | Default | Description |
|--------|--------|------------|-----------|-----------|
| [class](#class) | string | yes | null | The model class supposed to be autocompleted |
| [properties](#properties) | string array | no | id | The properties used in database query to filter search results of autocomplete action. This properties can be nested with path like "nestedProperty.property". |
| [display](#display) | string callable array | no | [properties](#properties) | The displayable properties used to build label of selectable choices. This properties can be nested with path like "nestedProperty.property". |
| [strategy](#strategy) | string | no | contains | The strategy used to filter search results (allowed : starts_with / ends_with / contains / equals). |
| [multiple](#multiple) | bool | no | false | Is collection field. |
| [format](#format) | string callable | no | json | Default format used to encode choices of autocomplete response. Values allowed are provided by your own serializer (basically json / xml / csv / yaml in symfony serializer). Use callable to override encoding process. |
| [identifier](#identifier) | string | no | id | Name of your model identifier property (will be used as value of each choice option). |
| [autocomplete_url](#autocomplete-url) | string | no | request.pathInfo | The entrypoint where autocomplete results can be retrieved. By default we use the route where the form has been built. This value will be set in attribute "data-autocomplete-url" of field input. |
| [transformer](#transformer) | boolean object | no | ModelTransformer | Disable/Override the form type transformer. If this value is false, transformer deals only with the identifier(s) value(s) (useful for filters). |
| [provider](#provider) | string callable array object | no | null | Create your own custom queries or specify a provider to use. |**Tips** : You can also override any part of the process more globally by creating a class which extends AutocompleteType.
### class
```php
use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;$formBuilder
->add('example', AutocompleteType::class, [
'class' => TargetClass::class
])
;
```### properties
```php
use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;$formBuilder
->add('example', AutocompleteType::class, [
'class' => TargetClass::class,
'properties' => 'targetProperty',
// OR
'properties' => ['name', 'profile.email'],
])
;
```### display
```php
use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;$formBuilder
->add('example', AutocompleteType::class, [
'class' => TargetClass::class,
'display' => 'targetPropertyOrMethod',
// OR
'display' => 'nestedProperty.targetProperty',
// OR
'display' => ['user.firstName', 'user.lastName'],
// OR
'display' => function(TargetClass $object): string {
return $object->getTargetProperty();
},
])
;
```### strategy
```php
use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;$formBuilder
->add('example', AutocompleteType::class, [
'class' => TargetClass::class,
'strategy' => 'starts_with', // LIKE ...%
// OR
'strategy' => 'ends_with', // LIKE %...
// OR
'strategy' => 'contains', // LIKE %...%
// OR
'strategy' => 'equals', // = ...
])
;
```### multiple
```php
use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;$formBuilder
->add('example', AutocompleteType::class, [
'class' => TargetClass::class,
'multiple' => true,
])
;
```### format
```php
use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;
use Symfony\Component\HttpFoundation\Response;$formBuilder
->add('example', AutocompleteType::class, [
'class' => TargetClass::class,
// Options values are provided by your serializer (these are default format supported by symfony serializer)
// Format can be override from js by add response_format param in data-autocomplete-url
'format' => 'json', // xml|csv|yaml|...// OR
// Encode response with your logic
'format' => function (array $normalized, Response $response): Response {
return $response->setContent(json_encode($normalized));
}
])
;
```### identifier
```php
use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;$formBuilder
->add('example', AutocompleteType::class, [
'class' => TargetClass::class,
// Identifier is used as choice value
'identifier' => 'targetPropertyOrMethod',
])
;
```### autocomplete_url
Sometimes you will need this option to retrieve search results from specific entrypoint.
```php
use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;$formBuilder
->add('example', AutocompleteType::class, [
'class' => TargetClass::class,
// This option value will be set in data-autocomplete-url of select input attributes
'autocomplete_url' => '/my-custom-entrypoint?param1=kevin',
])
;
```### transformer
```php
use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;$formBuilder
->add('example', AutocompleteType::class, [
'class' => TargetClass::class,
// Don't transform identifiers values to objects
'transformer' => false,// OR
// Use custom transformer
'transformer' => $myCustomTransformer
])
;
```### provider
```php
use Acseo\SelectAutocomplete\DataProvider\Doctrine\AbstractDoctrineDataProvider;
use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;$formBuilder
->add('example', AutocompleteType::class, [
'class' => TargetClass::class,// Override provider on search action to retrieve custom collection (Usage of partial query is allowed)
// The second argument is the default provider which supports the model class
'provider' => function(string $terms, AbstractDoctrineDataProvider $provider) {
return $provider->getRepository(TargetClass::class)
->createQueryBuilder('o')
->where('o.name LIKE :name')
->setParameter('name', $terms.'%')
->getQuery()
->getResult()
;// You can also just override default query (available with ORM & ODM Doctrine providers)
//
// if ($provider instanceof ORMDataProvider) {
// $qb = $provider->createSearchQueryBuilder('o', TargetClass::class, ['name'], $terms, 'starts_with');
// // Custom query
// return $qb->getQuery()->getResult();
// }
//
// if ($provider instanceof ODMDataProvider) {
// $qb = $provider->createSearchAggregationBuilder(TargetClass::class, ['name'], $terms, 'starts_with');
// // Custom query
// return $qb->execute()->toArray();
// }
},
// OR
// Use your own provider object
'provider' => $myProvider,// OR
// You can specify provider to use (the service has to be tagged as acseo_select_autocomplete.data_provider).
// 2 providers are included by default : ORMDataProvider and ODMDataProvider.
// You can add many providers, for specific model class or other kind of databases !
'provider' => MyCustomProvider::class,
// OR
// Create custom provider
// To know more about providers, please see Providers section.
'provider' => [
'find_by_ids' => function(array $ids, AbstractDoctrineDataProvider $provider) {
return $provider->getRepository(TargetClass::class)->findBy(['id' => $ids]);
},
'find_by_terms' => function(string $terms, AbstractDoctrineDataProvider $provider) {
return $provider->getRepository(TargetClass::class)
->createQueryBuilder('o')
->where('o.name LIKE :name')
->setParameter('name', $terms.'%')
->getQuery()
->getResult()
;
}
],
// If provider option is not set, the provider used is the first which supports model class
])
;
```## Providers
Providers classes are used to **retrieve search results** form database and **transform form view data** to model object.
2 Doctrine providers are included by default : ORMDataProvider and ODMDataProvider which supports multiple db connexions.
You can create your own provider for specific model class or specific database. This is an arbitrary example :
```php
manager = $manager;
}
/**
* Does provider supports the model class.
*/
public function supports(string $class): bool
{
return $this->manager->supports($class);
// To make specific provider for specific model class
// return $class === \App\Entity\Foo::class
}
/**
* Used to retrieve object with form view data (reverseTransform).
*/
public function findByIds(string $class, string $identifier, array $ids): array
{
return $this->manager->findOneBy([ $identifier => $ids ]);
}
/**
* Find collection results of autocomplete action.
*/
public function findByTerms(string $class, array $properties, string $terms, string $strategy): array
{
$qb = $this->manager->createQuery($class);
switch ($strategy) {
case 'contains':
$qb->contains($properties, $terms);
break;
// ... Rest of strategies code
}
return $qb->limit(20)->exec();
}
}
```Finally, tag this service with `acseo_select_autocomplete.data_provider`.
```yaml
services:
App\Form\Autocomplete\DataProvider\CustomDataProvider:
autowire: true
tags: ['acseo_select_autocomplete.data_provider']
```Now, this provider will be invoked by default if it supports the given model class.