using select2 with knockout

9,709 views
Skip to first unread message

maku

unread,
May 27, 2012, 11:07:24 AM5/27/12
to sel...@googlegroups.com
Hi,

I like this plugin. So I want to use it with knockout (http://knockoutjs.com/). 
Does anybody of you know if it is possible?
Would it be necessary to write a "custom binding"? (which would a little bit to advanced for me I guess...)


TIA
Martin

David Rosen

unread,
May 27, 2012, 6:14:37 PM5/27/12
to sel...@googlegroups.com

Hi Martin,

I'm using knockout with select2 in a site I'm building. The binding handler I'm using looks like this:

ko.bindingHandlers.select2 = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        $(element).select2(valueAccessor());

        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $(element).select2('destroy');
        });
    },
    update: function(element, valueAccessor, allBindingsAccessor) {
        var allBindings = allBindingsAccessor(),
            value = ko.utils.unwrapObservable(allBindings.value || allBindings.selectedOptions);
        if (value) {
            $(element).select2('val', value);
        }
    }
};

Here is a jsfiddle that shows it working.

Cheers,
Dave

David Rosen

unread,
May 27, 2012, 8:34:15 PM5/27/12
to sel...@googlegroups.com

I updated the jsfiddle to include an example with AJAX as well. It works, but there is an error logged to the console that I haven't quite figured out yet.

maku

unread,
May 28, 2012, 6:03:24 AM5/28/12
to select2
Hi Dave,

thank you very much. Works great...

The only thing that doesn't work for me was the height of the input
field when I'm using the base css (select2.css) ( I saw no input
field)
But fixing line 332 and set the height to e.g. 24 px (from 15px)
works.

Best regards,
Martin

On 28 Mai, 02:34, David Rosen <dros...@gmail.com> wrote:
> I updated the jsfiddle <http://jsfiddle.net/drosen/6XvqX/> to include an
> example with AJAX as well. It works, but there is an error logged to the
> console that I haven't quite figured out yet.
>
>
>
>
>
>
>
> On Sunday, May 27, 2012 3:14:37 PM UTC-7, David Rosen wrote:
>
> > Hi Martin,
>
> > I'm using knockout with select2 in a site I'm building. The binding
> > handler I'm using looks like this:
>
> > ko.bindingHandlers.select2 = {
> >>     init: function(element, valueAccessor, allBindingsAccessor) {
> >>         $(element).select2(valueAccessor());
>
> >>         ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
> >>             $(element).select2('destroy');
> >>         });
> >>     },
> >>     update: function(element, valueAccessor, allBindingsAccessor) {
> >>         var allBindings = allBindingsAccessor(),
> >>             value = ko.utils.unwrapObservable(allBindings.value ||
> >> allBindings.selectedOptions);
> >>         if (value) {
> >>             $(element).select2('val', value);
> >>         }
> >>     }
> >> };
>
> > Here is a jsfiddle <http://jsfiddle.net/drosen/6XvqX/> that shows it

David Rosen

unread,
May 28, 2012, 3:33:15 PM5/28/12
to sel...@googlegroups.com

Actually the "update" part of the binding handler is sort of a hack, and I believe select2 could be patched to make this more elegant. What the "update" part does is updates the value of the "select2" if the value of the underlying "select" or "input" control is changed outside of the "select2". The problem is that it also unnecessarily does this update if the "select2" is changed through normal interaction, which causes the tags in the multiple selection example to get sorted alphabetically, and there might be other side effects I'm not aware of.

I see two possible ways to fix this:

One way is to have select2 to listen for a change on the underlying control's value and update itself. This would eliminate the need for the "update" part of the binding handler, and is probably the most compatible with other frameworks.

The other way is to have a function of select2 that would trigger it to check for a change in the underlying control's value, but it would need to be debounced within select2.

Igor Vaynberg

