Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ajax remote data : outdated text displayed on re-selection #5391

Closed
mrp14 opened this issue Oct 9, 2018 · 18 comments · May be fixed by #6282
Closed

Ajax remote data : outdated text displayed on re-selection #5391

mrp14 opened this issue Oct 9, 2018 · 18 comments · May be fixed by #6282

Comments

@mrp14
Copy link

mrp14 commented Oct 9, 2018

Hello,

I have a select2 element with an ajax datasource. If a user selects a value, then deselects it and finally reselects it, while text has changed server-side for the same id, the old version of text is displayed instead of the new one.

I've been able to get around it by deleting options at selection, but of course this is not appropriate if select2 allows multiple selection (previous selected elements will be deleted too) :

if (!is_multiple) {
    $select2_element.on('select2:selecting', function (event) {
        $select.find('option').remove();
    });
}

Is there a way to disable or get around this caching behavior ? Or, at least, can I refresh by myself options after ajax response ?

Here is the classical select2 config :

var select2Config = {
    ajax: {
        url: ...,
        data: function (params) {
            return {...};
        },
        dataType: 'json',
        delay: 250,
        processResults: function (data) {...},
        cache: true
    },
    escapeMarkup: function (markup) {...},
    placeholder: '',
    width: 205,
    language: cur_locale
    multiple : true
};
@mrp14 mrp14 changed the title Ajax remote data : outdated text displayed Ajax remote data : outdated text displayed on re-selection Oct 9, 2018
@stale
Copy link

stale bot commented Mar 13, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the status: stale label Mar 13, 2019
@stale stale bot closed this as completed Mar 20, 2019
@jayaddison
Copy link
Contributor

Hi @mrp14 - I think that this is because select2 creates and stores an HTML <option> element and its associated metadata (value, ID) when an AJAX result is selected by the user.

That <option> element remains in the HTML DOM, even if the user removes/clears the corresponding item from the select2 control.

I encountered something very similar in openculinary/frontend#239 and was able to develop a small workaround - openculinary/frontend@53fa276 (the commit description is longer than the code change).

I'm not sure what the expected behaviour should be here. AJAX datasources are probably a bit unusual; in many cases the list of <option> elements will be declared statically at page-load-time. And that's not to mention dynamic user-entered tags.

@mrp14
Copy link
Author

mrp14 commented Oct 17, 2023

Hello,

IMHO the expected behavior should be that no remote data get cached at all by the component.
To resolve this, a simple solution would be that when a user deselects an option while an ajax datasource is configured, this option should be deleted from DOM and select 2 memory. Or, even more simply, to clear all unselected options at the moment remote data is queried/retrieved/rendered.

AJAX datasources are not so unusual, especially in enterprise management applications. Personally, when I'm looking for an autocomplete/multiselect/dropdown/call it what you want component like select2, the ability to work with remote data is absolutely mandatory.

I don't really work with jQuery anymore, but from what I remember I ended up using other alternatives, select2 feeling a bit clunky on several aspects.

@jayaddison
Copy link
Contributor

AJAX datasources are not so unusual, especially in entreprise management applications. Personnally, when I'm looking for an autocomplete/multiselect/dropdown/call it what you want component like select2, the ability to work with remote data is absolutely mandatory.

That seems reasonable @mrp14 - I've drafted a possible approach that would resolve this in #6282. It feels like there could be edge cases here though.

For example: is it valid for a select2 element with an AJAX datasource to also have a few statically-declared <option> values in the HTML page (before any AJAX requests occur)? If so, we wouldn't want to remove those -- but I don't know how we would differentiate them.

@mrp14
Copy link
Author

mrp14 commented Oct 18, 2023

For example: is it valid for a select2 element with an AJAX datasource to also have a few statically-declared values in the HTML page (before any AJAX requests occur)? If so, we wouldn't want to remove those -- but I don't know how we would differentiate them.

I don't think this is a problem to prevent developers from mixing both local and remote data. If anyone ever needs "hard-coded" values, they can include them in the response from their custom data source, integrating them with data from the database (or other sources).

@jayaddison
Copy link
Contributor

Ok. I think what you say is true, however I'd like to make sure we consider as many possible edge cases as we can. Another few that occur:

  • Cases where the page would like to have some items pre-selected and/or inactive (<option selected="true"> and <option disabled>).
  • Backwards compatibility - could removing options during unselect unexpectedly break common usage patterns? (if so we should increase the communication level about the change)

@jayaddison
Copy link
Contributor

(I'm drafing a test HTML page to explore some of these possibilities at the moment. unit/integration test coverage is helpful, but sometimes it's helpful to use practical testing too)

@jayaddison
Copy link
Contributor

Also: tagging could be another area to check for unexpected interactions with the proposed changes in #6282.

@jayaddison
Copy link
Contributor

