Git Product home page Git Product logo

select2entity-bundle's Introduction

select2entity-bundle

Introduction

This is a Symfony bundle which enables the popular Select2 component to be used as a drop-in replacement for a standard entity field on a Symfony form.

It works with Symfony 4 and 5. For Symfony 2 and 3, please use version or 2.x of the bundle. For Select2 4.0 and above. For older versions, use version 1.x of the bundle (not compatible with Symfony 5).

The main feature that this bundle provides compared with the standard Symfony entity field (rendered with a html select) is that the list is retrieved via a remote ajax call. This means that the list can be of almost unlimited size. The only limitation is the performance of the database query or whatever that retrieves the data in the remote web service.

It works with both single and multiple selections. If the form is editing a Symfony entity then these modes correspond with many to one and many to many relationships. In multiple mode, most people find the Select2 user interface easier to use than a standard select tag with multiple=true with involves awkward use of the ctrl key etc.

The project was inspired by lifo/typeahead-bundle which uses the Typeahead component in Bootstrap 2 to provide similar functionality. Select2Entity can be used anywhere Select2 can be installed, including Bootstrap 3.

Thanks to @ismailbaskin we now have Select2 version 4 compatibility.

Screenshots

This is a form with a single selection field list expanded.

Single select example

This is a form with a multiple selection field list expanded.

Multiple select example

Installation

Select2 must be installed and working first. I hope to setup a demo site but my setup is basically BraincraftedBootstrapBundle with Select2 installed for Bootstrap 3. Once the Braincrafted bundle is working, the only files I've needed to install are:

select2.js, select2.css from https://github.com/select2/select2/tree/4.0.0

select2-bootstrap.css from https://github.com/t0m/select2-bootstrap-css/tree/bootstrap3. That gets it working for Bootstrap 3.

These files live in the Resources/public/js and Resources/public/css folders of one of my bundles and then included in my main layout.html.twig file.

Alternatively, minified versions of select2.js and select2.css can be loaded from the CloudFlare CDN using the two lines of code given here: https://select2.github.io. Make sure the script tag comes after where jQuery is loaded. That might be in the page footer.

  • Add tetranz/select2entity-bundle to your projects composer.json "requires" section:
{
    // ...
    "require": {
        // ...
        "tetranz/select2entity-bundle": "2.*"
    }
}

Note that this only works with Select2 version 4. If you are using Select2 version 3.X please use "tetranz/select2entity-bundle": "1.*" in composer.json

  • Run php composer.phar update tetranz/select2entity-bundle in your project root.
  • Update your project config/bundles.php file and add this bundle to the $bundles array:
$bundles = [
    // ...
    Tetranz\Select2EntityBundle\TetranzSelect2EntityBundle::class => ['all' => true]
];
  • Update your project config/packages/twig.yaml file to provide global twig form templates:
twig:
    form_themes:
        - '@TetranzSelect2Entity/Form/fields.html.twig'

* Load the Javascript on the page. The simplest way is to add the following to your layout file. Don't forget to run console assets:install. Alternatively, do something more sophisticated with Assetic.
<script src="{{ asset('bundles/tetranzselect2entity/js/select2entity.js') }}"></script>

How to use

The following is for Symfony 4. See https://github.com/tetranz/select2entity-bundle/tree/v2.1 for Symfony 2/3 configuration and use.

Select2Entity is simple to use. In the buildForm method of a form type class, specify Select2EntityType::class as the type where you would otherwise use entity:class.

Here's an example:

$builder
   ->add('country', Select2EntityType::class, [
            'multiple' => true,
            'remote_route' => 'tetranz_test_default_countryquery',
            'remote_params' => [], // static route parameters for request->query
            'class' => '\Tetranz\TestBundle\Entity\Country',
            'primary_key' => 'id',
            'text_property' => 'name',
            'minimum_input_length' => 2,
            'page_limit' => 10,
            'allow_clear' => true,
            'delay' => 250,
            'cache' => true,
            'cache_timeout' => 60000, // if 'cache' is true
            'language' => 'en',
            'placeholder' => 'Select a country',
            'query_parameters' => [
                'start' => new \DateTime(),
                'end' => (new \DateTime())->modify('+5d'),
                // any other parameters you want your ajax route request->query to get, that you might want to modify dynamically
            ],
            // 'object_manager' => $objectManager, // inject a custom object / entity manager 
        ])

Put this at the top of the file with the form type class:

use Tetranz\Select2EntityBundle\Form\Type\Select2EntityType;

Options

Defaults will be used for some if not set.

  • class is your entity class. Required
  • primary_key is the name of the property used to uniquely identify entities. Defaults to 'id'
  • text_property This is the entity property used to retrieve the text for existing data. If text_property is omitted then the entity is cast to a string. This requires it to have a __toString() method.
  • multiple True for multiple select (many to many). False for single (many to one) select.
  • minimum_input_length is the number of keys you need to hit before the search will happen. Defaults to 2.
  • page_limit This is passed as a query parameter to the remote call. It is intended to be used to limit size of the list returned. Defaults to 10.
  • scroll True will enable infinite scrolling. Defaults to false.
  • allow_clear True will cause Select2 to display a small x for clearing the value. Defaults to false.
  • allow_add Is an option array for the add tags settings of Select2. Only available when 'multiple' is true on form.
    • enabled Enables the allow new tags option. True or False. Default False.
    • new_tag_text The text that is displayed behind entities that don't exist if allow_add is true. Default is " (NEW)".
    • new_tag_prefix The prefix identifier for new tags, default is "__". Your real values must not contain these symbols in the beginning.
    • tag_separators A javascript array of delimiters to auto split the tags with.
  • delay The delay in milliseconds after a keystroke before trigging another AJAX request. Defaults to 250 ms.
  • placeholder Placeholder text.
  • language i18n language code. Defaults to en.
  • theme Defaults to 'default'.
  • cache Enable AJAX cache. Results will be cached for each 'term' queried.
  • cache_timeout How long to cache a query in milliseconds. Setting to 0 will cause the cache to never timeout (60000 = 60 seconds)
  • transformer The fully qualified class name of a custom transformer if you need that flexibility as described below.
  • autostart Determines whether or not the select2 jQuery code is called automatically on document ready. Defaults to true which provides normal operation.
  • width Sets a data-width attribute if not null. Defaults to null.
  • class_type Optional value that will be added to the ajax request as a query string parameter.
  • render_html This will render your results returned under ['html'].

The url of the remote query can be given by either of two ways: remote_route is the Symfony route. remote_params can be optionally specified to provide parameters. Alternatively, remote_path can be used to specify the url directly.

You may use query_parameters for when those remote_params have to be changeable dynamically. You may change them using $('#elem').data('query-parameters', { /* new params */ });

The defaults can be changed in your config/packages/tetranzselect2entity.yaml file with the following format.

tetranz_select2_entity:
    minimum_input_length: 2
    page_limit: 8
    allow_clear: true
    delay: 500
    language: 'fr'
    theme: 'default'
    cache: false
    cache_timeout: 0
    scroll: true
    object_manager: 'manager_alias'
    render_html: true

AJAX Response

The controller should return a JSON array in the following format. The properties must be id and text.

[
  { id: 1, text: 'Displayed Text 1' },
  { id: 2, text: 'Displayed Text 2' }
]

Infinite Scrolling

If your results are being paged via the Select2 "infinite scrolling" feature then you can either continue to return the same array as shown above (for Backwards Compatibility this bundle will automatically try to determine if more results are needed), or you can return an object shown below to have finer control over the paged results.

The more field should be true if there are more results to be loaded.

{
  results: [
     { id: 1, text: 'Displayed Text 1' },
     { id: 2, text: 'Displayed Text 2' }
  ],
  more: true
}

Your controller action that fetches the results will receive a parameter page indicating what page of results should be loaded. If you set scroll to true then you must handle the page parameter in the query. Weird things will happen if you don't.

Custom option text

If you need more flexibility in what you display as the text for each option, such as displaying the values of several fields from your entity or showing an image inside, you may define your own custom transformer. Your transformer must implement DataTransformerInterface. The easiest way is probably to extend EntityToPropertyTransformer or EntitiesToPropertyTransformer and redefine the transform() method. This way you can return as text anything you want, not just one entity property.

Here's an example that returns the country name and continent (two different properties in the Country entity):

$builder
    ->add('country', Select2EntityType::class, [
        'multiple' => true,
        'remote_route' => 'tetranz_test_default_countryquery',
        'class' => '\Tetranz\TestBundle\Entity\Country',
        'transformer' => '\Tetranz\TestBundle\Form\DataTransformer\CountryEntitiesToPropertyTransformer',
    ]);

In transform sets data array like this:

$data[] = array(
    'id' => $country->getId(),
    'text' => $country->getName().' ('.$country->getContinent()->getName().')',
);

Your custom transformer and respectively your Ajax controller should return an array in the following format:

[ 
    { id: 1, text: 'United Kingdom (Europe)' },
    { id: 1, text: 'China (Asia)' }
]

If you are using the allow_add option and your entity requires other fields besides the text_property field to be valid, you will either need to extend the EntitiesToPropertyTransformer to add the missing field, create a doctrine prePersist listener, or add the missing data in the form view after submit before saving.

Add New Tags

If you want to be able to create new entities through Select2 tags, you can enable it using the allow_add set of options.

For example:

$builder
    ->add('tags', Select2EntityType::class, [
        'remote_route' => 'tetranz_test_tags',
        'class' => '\Tetranz\TestBundle\Entity\PostTags',
        'text_property' => 'name',
        'multiple' => true,
        'allow_add' => [
            'enabled' => true,
            'new_tag_text' => ' (NEW)',
            'new_tag_prefix' => '__',
            'tag_separators' => '[",", " "]'
        ],
    ]);

A few things to keep in mind when adding tags:

  • Your data should not have any chance of matching the first characters with the new_tag_prefix. If there is a chance, change it to something else like '**' or '$$'.
  • tag_separators is the same as the Select2 option. It should be a javascript array.
  • If the entity you are wanting to allow_add has any other required fields aside from the one specified in text_property, you must either add them in the form submit or add prePersist hooks to the doctrine entity.
  • If you are using the "tags" to allow the creation of new entities through a single entry mode, keep in mind you need to remove the Space as a separator or you won't be able to input a space character in this entity.
$builder
    ->add('tags', Select2EntityType::class, [
        ...
        'allow_add' => [
            ...
            'tag_separators' => '[",", ""]' // No Space here
        ],
    ]);

Including other field values in request