unread,
May 28, 2012, 6:09:02 PM5/28/12
to sel...@googlegroups.com
On Mon, May 28, 2012 at 12:33 PM, David Rosen <dro...@gmail.com> wrote:
>
> Actually the "update" part of the binding handler is sort of a hack, and I
> believe select2 could be patched to make this more elegant. What the
> "update" part does is updates the value of the "select2" if the value of the
> underlying "select" or "input" control is changed outside of the "select2".
> The problem is that it also unnecessarily does this update if the "select2"
> is changed through normal interaction, which causes the tags in the multiple
> selection example to get sorted alphabetically, and there might be other
> side effects I'm not aware of.
>
> I see two possible ways to fix this:
>
> One way is to have select2 to listen for a change on the underlying
> control's value and update itself. This would eliminate the need for the
> "update" part of the binding handler, and is probably the most compatible
> with other frameworks.

select2 already does this, see

http://ivaynberg.github.com/select2/#event_ext_change

-igor
> --
> You received this message because you are subscribed to the Google Groups
> "select2" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/select2/-/bvlgHvxxLSQJ.
> To post to this group, send email to sel...@googlegroups.com.
> To unsubscribe from this group, send email to
> select2+u...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/select2?hl=en.

David Rosen

unread,
May 28, 2012, 7:17:31 PM5/28/12
to sel...@googlegroups.com

Perfect. I updated the jsfiddle (http://jsfiddle.net/drosen/6XvqX/) to call trigger('change') on update, which fixes the issue.


On Monday, May 28, 2012 3:09:02 PM UTC-7, Igor Vaynberg wrote:
> select2+unsubscribe@googlegroups.com.

chad...@gmail.com

unread,
Sep 19, 2012, 5:54:17 PM9/19/12
to sel...@googlegroups.com
This doesn't work correctly if you don't specify an optionsValue. See "Example 3: Drop-down list representing arbitrary JavaScript objects, not just strings" on the knockout documentation: http://knockoutjs.com/documentation/options-binding.html

The select2 box doesn't bind correctly to the underlying select and doesn't respond to model updates.

I'm not sure how to make this work in that context.
> > select2+u...@googlegroups.com.

David Rosen

unread,
Sep 26, 2012, 3:56:17 AM9/26/12
to sel...@googlegroups.com, chad...@gmail.com
I guess I avoided that scenario in my example, but it would be nice if it worked. I'll try to get it to work when/if I have some time. If you find a solution, please post it here.

fi...@filovo.net

unread,
Oct 10, 2012, 3:37:15 PM10/10/12
to sel...@googlegroups.com
This almost works for me - the only problem I'm currently facing is when I need to clear ajax-based selection from KO view model side (this.selectStateAjax(null)). Do you have any idea what should I add to the bindingHandler to support this scenario? My sample is here: http://jsfiddle.net/BDpLe/1/ (the "Clear" button).

Anyway thanks for the KO integration code.
> > select2+u...@googlegroups.com.

hyma...@gmail.com

unread,
Jan 18, 2013, 10:59:13 AM1/18/13
to sel...@googlegroups.com, chad...@gmail.com
Has anyone found a solution to this (drop-down list representing arbitrary JavaScript objects, not just strings)? I'm encountering the same issue.

anish...@unasys.com

unread,
Feb 19, 2014, 4:42:44 AM2/19/14
to sel...@googlegroups.com
Hi, I'd also like to know if anyone has a nice solution using arbitrary javascript objects instead of strings.

rcarl...@gmail.com

unread,
May 26, 2014, 3:39:51 PM5/26/14
to sel...@googlegroups.com
does any body could it make it work with an object and not with just strings? thanks

4vers...@gmail.com

unread,
Feb 27, 2015, 2:55:52 PM2/27/15
to sel...@googlegroups.com, martin....@gmail.com
In case there's createSearchChoice() to allow enter values not in data to be added, I'd add something like that to the binding to add new value to the data:


if ("value" in allBindings) {
// {begin code by AV}
var value = allBindings.value();
if (allBindings.select2.createSearchChoice) {
var selectedObj = ko.utils.arrayFirst(allBindings.select2.data, function(item) {
return item.id === value;
});
if (!selectedObj) {
selectedObj = {id: value, text: value};
allBindings.select2.data.unshift(selectedObj);
}
}
// {end code by AV}
if (allBindings.select2.multiple && value.constructor != Array) {

bruno.z...@gmail.com

unread,
Sep 21, 2015, 5:51:52 AM9/21/15
to select2, martin....@gmail.com
Yes, the right way it using a custom binder
Reply all
Reply to author
Forward
0 new messages