Tagging, pre-selected=true items and single-select (non-multiple) behaviour seems OK based on my testing so far. I haven't yet checked inactive item behaviour.

Also I've discovered a regression -- pressing the enter/return key in a multiselect seems to remove the last entry in a multiselect. I'm not sure yet whether that's a result of my changes or other commits since 4.0.13 - I'm tracking that down next.

@jayaddison
Copy link
Contributor

@kevin-brown I've found what I think is a regression in 181170f related to a multiple select; the <button> element of the last item entered seems to become the default target for the enter/return key in Firefox 115.3 - I'll file a bug for this soon.

@jayaddison
Copy link
Contributor

@kevin-brown apologies: after attempting to write a minimal repro, I discovered that the problem is not in select2: it's due to an insufficiently constrained JQuery selector that was initiating clicks on the clear button during an enter keypress handler.

@kevin-brown
Copy link
Member

@kevin-brown apologies: after attempting to write a minimal repro, I discovered that the problem is not in select2: it's due to an insufficiently constrained JQuery selector that was initiating clicks on the clear button during an enter keypress handler.

I was excited for a new hard to solve bug! But I'm glad to hear you were able to solve it outside of Select2 and that it wasn't actually a bug.

@mrp14
Copy link
Author

mrp14 commented Oct 18, 2023

Also: tagging could be another area to check for unexpected interactions with the proposed changes in #6282.

You're right, "tagging" requires appropriate attention in this discussion.

I don't think that deleting deselected custom options would pose a problem, as they are no longer relevant.
In the context of using remote data, if the developer wants the custom options to be persisted as soon as the user inputs them, he would use the createTag option to achieve it. As a result, newly created options would be available in future datasource requests.

However, perhaps you could introduce one or multiple configuration options to allow developers to handle these scenarios as they want to.

By the way, two points of my own :

  • The createTag option should allow developers to provide option data to Select2 asynchronously. This could be achieved by accepting a callback function that the developer would invoke upon completion, or even better, by allowing the return of a promise.
  • I believe "tagging" is kinda misnamed. Its only function is to allow the creation of custom options. Therefore, the tag option might be better named allowCustom or allowCreateOption, aligning with options like allowClear, for instance.

@jayaddison
Copy link
Contributor

Mostly agreed. I think the naming of tags is probably a historic artifact of the fact that multiple was already well-known as a property of HTML select elements, while tags were seen as a dynamic, user-content, Web 2.0 kind of thing.

One nitpick though:

The createTag option should allow developers to provide option data to Select2 asynchronously. This could be achieved by accepting a callback function that the developer would invoke upon completion, or even better, by allowing the return of a promise.

That seems like a feature request, so it's probably worth opening separately?

@mrp14
Copy link
Author

mrp14 commented Oct 19, 2023

That seems like a feature request, so it's probably worth opening separately?

That would totally be a feature request, I just felt it was missing when I was looking at the createTag documentation. I'm not using Select2 anymore, and I'm not committed to maintaining it or pushing for its evolution. However, since you seem to be involved in its development, I wanted to share my little thoughts with you. Do with them as you see fit :)

@jayaddison
Copy link
Contributor

@mrp14 it's possible we should move this discussion to a separate issue thread, but: how would the suggested functionality differ from the existing callback parameter on createTag? (it's invoked after the user enters a fragment of text -- the tag/custom item text -- and allows the application to customize the metadata (id, text, and any additional properties the application wants to store).

@jayaddison
Copy link
Contributor

One more edge case to consider: grouped data is valid for AJAX datasources.

If we're removing empty <option> elements during unselection, we may also need to clean up related group-level resources (specifically in the case of the unselection of the last item within a group).

@mrp14
Copy link
Author

mrp14 commented Oct 23, 2023

@mrp14 it's possible we should move this discussion to a separate issue thread, but: how would the suggested functionality differ from the existing callback parameter on createTag? (it's invoked after the user enters a fragment of text -- the tag/custom item text -- and allows the application to customize the metadata (id, text, and any additional properties the application wants to store).

The idea would be that the developer could provide to select2 the built tag object asynchronously, which would allow the developer to make an API call and create it server side for example.

It would allow to compute the tag object and its metadata server side, while doing whatever needed at the same moment (i.e. persist the "tag" in database).

An example code :

$('select').select2({
	createTag: function(params, success_callback) {
		var term = $.trim(params.term);

		if (term === '') {
			success_callback(null);
			return;
		}


		$.ajax({
			type: 'post',
			url: '/api/create-tag',
			data: {
				"tag-text": term
			},
			dataType: 'json',
			success: function(response) {
				//response is null or a valid select2 tag object with id, text and whatever needed metadata
				success_callback(response);
			},
			error: function() {
				success_callback(null);
			}
		});
	}
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants