Select2 style attribute not picking up

Viewed 478

I am attempting to style the background color of some select2 options programmatically. For some reason it doesn't seem to work. I'm not seeing the background-color as red at all. Really what I am trying to do is set the background color for what select2 renders as an li and is the parent of the span tag in the formatText() function.

EDIT: this is currently how the list looks

What you see here where those options are yellow, I want the whole row and not just the text to be yellow.

I also want to style individual rows in my Family drop-down to correspond with how they will be colored in my Products drop-down.

I have two sections of code that I think should be doing this. Here is the Fiddle - https://jsfiddle.net/jamiebrs/8axy7123/

  const productsConfig = {
  width: "100%",
  theme: 'bootstrap4',
  placeholder: "Select item",
  allowClear: true,
  templateSelection: formatText,
  templateResult: formatText, 
  data: dataitems2, 
   escapeMarkup: function(m) {
      return m;
   }
};

function formatText (icon) {
if(icon.badge == undefined){
    return  $('<span>' + icon.text + '</span>');
} else {
  return  $('<span><span class="badge" style"background-color:red">'+ icon.badge.length + '</span> ' + icon.text + '</span>');
}
    
};

and....

$('#products').select2(
    Object.assign({},
    productsConfig,
    {data: null}
  )
 );


$('#fam').on('change', function() {
  // get selected value from the #fam select2
  const selected = $(this).val();
  // get the new products config (products config + data options)
  const newProductsConfig = Object.assign({},
    productsConfig,
    {data: productOptions[selected]}
  );

  // destroy the existing products select2 and re-initialize
  $('#products').empty().select2('destroy').select2(newProductsConfig);
  $('#products').val(null).trigger('change')
});
2 Answers

You simply have a typo in that you are missing the = sign on your style declaration. In your else statement you should change the HTML from

<span class="badge" style"background-color:red">

to

<span class="badge" style="background-color:red">

I might also create a new CSS class and use that rather than using a hardcoded style. So for example you could define a CSS class like this:

.badge-highlight { /* name this whatever you want */
  background-color: red;
}

and then alter your JavaScript to contain this HTML:

<span class="badge badge-highlight">

I am adding another answer since I think my first answer is viable for your initial question and resolves the bug you had, and this answer does what you actually want. Your main issue is that you want to change the background color of your options, but the dropdown container is generated dynamically at the time it opens. This makes it tricky to alter the styles. However, you can somewhat hack the theme option in the select2 config. Normally, when you set the theme option it will add that string to your dropdown class prefixed by select2-container--. For example, if you set this config:

$('#example').select2({theme: 'bootstrap4'});

then whenever you open your dropdown, the main select2 container will have the class select2-container--bootstrap4. It simply appends whatever you set for theme to select2-container--, which means we can add our own class within the config like so:

$('#example').select2({theme: 'bootstrap4 my-custom-class'});

and then whenever you open your dropdown, the main select2 container will have the class select2-container--bootstrap4 as well as the class my-custom-class.

Knowing this, you can create whatever styles you want in advance for your list items:

#select2-fam-results li:nth-child(1),
.select2-container.bg-red li {
  background-color: red;
}

#select2-fam-results li:nth-child(2),
.select2-container.bg-yellow li {
  background-color: yellow;
}

EDIT NOTE:

Notice how I also have added matching styles for your family's list element such as #select2-fam-results li:nth-child(1) and #select2-fam-results li:nth-child(2). Since you gave an id of fam on your Family <select> element, the dynamically-generated <ul> list will always have the id corresponding id select2-fam-results. You have to be a bit careful here since you are hardcoding the nth-child index, but if you can be reasonably sure how the ordering of the Family options will appear then you can safely do this.

END EDIT NOTE

Now all you need to do is update your theme dynamically when Family is selected. Let's modify productOptions so that it contains both your data and the theme that you want:

const productOptions = {
  dataitems1: {data: dataitems1, theme: 'bg-red'},
  dataitems2: {data: dataitems2, theme: 'bg-yellow'},
};

Now in your #fam change event, all you have to do is add that theme to your existing theme:

$('#fam').on('change', function() {
  /* ... */
  const options = productOptions[selected];

  // get the new products config (products config + data options + theme)
  const newProductsConfig = Object.assign({}, productsConfig, {
    data: options.data,
    theme: `${productsConfig.theme} ${options.theme}`,
  });
  /* ... */
});

This gives you the flexibility of changing the background color for your products depending on which family you select.

Note: In your productsConfig definition you would then also have to change data: dataitems2 to data: dataitems2.data or remove the line altogether since it is not actually being used.

Related