select2 icon indicating copy to clipboard operation
select2 copied to clipboard

Select2 triggering event don’t loading additional data

Open evandroph opened this issue 2 years ago • 10 comments

I’m trying to load some important data on my select (select2) that will be used in other parts of the page in the future, but the Triggering Event is not loading the additional data. The code and results are shown below. If anyone has any suggestions, I’d be grateful.

$('#id_cc1').select2();
var data = {
	id: 1,
	text: 'text_default',
	text2: 'text_2',
	text3: 'text_3'
};
var newOption = new Option(data.text, data.id, true, true);
$('#id_cc1').append(newOption).trigger('change'); //until this point, everything works
$('#id_cc1').trigger({
	type: 'select2:select',
	params: {
		data: data
	}
});
console.log($('#id_cc1').select2('data')[0]['text']);// return text_default
console.log($('#id_cc1').select2('data')[0]['text2']);// return undefined

I believe the second ‘console.log’ should return: ‘text_2’.

evandroph avatar Mar 14 '22 01:03 evandroph

Hey @evandroph , I believe the data format you are entering is not correct. https://select2.org/data-sources/formats

var data = [ 
{
	id: 1,
	text: 'text_default'
},
{
        id: 2,
	text2: 'text_2'
},
{
        id: 3,
	text3: 'text_3'
}];

luiseugenio avatar Apr 25 '22 11:04 luiseugenio

Hi @luiseugenio . Just like @evandroph , exactly same scenerio, I wanted to manually set the data in select2 (refer to this https://select2.org/programmatic-control/add-select-clear-items#preselecting-options-in-an-remotely-sourced-ajax-select2) and the problem lies that it can't output any additional data. There must be a way/method to populate an additional data.

phantomGaming1 avatar Apr 27 '22 05:04 phantomGaming1

Hi @luiseugenio . Just like @evandroph , exactly same scenerio, I wanted to manually set the data in select2 (refer to this https://select2.org/programmatic-control/add-select-clear-items#preselecting-options-in-an-remotely-sourced-ajax-select2) and the problem lies that it can't output any additional data. There must be a way/method to populate an additional data.

@phantomGaming1 Is your scenario the same? I can using exactly the same code from the link you showed. Here is a code snippet from my stimulujs controller.

bindEvents() {
    var controller = this
    this.select2.on('select2:select', function (e) {
      var data = e.params.data
      if (data.newTag) {
        controller.createSite(data)
      }
    })
  }

createSite(data) {
    var controller = this

    $.ajax({
      url: controller.data.get('url-create'),
      dataType: "json",
      type: 'POST',
      data: {
        'sites[]': {'url': data.text}
      },
      error: function (xhr) {
        let error = xhr.responseJSON.errors.map(function(error) {
          return `URL ${error.url.join(', ')}`
        })
        noty({ text: error })
        controller.select2.val(null).trigger('change') // clear selected option
      },
      success: function (response) {
        let site = response[0]
        var newSiteOption = new Option(site.url, site.id, true, true)
        controller.select2.append(newSiteOption).trigger('change')
      },
      complete: function() {
        data.newTag = false
      }
    })
  }

Take a look at the success: there I add a new option and I get it selected.

luiseugenio avatar Apr 27 '22 10:04 luiseugenio

@luiseugenio the format is correct, but I tried with the format showed on the documentations and the problem persist:

$('#section').select2();
		var data = [
			{
				id: 1,
				text: 'text1_default',
				anothertext: 'text_1'
			},
			{
				id: 2,
				text: 'text2_default',
				anothertext: 'text_2'
			}
		];
		var newOption = new Option(data[0].text, data[0].id, true, true);
		$('#section').append(newOption).trigger('change'); //until this point, everything works
		newOption = new Option(data[1].text, data[1].id, true, true);
		$('#section').append(newOption).trigger('change'); //until this point, everything works*/
		$('#section').trigger({
			type: 'select2:select',
			params: {
				data: data
			}
		});
		console.log($('#section').select2('data')[0]);// return object: OK
		console.log($('#section').select2('data')[0]['id']);// return text1_default: OK
		console.log($('#section').select2('data')[0]['anothertext']);// return undefined: FAIL

I even tried it in several different ways.

var data[] = { id: 1, text: 'text1_default', anothertext: 'text_1' }; var data = [{ id: 1, text: 'text1_default', anothertext: 'text_1' }]; var data = [{ "id": 1, "text": "text1_default", "anothertext": "text_1" }];

evandroph avatar Apr 27 '22 11:04 evandroph

Hi @luiseugenio . Just like @evandroph , exactly same scenerio, I wanted to manually set the data in select2 (refer to this https://select2.org/programmatic-control/add-select-clear-items#preselecting-options-in-an-remotely-sourced-ajax-select2) and the problem lies that it can't output any additional data. There must be a way/method to populate an additional data.

@phantomGaming1 Is your scenario the same? I can using exactly the same code from the link you showed. Here is a code snippet from my stimulujs controller.

bindEvents() {
    var controller = this
    this.select2.on('select2:select', function (e) {
      var data = e.params.data
      if (data.newTag) {
        controller.createSite(data)
      }
    })
  }

createSite(data) {
    var controller = this

    $.ajax({
      url: controller.data.get('url-create'),
      dataType: "json",
      type: 'POST',
      data: {
        'sites[]': {'url': data.text}
      },
      error: function (xhr) {
        let error = xhr.responseJSON.errors.map(function(error) {
          return `URL ${error.url.join(', ')}`
        })
        noty({ text: error })
        controller.select2.val(null).trigger('change') // clear selected option
      },
      success: function (response) {
        let site = response[0]
        var newSiteOption = new Option(site.url, site.id, true, true)
        controller.select2.append(newSiteOption).trigger('change')
      },
      complete: function() {
        data.newTag = false
      }
    })
  }

Take a look at the success: there I add a new option and I get it selected.

In your case, data.ID and data.TEXT returns OK. On my code, too! But if you need returns more data (in my case: anothertext key) select2 don't load this data, only ID and TEXT

evandroph avatar Apr 27 '22 12:04 evandroph

@luiseugenio the format is correct, but I tried with the format showed on the documentations and the problem persist:

But @evandroph @phantomGaming1 nowhere in the documentation (https://select2.org/data-sources/formats) is there this pattern you need:

var data = [
			{
				id: 1,
				text: 'text1_default',
				anothertext: 'text_1'
			},
			{
				id: 2,
				text: 'text2_default',
				anothertext: 'text_2'
			}
		];

There is no such anothertext. For that you would need to add data-attributes (https://select2.org/configuration/data-attributes). So you can get the selected object and get the data attribute from it. Make sense?

luiseugenio avatar Apr 27 '22 12:04 luiseugenio

Hello guys. Good Morning. I create simple visual representation and a source code here: https://gist.github.com/phantomGaming1/31bde03725f2aa14d0695c741f08b7e9

select2_asd

For what I'm trying to do is first click the edit and second is get the additional data that is given in selec2 data (Please see the code for the further info).

Then about in this code: this actually working as intended and passed all additional data in params and access it. But it only works on event and not really store any data on it.

$('#id_cc1').trigger({
	type: 'select2:select',
	params: {
		data: data
	}
});

The docs said that: Notice that we manually trigger the select2:select event and pass along the entire data object. This allows other handlers to access additional properties of the selected item.

But I think the main problem is using the code $('#id_cc1').select2('data')[0]['text2'] or just $('#id_cc1').select2('data') itself when I'm manually preselecting data on remotely-sourced select2. But the code works just fine when using on remote data.

I think the best alternative solution is to have a global variable or the solution sir @luiseugenio provided. Thank you sir @luiseugenio for the replies I think this probably solve my issue.

phantomGaming1 avatar Apr 28 '22 01:04 phantomGaming1

I ran into this same problem which drove me a bit crazy until I found this issue report. (I should note that I'm using the current release version 4.0.13, NOT the 4.1.0-rc.0 version.). My problem arose from needing to set up an initial value with extra data, and using AJAX when the user tries to find a different value -- the extra data was showing up on any selection from AJAX, but not on the initial selection, even if AJAX had been used to change selection, then used again to change back to the initial selection.

The docs on the https://select2.org/data-sources/formats page explicitly state you can have additional parameters on data objects passed in (bold formatting mine):

Select2 requires that each object contain an id and a text property. Additional parameters passed in with data objects will be included on the data objects that Select2 exposes.

...as well as shown in a number of examples elsewhere in the docs.

After trying to set the values both through specifying the data with the select2 options, and via the trigger method described in https://select2.org/programmatic-control/add-select-clear-items#preselecting-options-in-an-remotely-sourced-ajax-select2 I was stumped. The only way it appeared the extra parameters were stored was through an AJAX request triggered by the select2 control itself via it's 'ajax' option, which meant they couldn't be used on an initially selected value.

I couldn't use the solution provided by @luiseugenio directly, because I'm using the kartik-v/yii2-widget-select2 wrapper around select2 itself and all the other options are built dynamically using the select2 AJAX requests for searching, which makes it very hard to add data attributes to the appropriate OPTION tags. Instead, I'm adding data attributes for the initial value and my needed extra data to the SELECT tag itself during initialization roughly like so:

$('myselect').data('initval', 123);
$('myselect').data('initattribute', 'my extra data corresponding to the initial 123 value here'); 

...then, in my select2:select handler (and several other places where it needs the data), I have a snippet roughly like so to actually retrieve my extra data:

selData = $(this).select2('data');
if (selData[0].myattribute) {
    myattr = selData[0].myattribute;
} else if ($(this).data('initval') == $(this).val()) {
    myattr = $(this).data('initattribute');
}

The check against initval is needed because sometimes when an ajax request for more options returns the original value and the user selects it again, select2 simply reuses the original option tag which doesn't have the extra parameters in it even though they were returned by the Ajax call.

steve962 avatar Mar 09 '23 14:03 steve962

hello same issue even with 4.1.0-rc.0 it's a great problem for us... do you have an idea how to fix it ? thank's

guen

guenlm avatar Jun 15 '23 12:06 guenlm