harvesthq / chosen

Deprecated - Chosen is a library for making long, unwieldy select boxes more friendly.
http://harvesthq.github.io/chosen/
Other
21.85k stars 4.1k forks source link

allow_single_deselect is not working if empty option is added after initialization #1835

Open JirkaChadima opened 10 years ago

JirkaChadima commented 10 years ago

allow_single_deselect option works perfectly as documented. Sadly, when using a dynamic select, this option seems to not work. I skimmed through changes in master and it looks like that this has not yet been addressed since the latest release which I used for testing.

Test fiddle

http://jsfiddle.net/t3E7p/3/ using chosen 1.1.0

Seen on

Expected behaviour

When I dynamically add an empty option to the beginning of the select and trigger chosen:updated, the little grey cross should show up and I should be able to deselect any selected option.

tjschuck commented 10 years ago

Why are you dynamically adding the empty option? If you just include the option in your original markup, it works fine:

<select id="chosen">
    <option></option>
    <option value="2">example</option>
    <option value="3">example 2</option>
</select>

You can then dynamically add other options to your heart's content and trigger chosen:updated, and it will work fine.

Not sure I'm seeing the use case here. Will reopen if more info is provided.

JirkaChadima commented 10 years ago

Well, I guess it really is specific, I'll try to describe it, maybe I am just missing something. The numeric value represents server-generated record ID. The text itself represents a name assigned to that ID. An empty name is a valid case (don't ask me why, not my idea), but it has to have a numeric ID (again, not a constraint controlled by me). The full list of names is not known beforehand and is editable by a user with some AJAX UI on the same page as the chosen-enhanced select is.

If an empty name is not in a list, it is not available in the original select (therefore allow_single_deselect does not apply during init phase). It should however start working once the user inserts an empty name, server generates an ID for it and options are updated.

tjschuck commented 10 years ago

There have been a lot of somewhat similar issues opened before, and most of them have been solved in one way or another. Consider looking through them for a possible solution: https://github.com/harvesthq/chosen/search?q=allow_single_deselect&type=Issues

Reopening this as bug-ish behavior, but @harvesthq/chosen-developers might have other opinions.

JirkaChadima commented 10 years ago

I think the two most related issues are #1780 and #1809.

1780 was supposedly resolved by adding an empty option before chosen init. Fair enough.

1809 was closed as unable to be replicated. I was fiddling with it a bit and in my opinion it really does not work well. Chosen keeps the information about an empty option even when you do not reappend it. Run the following snippet on chosen demo page. You are then still able to click the grey cross and visually deselect the value, but in the underlying select there is no empty option! That's inconsistent at least.

$('.chosen-select-deselect').empty();
$('.chosen-select-deselect').append($("<option/>", {
        value: "1",
        text: "1"
    }));
$('.chosen-select-deselect').trigger("chosen:updated");

I think chosen:updated event should always reflect the actual presence of an empty option, the initial state is simply not enough. I have prepared another jsfiddle showing the inconsistency: http://jsfiddle.net/RA8ej/2/. Eventhough the final DOM state of both selects is the same, chosen behaviour differs each time.

Aymkdn commented 10 years ago

I agree with @JirkaChadima :+1:

pavdro commented 10 years ago

+1 Looks like triggering chosen:update doesn't work fully with deselect function.

kkoster commented 10 years ago

+1 A case in point of using dynamically added/removed options is when you are integrating chosen with two way binding frameworks, specifically Angular. I am using angular-chosen and am having fits around the addition/removal of the empty option both by angular and by myself. We have a filtering framework that, for some users, requires that an item from the drop down be selected and others does not. The existence of the empty option is conditional with respect to the particular users credentials. This may happen at any time in the app since CS representatives may alias an external user's credentials to aid them in use of the site.

smerchek commented 10 years ago

We encountered this bug after a recent update to chosen 1.0. In pre-1.0 versions, dynamically adding options with a binding framework like knockoutjs or angular worked just fine.

So, :+1:

stof commented 10 years ago

@smerchek make sure your angular/knockout integration with chosen is updated properly. In pre-1.0, the event to trigger was listz:updated. In 1.0, we changed to chosen:updated

smerchek commented 10 years ago

@stof Yes, we previously encountered that and are currently using chosen:updated. This is still a problem, despite that.

bpabel commented 9 years ago

I would also like to see this implemented. The use case is having a lot of dynamically populated selects. Having it update on chosen:updated would be great.

brianjn commented 9 years ago

+1 I agree that chosen:updated should handle this. If you dynamically remove the empty option, the deselect button is still visible even after triggering chosen:updated. Then if you deselect, it visually appears to be deselected, but the underlying select actually has the first option selected.

plindelauf commented 8 years ago

Any update on this issue? We're seeing the same problem and would really like to see it solved...

ganesh104012 commented 8 years ago

My Code was

<select data-placeholder="All Cities" class="chosen" name="mycity">
<option value="">All Cities</option>
<option value="1">chennai</option>
<option value="2">mumbai</option>
</select>

(function($){
    $('[name="mycity"]').chosen({placeholder_text_single: "All Cities",allow_single_deselect: true,width: '100%'}).change( function(){
    //some code
    });
})(jQuery);

I replaced it with

<select data-placeholder="All Cities" class="chosen" name="mycity">
<option value=""></option><!--Removed Empty Option TEXT-->
<option value="1">chennai</option>
<option value="2">mumbai</option>
</select>

(function($){
    $('[name="mycity"]').chosen({placeholder_text_single: "All Cities",allow_single_deselect: true,width: '100%'}).change( function(){
    //some code
    });
})(jQuery);

then it worked fine!