If you need to include other field values because the selection depends on it you can add the req_params option. The key is the name of the parameter in the query string, the value is the path in the FormView (if you don't know the path you can do something like {{ dump(form) }} in your template.)

The property option refers to your entity field which is used for the label as well as for the search term.

In the callback you get the QueryBuilder to modify the result query and the data object as parameter (data can be a simple Request object or a plain array. See AutocompleteService.php for more details).

$builder
    ->add('firstName', TextType::class)
        ->add('lastName', TextType::class)
        ->add('state', EntityType::class, array('class' => State::class))
        ->add('county', Select2EntityType::class, [
            'required' => true,
            'multiple' => false,
            'remote_route' => 'ajax_autocomplete',
            'class' => County::class,
            'minimum_input_length' => 0,
            'page_limit' => 10,
            'scroll' => true,
            'allow_clear' => false,
            'req_params' => ['state' => 'parent.children[state]'],
            'property' => 'name',
            'callback'    => function (QueryBuilder $qb, $data) {
                $qb->andWhere('e.state = :state');

                if ($data instanceof Request) {
                    $qb->setParameter('state', $data->get('state'));
                } else {
                    $qb->setParameter('state', $data['state']);
                }

            },
        ])
    ->add('city', Select2EntityType::class, [
        'required' => true,
        'multiple' => false,
        'remote_route' => 'ajax_autocomplete',
        'class' => City::class,
        'minimum_input_length' => 0,
        'page_limit' => 10,
        'scroll' => true,
        'allow_clear' => false,
        'req_params' => ['county' => 'parent.children[county]'],
        'property' => 'name',
        'callback'    => function (QueryBuilder $qb, $data) {
            $qb->andWhere('e.county = :county');

            if ($data instanceof Request) {
                $qb->setParameter('county', $data->get('county'));
            } else {
                $qb->setParameter('county', $data['county']);
            }

        },
    ]);

Because the handling of requests is usually very similar you can use a service which helps you with your results. To use it just add a route in one of your controllers:

    /**
     * @param Request $request
     *
     * @Route("/autocomplete", name="ajax_autocomplete")
     *
     * @return Response
     */
    public function autocompleteAction(Request $request)
    {
        // Check security etc. if needed
    
        $as = $this->get('tetranz_select2entity.autocomplete_service');

        $result = $as->getAutocompleteResults($request, YourFormType::class);

        return new JsonResponse($result);
    }

Templating

General templating has now been added to the bundle. If you need to render html code inside your selection results, set the render_html option to true and in your controller return data like this:

[ 
    { id: 1, text: 'United Kingdom (Europe)', html: '<img src="images/flags/en.png" />' },
    { id: 2, text: 'China (Asia)', html: '<img src="images/flags/ch.png">' }
]
If you need further templating, you'll need to override the .select2entity() method as follows. If you need [Templating](https://select2.org/dropdown#templating) in Select2, you could consider the following example that shows the country flag next to each option.

Your custom transformer should return data like this:

[ 
    { id: 1, text: 'United Kingdom (Europe)', img: 'images/flags/en.png' },
    { id: 2, text: 'China (Asia)', img: 'images/flags/ch.png' }
]

You need to define your own JavaScript function select2entityAjax which extends the original one select2entity and display custom template with image:

$.fn.select2entityAjax = function(action) {
    var action = action || {};
    var template = function (item) {
        var img = item.img || null;
        if (!img) {
            if (item.element && item.element.dataset.img) {
                img = item.element.dataset.img;
            } else {
                return item.text;
            }
        }
        return $(
            '<span><img src="' + img + '" class="img-circle img-sm"> ' + item.text + '</span>'
        );
    };
    this.select2entity($.extend(action, {
        templateResult: template,
        templateSelection: template
    }));
    return this;
};
$('.select2entity').select2entityAjax();

This script will add the functionality globally for all elements with class select2entity, but if the img is not passed it will work as the original select2entity. You should add a 'autostart' => false to form to run properly JS code.

    ->add('contry', Select2EntityType::class, [
        'remote_route' => 'country_select2_query',
        'autostart' => false,
    ])

You also will need to override the following block in your template:

{% block tetranz_select2entity_widget_select_option %}
    <option value="{{ label.id }}" selected="selected"
            {% for key, data in label %}
                {% if key not in ['id', 'text'] %} data-{{ key }}="{{ data }}"{% endif %}
            {% endfor %}>
        {{ label.text }}
    </option>
{% endblock %}

This block adds all additional data needed to the JavaScript function select2entityAjax, like data attribute. In this case we are passing data-img.

Themes

Select2 supports custom themes using the theme option so you can style Select2 to match the rest of your application. For Bootstrap4 theme look at https://github.com/ttskch/select2-bootstrap4-theme

Embed Collection Forms

If you use Embedded Collection Forms and data-prototype to add new elements in your form, you will need the following JavaScript that will listen for adding an element .select2entity:

$('body').on('click', '[data-prototype]', function(e) {
    $(this).prev().find('.select2entity').last().select2entity();
});

select2entity-bundle's People

Contributors

alexndlm avatar arkemlar avatar bukashk0zzz avatar chrisp1tv avatar dubbleclick avatar duhui avatar emirii avatar jaimz22 avatar kfi avatar kl3sk avatar knallcharge avatar lifo101 avatar mathieujamot avatar maximepinot avatar michalkurzeja avatar mik-laj avatar mnowaczyk avatar n3o77 avatar peter-gribanov avatar philetaylor avatar pivolan avatar remmel avatar roverwolf avatar schyzophrenic avatar seb33300 avatar seriy avatar tetranz avatar tmisheva avatar vibby avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

select2entity-bundle's Issues

Preloading data with minimum length = 0

Hi,

I would like to add feature that formtype return some records on load. I can add attribute minimum_input_length=0, so records will be loaded, but I can not add query_builder if I want to specific which one recoreds should be loaded on load.

Do you have any solution?

Not getting value after submit on Symfony3

This is related to my thread on Stack here

I use select2entity-bundle 2.* in my project to select a town (commune in French) out of 30000+ rows. I managed all the client-side implementation fine and can select my towns seamlessly. But after submit, the field is empty with an invalid error message.

In the profiler, i get this message:

Symfony\Component\Validator\ConstraintViolation
Object(Symfony\Component\Form\Form).children[address].children[commune] = 30223
Caused by: Symfony\Component\Form\Exception\TransformationFailedException
Unable to reverse value for property path "commune": The choice "30223" does not exist or is not unique
Caused by: Symfony\Component\Form\Exception\TransformationFailedException
The choice "30223" does not exist or is not unique

So this error means that my choice (town of Chambéry, ID 30223) is not part of the available choices on form build. Ok. But the bundle is supposed to handle this and display the selection after form submit i believe?

So, what i did was hack into the Twig field template and dump() the value variable -> empty.
I also dumped the POST vars, just in case but the given posted var fits perfectly my selection.

Am I missing something?
Thanks!

"Tags" support is throwing an exception in select2 (even if not enabled)

The new "tags" support in v2.7 is causing my installation to hit a apparent bug in the select2 code base (and I don't even use the tags feature). I'm not entirely sure why at the moment, but it can be reproduced by simply typing one of the separator characters into a select2 input (eg: a space or comma). You'll have to enable your browser's dev tools to see the error shown below. You don't need tags enabled in your select2 input to see the error.

error

I found a quick work-around for your bundle. It doesn't fix the bug but at least makes it so that installations that don't use the tag feature to cause an exception (which also prevents the search query from working). Simply don't add the tags related data attributes to the element if allow_add is not enabled.

I'll submit a pull-request shortly with that work-around, but as I said, it doesn't actually fix the exception from being thrown if you do use the tag feature.

remote_params

Can i know what is the type of return that this function should be ?
'remote_route' => 'tetranz_test_default_countryquery', ?
it should be a query ? or a list ?

select2 is not working for me in symfony2.7

Below is the form when i remove the tetranz_select2entity this is working. i have check json url in separate url it also woking fine. every time an error displayed PropertyAccessor requires a graph of objects or arrays to operate on i try to resolve the problem but failed i check EntityToPropertyTransformer class and print the entity it return 0.
following is the Formtype
$builder->add('outletid', 'entity', array(
'multiple' => false,
#'remote_route' => 'admin_notification_outletjson',
'class' => 'Application\FreemonyBundle\Entity\Outlet',
// 'text_property' => 'email',
// 'minimum_input_length' => 2,
// 'page_limit' => 10,
'placeholder' => 'Select a country',
));

Bootstrap theme

Hello, I'm using your bundle and it works fine.
The only problem is bootstrap theme: I'm using the official theme from https://github.com/select2/select2-bootstrap-theme
but it doesn't work. It says I need to set theme: "bootstrap" when initialize select2.
Can you help me to do that?

I've solved adding
theme: "bootstrap",

in bundles/tetranzselect2entity/js/select2entity.js

$(document).ready(function () {
  $.fn.select2entity = function(action) {
    var action = action || {};
    this.select2($.extend(action, {
      theme: "bootstrap",
      ajax: {
        data: function (params) {
          return {
            q: params.term
          };
        },
        processResults: function (data) {
          return {
            results: data
          };
        }
      }
    }));
    return this;
  };

  $('.select2entity').select2entity();
});

do you have a more clean solution, like config.yml?
Thanks

Implement "attributes" argument

Hello.

As I finally got this bundle to work... is there any chance to implement 'attr' argument, like in typical form fields? For example, I'd like to have custom CSS class on my field - right now I can't control Selec2's width and it looks like crap. It can be worked around of course, but having control over attributes would be great.

[Feature] Add cache clear option

The cache option is very useful, however on some occasions it is necessary to clear the cache manually (e.g. if we know that the remote data has changed). Currently the only way is to set extremely low cache timeout (bad), disable cache entirely (also not great) or to override ajax.transport function and override the caching layer. It would be great to have a function that would clear the cache on demand for us.

Example call:

    $element.select2entity("clear-cache");

This should completely clear the cache array.

Can't set the select2 value programatically from js

I'm trying to set the the value of the select2 from js instead and I can't find a solution.
I found this thread already: select2/select2#3057
The solutions vary, some recommend to give the select2 a custom json but it won't work for me

$("#list").select2('data', [{"id":602,"text":"1234"}]);

Others recommend to append the manually then change the value

$('#list').append('1234');
$('#list').select2().val(602).trigger("change")

This seems to work but the next time you click on the select2, it will generate errors

jQuery.Deferred exception: Cannot read property 'slice' of undefined TypeError: Cannot read property 'slice' of undefined

Is this a bug or am I doing it wrong?

Unable to generate a URL for the named route "" in Symfony 3.2

Hello,

When adding this field

            ->add('company', Select2EntityType::class, [
                'class' => 'ApiBundle:Company',
                'primary_key' => 'id',
                'multiple' => false,
                'text_property' => 'name',
                'minimum_input_length' => 2,
                'allow_clear' => true,
                'placeholder' => 'Select a Company',
                'required' => false,
                'empty_data' => null,
            ])

I get the following error:
image

Even if i remove all options from the field and do a simple
->add('company', Select2EntityType::class, []) i would get the error.

If I remove the field or put a regular entity field everything works perfectly.
The bundle is itself properly installed.

Any leads on where that could come from?

Thanks guys!

Can't get the search input

hello,

i'm using SF3 and tried to install this bundle. I'm supposed to get an input form with a "search" input text like https://github.com/tetranz/select2entity-bundle/blob/master/Resources/doc/img/multi.png but I've got this :
1

Here is my form :

use Tetranz\Select2EntityBundle\Form\Type\Select2EntityType;
...
  public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('recipient', Select2EntityType::class, [
            'multiple' => true,
            'remote_route' => 'user_select',
            'class' => User::class,
            'primary_key' => 'id',
            'text_property' => 'name',
            'minimum_input_length' => 2,
            'page_limit' => 10,
            'allow_clear' => true,
            'delay' => 250,
            'cache' => true,
            'cache_timeout' => 60000, // if 'cache' is true
            'language' => 'en',
            'placeholder' => 'Select a country',
            'label' => 'recipient',
            'translation_domain' => 'FOSMessageBundle',
            // 'object_manager' => $objectManager, // inject a custom object / entity manager
        ])
            ->add('subject', LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\TextType'), array(
                'label' => 'subject',
                'translation_domain' => 'FOSMessageBundle',
            ))
            ->add('body', FroalaEditorType::class, array(
                'label' => 'body',
                'translation_domain' => 'FOSMessageBundle',
            ));
    }

My Appkernel contains :

            new Braincrafted\Bundle\BootstrapBundle\BraincraftedBootstrapBundle(),
            new Tetranz\Select2EntityBundle\TetranzSelect2EntityBundle(),

My template:

({% block stylesheets %}
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
<script src="{{ asset('node_modules/select2-bootstrap-css/select2-bootstrap.min.css') }}"></script>
{% endblock %}
<h2>{% trans from 'FOSMessageBundle' %}send_new{% endtrans %}</h2>

<form action="{{ url('message_thread_new') }}" method="post">
    {{ form_widget(form) }}

    <input type="submit" />
</form>

{% endblock %}

{% block javascripts %}

<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>
{% endblock %}))

My controller :


    /**
     * @Route("/query/user.json", name="user_select")
     */
    public function userSelectAction(Request $request)
    {
      $em = $this->getDoctrine()->getManager();

        $result =  $em->createQuery('
            SELECT u.id, u.username as text
            FROM AppBundle:User u
            WHERE lower(u.username)  LIKE :username
            ORDER BY u.username
        ')
        ->setParameter('username', '%' . $query . '%')
        ->setMaxResults(10)
        ->getArrayResult();

        return new JsonResponse($result);
    }

Any idea ?
Thanks

Doesn't work with mongo db :(

Hi,

It seems that your bundle doesn't work with mongodb :

Type error: Argument 1 passed to Tetranz\Select2EntityBundle\Form\Type\Select2EntityType::__construct() must implement interface Doctrine\ORM\EntityManagerInterface, instance of Doctrine\ODM\MongoDB\DocumentManager given, called in

Basically MongoDB part of Doctrine doens't implement the same interface as "Entity" one ...

Any solution or workaround?

Thanks!

2.6 not available in Packagist

Hi, I'm looking to update my project to fix #30 which I believe is solved in 2.6, however it appears the tag hasn't been created so Packagist/composer cannot update - is it possible to get a tag created for this?

Specify width

Due to a bug in Select2 you need to specify width when a select2 element is hidden on render else it will be 100px wide.

select2/select2/issues/3278

But afaik there is no option to specify width...

Foreign Entity with invalid value causes sql error

There is a bug with foreign entity.
I have a form Book, that has field author_id. Author id is taken from users.id.
If I submit integer values, then all is fine. But when I submit text instead of integer id, I get doctrine exception
Uncaught PHP Exception Doctrine\DBAL\Exception\DriverException: "An exception occurred while executing 'SELECT t0.id AS id_1, t0.firstname AS firstname_2 FROM users t0 WHERE t0.id = ?' with params ["test"]

The default Symfony Form Entity is working fine, it returns This value is not valid. error

Unable to re submit the form if the the select allows (and contains) a new entry

Hi,

When adding a Select2EntityType field with allow_add option enabled.

If we add a new value:

When we submit the form for the first time, the select value is submitted with the new_tag_prefix
Ex: __myvalue

But if the form submission fails, the select is refilled without the new_tag_prefix.
So the submitted value will be myvalue insteaf of __myvalue.

So the form submission will fails because Select2Entity is not able to know that this is a new value submitted.

Is it bug or maybe I have missed something in the configuration?

I can solve this by persisting the new added entity on form submit even if the submission fails.
But I wish to persist it only if the form submission is valid.

Seb

Shouldn't return ArrayCollection in EntitiesToPropertyTransformer

In your EntitiesToPropertyTransformer you return an ArrayCollection instead of an empty array when the $value is empty. I'm pretty sure you simply want to return an empty array instead of the collection. For one, you can't assume people will be using Doctrine, and second, I end up having to do something like this in some of my code that uses a select2 filter:

$form->handleRequest($request);
if ($form->isValid()) {
    $filter = $form->getData();
    // fix Select2EntityType nuance 
    if (($filter['tags'] instanceof ArrayCollection) && $filter['tags']->count() == 0) {
        $filter['tags'] = null;
    }
}

Allow option to limit number of tags/selections

It should be great to be able to define maximum allowed number of tags directly in form parameters like this:

->add('lockedCompanies',Select2EntityType::class,[
             'maximum_selection_length' => 2,'

Solution shoud be to add support of parameter in config and twig template:

'data-maximum-selection-length' : maximum_selection_length,

Then edit js file of the bundle like this on select2 creation:

 $s2.select2($.extend(true, {
                // Tags support
                maximumSelectionLength: $s2.data('maximum-selection-length'),

I tested it locally and it seems to work.
What do you think about this idea?

unable to update route of select2

i have chained select, but i'm anable to update the route depending on first select.. I tried this

            $.fn.select2entityAjax = function(action) {
            var action = action || {};
            this.select2($.extend(action, {
                ajax: {
                    url: function () {
                        return  Routing.generate('subactivity_list', {  _locale: '{{ app.request.locale }}', id: $('#company_activity').val() });
                    },
                    data: function (params) {
                        return {
                            q: params.term
                        };
                    },
                    processResults: function (data) {
                        return {
                            results: data
                        };
                    }
                }
            }));
            return this;
        };
        $('#company_subactivities').select2entityAjax();

        $('#company_activity').on('change', function(){
            activity = $(this).val();
            var locale = '{{ app.request.locale }}' ;
            route = Routing.generate('subactivity_list', {_locale: locale, id: activity  });
            $('#company_subactivities').attr('data-ajax--url', route);
            $('#company_subactivities').attr('ajax--url', route);


        });
    });

Can you provide some info?

Custom query and custom request params

Is possible send custom params to the request and process a custom query ?

Example:

I send the country and want get cityesnot deleted (logical deletion) of this country

1 - select the coutry
2 - autocomplete cityes of the coutry

Value not valid and remote_params

I'd like to use the select2 tags option to add a non existing entity (e.g: a new Country entity) but I have a "This value is not valid" error, presumably from the ChoicesTransformer and the fact that the entity does not exist yet.
How to avoid that ?

Also, I have linked two Entities: Country and PostalCode (Zip Code). When choosing a Country I want to load all the PostalCode associated but don't know how to pass the param in my ajax call.

Not working with non default entity manager

In my application, I'm using entities from Default Entity manager, and also from alternative entity manager.

select2entity-bundle seems to work only on default entity manager.

Suggestion: do not inject entity manager, but doctrine service.
Use manager name instead of entity manager to handle EntityPropertyTransformer (and, by default, use "default" for this manager name).

Having an options error

Followed all the install instructions and i'm receiving the following error when loading my form:

The options "class", "minimum_input_length", "multiple", "page_limit", "placeholder", "remote_route", "text_property" do not exist. Known options are: "action", "attr", "auto_initialize", "block_name", "by_reference", "cascade_validation", "compound", "constraints", "csrf_field_name", "csrf_message", "csrf_protection", "csrf_provider", "csrf_token_id", "csrf_token_manager", "data", "data_class", "disabled", "empty_data", "error_bubbling", "error_mapping", "extra_fields_message", "inherit_data", "intention", "invalid_message", "invalid_message_parameters", "label", "label_attr", "mapped", "max_length", "method", "pattern", "post_max_size_message", "property_path", "read_only", "required", "translation_domain", "trim", "validation_groups", "virtual" 

Any advice on this?

Symfony version 2.5.10
Debug info:

CRITICAL - Uncaught PHP Exception Symfony\Component\OptionsResolver\Exception\InvalidOptionsException: "The options "class", "minimum_input_length", "multiple", "page_limit", "placeholder", "remote_route", "text_property" do not exist. Known options are: "action", "attr", "auto_initialize", "block_name", "by_reference", "cascade_validation", "compound", "constraints", "csrf_field_name", "csrf_message", "csrf_protection", "csrf_provider", "csrf_token_id", "csrf_token_manager", "data", "data_class", "disabled", "empty_data", "error_bubbling", "error_mapping", "extra_fields_message", "inherit_data", "intention", "invalid_message", "invalid_message_parameters", "label", "label_attr", "mapped", "max_length", "method", "pattern", "post_max_size_message", "property_path", "read_only", "required", "translation_domain", "trim", "validation_groups", "virtual"" at /Users/Steve/Sites/NavioHealth/patient-app-web/vendor/symfony/symfony/src/Symfony/Component/OptionsResolver/OptionsResolver.php line 260
Context: {"exception":"Object(Symfony\Component\OptionsResolver\Exception\InvalidOptionsException)"}

Results not displayed; empty entity

Hello,
I configured the bundle as indicated in the doc.
The thing is, my entities are using uuids as primary keys and name as text property, so here is what I did:

            $builder->add('category', Select2EntityType::class, array(
                'class' => Category::class,
                // [...]
                'primary_key' => 'uuid',
                'text_property' => 'name'
            ));

Here is the output from the controller used by the widget:

[{"uuid":"69d440fb-357a-440a-a932-0e71a203b085","name":"Some Category"}]

However, as I said, results are loaded (I checked in the brower console, everything is clear), and here is what happens. I tried investigating the problem, and found out that the $entity coming into EntityToPropertyTransformer::transform($entity) is empty.

Any clue?

Many To Many Issue

Hello, I've an issue with many to many relationship (if I use EntityType it works):

This is the use case:
I've a match with three categories of judges.
This code works:

->add('judgesA', EntityType::class, array(
                'class'=>'AppBundle\Entity\Judge',
                'expanded'=>'false',
                'multiple'=>'true',
                'choice_label'=>'name'
            ))
            ->add('judgesB', EntityType::class, array(
                'class'=>'AppBundle\Entity\Judge',
                'expanded'=>'false',
                'multiple'=>'true',
                'choice_label'=>'name'
            ))
            ->add('judgesC', EntityType::class, array(
                'class'=>'AppBundle\Entity\Judge',
                'expanded'=>'false',
                'multiple'=>'true',
                'choice_label'=>'name'
            ))

but this doesn't work:

            ->add('judgesA', Select2EntityType::class, array(
                'multiple'=>true,
                'class'=>'AppBundle\Entity\Judge',
                'empty_data'=>null,
                'placeholder'=>'',
                'remote_route' => 'all_judges_json',
                'primary_key' => 'id',
                'text_property' => 'name',
                'cache'=>true,
                'allow_clear'=>true
            ))
            ->add('judgesB', Select2EntityType::class, array(
                'multiple'=>true,
                'class'=>'AppBundle\Entity\Judge',
                'empty_data'=>null,
                'placeholder'=>'',
                'remote_route' => 'all_judges_json',
                'primary_key' => 'id',
                'text_property' => 'name',
                'cache'=>true,
                'allow_clear'=>true
            ))
            ->add('judgesC', Select2EntityType::class, array(
                'multiple'=>true,
                'class'=>'AppBundle\Entity\Judge',
                'empty_data'=>null,
                'placeholder'=>'',
                'remote_route' => 'all_judges_json',
                'primary_key' => 'id',
                'text_property' => 'name',
                'cache'=>true,
                'allow_clear'=>true
            ))

This is the error:

Neither the property "judgesA" nor one of the methods "addJudgesOn()"/"removeJudgesOn()", "addJudgesUm()"/"removeJudgesUm()", "setJudgesA()", "judgesA()", "__set()" or "__call()" exist and have public access in class "AppBundle\Entity\WorkEvent".

Can you help me? Thank you

multiple option

Hi,
instead of a remote_route that sends serialized entities can I use an array as source of a multiple select2 without autocompletition?
thx

Request: additional data to be sent via AJAX

Hi.

I love this bundle, thanks for a great job. I would like to ask for a feature, which would make it easier to create customized responses. I'd like to send additional data with AJAX request, so I could return filtered dataset to Select2.

For example:

  • I have generic (more or less) API method, which returns a set of entities matching Select2's search query
  • let's say the entities can have parent of the same class
  • I am editing one entity and I would like to set parent, but I don't want the currently being edited entity to appear on the "parent" list, because it makes no sense. I would like to pass current entity's ID to search API along with searchstring:
$builder
    ->add('tags', Select2EntityType::class, [
        'remote_route' => 'tetranz_test_tags',
        'class' => '\Tetranz\TestBundle\Entity\PostTags',
        'text_property' => 'name',
        //...
        'custom_post_data' => array(
            'exclude' => $currentId
        ),
    ]);

Now in search method I can return everything that matches search pattern BUT the one entity to ignore.

Is it possible?

Select 2 allowClear option not working

Hi,
I've been trying to get the Select2 allowClear option to be active. However, I didn't seem to find the way to activate it with your select2entity-bundle. I've tried to add $("#myField").select2entity({allowClear: true}); or $("#myField").select2({allowClear: true});, both before and after I've included the select2entity.js file. Either way, it's not working. It return the error Uncaught TypeError: Cannot read property 'slice' of undefined in select2.min.js.

May I suggest that Select2Entity act similar to Select2, in the way that it doesn't auto-activate the Select2 form (at line 25 of /Resources/public/js/select2entity.js). Instead, let the user activate similar to Select2, with something like $("#myField").select2entity();, passing all the attributes to the .select2();. Moreover, this auto-activatation, prevent applying the Select2 defaults to Select2Entity (since the default would most probably set after including the select2entity.js file).

Not working with functional tests

I'd like to run functional tests and submit a form with this field, but I get the following error:

InvalidArgumentException: Input "my_select2_field" cannot take "1" as a value (possible values: ).

Any ideas?

Wrong tags for composer

When trying to update to 2.8 its get overwritten by 2.52 because 52>8
Perhaps you can remove the tags and retag as 2.5.2 and 2.5.1 ?

[Feature] add non-AJAX option

This is a pre pull-request conversation

I would like the option to have Select2 either use AJAX to fetch data or the options already in the select field. While this can be done - using this bundle for the AJAX fields, and a ChoiceType + custom JS for the others - I would like to see one Select2 field type for Symfony2, which I can switch between the two quickly and easily (as datasets scale), via changing one parameter (e.g. an ajax flag per field).

Is this a change you would like to have as part of the library? I don't believe it's already present in your bundle, and would be interested in working on it.

Provide a CHANGELOG

It's a great help to see the progress and see whats changed in a newer version.

Not working at all...

Hi.
I'm not sure, what's wrong, but I'm pretty sure I did everything like in the documentation. Instead of SELECT field, there's just simple INPUT with text type. No Select2, nothing... (screenshot and twig list from profiler at the end)

I'll show, what I did on the test project.

  • I've got Movie entity with actors field:
  • Class Actor has firstName and surname. Its __toString() returns:
$this->surname . ', ' . $this->firstName
  • Class Movie has:
/**
 * @var ArrayCollection
 * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Actor")
 */
    private $actors;

...and getActors(), setActors(), addActor(), removeActor(). everything works with EntityType::class in form.

  • Action returning JSON search result (it's not cleaned yet, but it works):
<?php
namespace AppBundle\Controller\API\Actor;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class ActorApiController extends Controller
{
    /**
     * @Route(path="/api/actor/search", name="api_actor_search")
     * @Method({"GET"})
     */
    public function searchAction(Request $request)
    {
        $searchString = $request->get('q');
        if(strlen($searchString) < 2)
            return new Response("Invalid search query", 406);

        $entityManager = $this->getDoctrine()->getManager();
        $query = $entityManager->createQuery('
            SELECT a FROM AppBundle:Actor a
            WHERE a.firstName LIKE :searchString
                OR a.surname LIKE :searchString
            ORDER BY a.surname ASC
        ')
                               ->setParameter('searchString', '%' . $searchString . '%');

        $actors = $query->getResult();
        $actorsArray = array();
        foreach($actors as $actor)
        {
            $actorsArray[] = array(
                'id' => $actor->getId(),
                'text' => $actor->__toString(),
            );
        }
        return new Response(json_encode($actorsArray), 200, array('Content-Type' => 'application/json'));
    }
}
  • In config.yml at the end I added:
twig:
    form:
        resources:
            - 'TetranzSelect2EntityBundle:Form:fields.html.twig'
  • I generated CRUD for test with doctrine:generate:crud for AppBundle:Movie
  • In form MovieType, i changed field actors to:
->add('actors', 'tetranz_select2entity', array(
                'multiple' => true,
                'remote_route'=>'api_actor_search',
                'class'=>'AppBundle\Entity\Actor'
            ))
  • at the end I simply edited base.html.twig (again: it's for testing purposes):
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8"/>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.css" rel="stylesheet"/>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.2-rc.1/css/select2.css" rel="stylesheet"/>

    <title>{% block title %}Welcome!{% endblock %}</title>
    {% block stylesheets %}{% endblock %}
    <link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}"/>
</head>
<body>
{% block body %}{% endblock %}
{% block javascripts %}
    <script type="application/javascript">
        var ajaxBaseUrl = '{{ url('homepage') }}';
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.2-rc.1/js/select2.js"></script>

    {% javascripts '@TetranzSelect2EntityBundle/Resources/public/js/select2entity.js' %}
    <script src="{{ asset_url }}"></script>
    {% endjavascripts %}
{% endblock %}
</body>
</html>
main 8.03ms/100%
└ movie/new.html.twig 5.81ms/72%
│ └ base.html.twig 5.74ms/72%
│   └ base.html.twig::block(title)
│   └ base.html.twig::block(stylesheets)
│   └ movie/new.html.twig::block(body) 5.56ms/69%
│   │ └ form_div_layout.html.twig::block(form_start)
│   │ └ form_div_layout.html.twig::block(form_widget) 1.45ms/18%
│   │ │ └ form_div_layout.html.twig::block(form_widget_compound) 1.44ms/18%
│   │ │   └ form_div_layout.html.twig::block(widget_container_attributes)
│   │ │   └ form_div_layout.html.twig::block(form_errors)
│   │ │   └ form_div_layout.html.twig::block(form_rows) 1.20ms/15%
│   │ │   │ └ form_div_layout.html.twig::block(form_row)
│   │ │   │ │ └ form_div_layout.html.twig::block(form_label)
│   │ │   │ │ └ form_div_layout.html.twig::block(form_errors)
│   │ │   │ │ └ form_div_layout.html.twig::block(form_widget)
│   │ │   │ │   └ form_div_layout.html.twig::block(form_widget_simple)
│   │ │   │ │     └ form_div_layout.html.twig::block(widget_attributes)
│   │ │   │ └ form_div_layout.html.twig::block(form_row)
│   │ │   │ │ └ form_div_layout.html.twig::block(form_label)
│   │ │   │ │ └ form_div_layout.html.twig::block(form_errors)
│   │ │   │ │ └ form_div_layout.html.twig::block(integer_widget)
│   │ │   │ │   └ form_div_layout.html.twig::block(form_widget_simple)
│   │ │   │ │     └ form_div_layout.html.twig::block(widget_attributes)
│   │ │   │ └ form_div_layout.html.twig::block(form_row)
│   │ │   │ │ └ form_div_layout.html.twig::block(form_label)
│   │ │   │ │ └ form_div_layout.html.twig::block(form_errors)
│   │ │   │ │ └ form_div_layout.html.twig::block(form_widget)
│   │ │   │ │   └ form_div_layout.html.twig::block(form_widget_simple)
│   │ │   │ │     └ form_div_layout.html.twig::block(widget_attributes)
│   │ │   │ └ form_div_layout.html.twig::block(hidden_row)
│   │ │   │   └ form_div_layout.html.twig::block(hidden_widget)
│   │ │   │     └ form_div_layout.html.twig::block(form_widget_simple)
│   │ │   │       └ form_div_layout.html.twig::block(widget_attributes)
│   │ │   └ form_div_layout.html.twig::block(form_rest)
│   │ └ form_div_layout.html.twig::block(form_end)
│   │   └ form_div_layout.html.twig::block(form_rest)
│   └ base.html.twig::block(javascripts)
└ @WebProfiler/Profiler/toolbar_js.html.twig 2.22ms/28%
  └ @WebProfiler/Profiler/base_js.html.twig

Inner object is validated

Hi,

When selecting an object, the object is validated. It feels somewhat wrong to me: it's a selector, not a form that allows to create an object from user data.

Should it be removed?

Thanks

Accesing Event handler for select2entity bundle?

Is it possible to access event handlers defined in select2 js for the dropdown element:

`$eventname= $(.select2example).select2()
$eventname.on("select2:select", function(e){
ajaxupdatessamplevariable(e.params.data);
console.log(e);

           });`

When I want to remove last options it doesn't work

I have a problem about manyToMany association. When I want to remove last option for multiple select2 it doesn't work. But I remove the last second option it's work. Here is my form type config.

 $builder->add('personnel', Select2EntityType::class, [ 
                'multiple' => true,
                'remote_route' => 'wcms_admin_personnel_search_ajax',
                'class' => 'Wcms\UserBundle\Entity\Personnel',
                'primary_key' => 'id',
                'text_property' => 'definition',
                'minimum_input_length' => 0,
                'page_limit' => 10,
                'empty_data'  => null,
                'allow_clear' => true,
                'delay' => 250,
                'cache' => true,
                'cache_timeout' => 60000,
                'language' => 'tr',
                'autostart' => true
            ]);

Please tag release 2.5 (or 2.4.1)

I need your PHP v5.4 compat fixes, but don't want to use dev-master in my project's composer for your library (I don't want to fork your master either; I'm lazy). Thanks =)

Thanks for the shout-out for lifo/typeahead-bundle, btw. =)

Bug on loading infinite scroll if select2 option "page_limit" < 6

Hi,
i found a bug on loading infinite scroll if i set the select2 option "page_limit" < 6 (in my example 5).

$builder->add('singleSelect2',
              Select2EntityType::class,
              ['multiple' => false,
              'remote_route' => 'single_select2',
              'autostart' => true,
              'primary_key' => 'id',
              'minimum_input_length' => 0,
              'page_limit' => 5,
              'delay' => 500,
              'cache' => true,
              'cache_timeout' => 60000,
              'placeholder' => 'this is a placeholder',
              'scroll' => true]);

On opening the select2 drop down box in GUI i have these problems (i think it's only one bug):

  • it will only loads the first five elements
  • it haves no scroll bar
  • at the end of the drop down box you will see the whole time "Loading more results..."

Well, it looks like a select2 bug but maybe you know more about that? Or did i something wrong?

Greetz,
Schluepfer

non ID primary keys support

non ID primary keys support
when I try to save form:
[Semantical Error] line 0, col 92 near 'id IN (:ids)': Error: Class Entity\Characteristic has no field or association named id
Primary key is slug.

Cannot change autostart in config

Hello,

I would like to change the autostart option globally, so I added it to the config.yml:

tetranz_select2_entity:
    autostart: false

But:

Unrecognized option "autostart" under "tetranz_select2_entity"

Is it normal?

Language option

There are no effects when i try to change language to 'ru'. What am i doing wrong?

$builder->add('company', Select2EntityType::class, array(
'label' => 'form.company',
'translation_domain' => 'FOSUserBundle',
'multiple' => false,
'remote_route' => 'get-all-companies',
'class' => '\AppBundle\Entity\Company',
'primary_key' => 'id',
'text_property' => 'name',
'minimum_input_length' => 3,
'page_limit' => 20,
'allow_clear' => true,
'delay' => 250,
'cache' => true,
'cache_timeout' => 60000, // if 'cache' is true
'language' => 'ru',
'placeholder' => 'form.select.company',
));

select 3.x compatibility

This bundle generate a "select" which is not compatible with select2 Ajax option, I get this error:
Uncaught Error: Option 'ajax' is not allowed for Select2 when attached to a <select> element.
I don't get this error with select2 4.x , but I can't upgrade to 4.x.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.