Skip to content

How can I make a dropdown tree with select2 using jquery?

I’ve been trying to create an dropdown tree with my json. It represents two categories with a list of products.

Here my JSON Array:

    [
    {
    "reference":'BC-ENFANT',
    "name":'Pour les Enfants',
    "description":'Soins pour les enfants...',
    "id":155,
    "productList":[
    {"id":13655,"reference":'PROD_ENFANT_01',"name":'Brushing'},
    {"id":13656,"reference":'PROD_ENFANT_03',"name":'Soins'},
    ]
    },
    
    {
    "reference":'BC-FEMME',
    "name":'Pour les Femmes',
    "description":'Prestations pour les femmes',"id":154,
    "productList":[
    {"id":13657,"reference":'PROD_ENFANT_01',"name":'Brushing'},
    {"id":13658,"reference":'PROD_ENFANT_03',"name":'Soins'},
    ]}]

I have been only able to populate a simple select2 with those lines (Using Ajax call) :

    <div class="form-group">
        <label class="form-label" for="prestationCombo">Prestation</label>
        <div class="input-group">
           <select type="text" id="benefitList" class="form-control"></select>
        </div>
    </div>

        $.post("BookingManager/CategoryResult",
                                {
                                    shopId: shopId
                                },
                                function (data) {
                                    console.log(data);
                                    $('#benefitList').select2({
                                        multiple: false,
                                        data: data.map(c => { return c.reference }),
                                        dropdownParent: $('#emptyEvent'),
                                        placeholder: 'Rechercher une prestation...',
                                    });
                                }
    );

I have already used select2 but never find a way to get a proper solution to this problem.

Answer

The response format of your AJAX call is not in the correct structure for grouped data within Select2.

This can be fixed by using the ajax property of the Select2 library along with processResult. The latter will accept the AJAX response and can be used to convert the data in to the format Select2 needs in order to display grouped options. Try this:

$('#benefitList').select2({
  multiple: false,
  ajax: {
    url: 'BookingManager/CategoryResult',
    type: 'POST',
    data: params => {
      term: params.term, // include the search term in the request
      shopId: shopId
    },
    processResults: data => {
     let results = data.map(group => ({
        text: group.name,
        children: group.productList.map(product => ({
          id: product.id,
          text: product.name
        }))
      }));
    
      return { results };
    }    
  }
  dropdownParent: $('#emptyEvent'),
  placeholder: 'Rechercher une prestation...',
});

For reference this is what the grouped data structure output will look like:

let data = [{"reference":'BC-ENFANT',"name":'Pour les Enfants',"description":'Soins pour les enfants...',"id":155,"productList":[{"id":13655,"reference":'PROD_ENFANT_01',"name":'Brushing'},{"id":13656,"reference":'PROD_ENFANT_03',"name":'Soins'},]},{"reference":'BC-FEMME',"name":'Pour les Femmes',"description":'Prestations pour les femmes',"id":154,"productList":[{"id":13657,"reference":'PROD_ENFANT_01',"name":'Brushing'},{"id":13658,"reference":'PROD_ENFANT_03',"name":'Soins'}]}]

let results = data.map(group => ({
  text: group.name,
  children: group.productList.map(product => ({
    id: product.id,
    text: product.name
  }))
}));

console.log({ results });