voam
voam

Reputation: 1016

knockout dropdown

I am having trouble getting the selected item of a bound drop down list.

<p>
  Your Group: 
  <select data-bind="options: availableGroups, optionsText: 'Name', optionsValue: 'GroupId', value: selectedGroup, optionsCaption: 'Choose...'"></select>
</p>
<p>
  I am visible
  You have chosen <span data-bind="text: selectedGroup() ? selectedGroup().Name : 'Nothing'"></span>
</p>

When I choose something from the drop down list, I would like to get the text of the selection, not the value. I am very new to knockout and trying to get a handle on this. I've created a fiddle for this.

http://jsfiddle.net/voam/FjRxn/

Upvotes: 3

Views: 3319

Answers (6)

Nimesco
Nimesco

Reputation: 720

Personally I would use @pomber's answer, with a small edit.

self.selectedGroup = ko.computed(function(){
  return ko.utils.arrayFirst(self.availableGroups(), function(grp) {
    return grp.GroupId == self.selectedGroupId();
  }
}, this);

I don't like using for-loop in computed observables.

Fiddle

Upvotes: 0

Tim Yonker
Tim Yonker

Reputation: 403

The simplest solution would be to remove the optionsValue binding from your element. It will then store the whole object in the observable and you can get to all of your properties.

jsfiddle

<select data-bind="options: availableGroups, optionsText: 'Name',
value: selectedGroup, optionsCaption: 'Choose...'"></select>

Upvotes: 0

Jacob Seward
Jacob Seward

Reputation: 21

I just wanted to post a solution I've been using recently to solve this issue. It utilizes binding handlers (valueAppendText and textFromOption) and appends an observable to the observable being tracked by the drop down. This solution isn't complete, but demonstrates the idea of not using adding a computed to get the drop down text. This solution also utilizes jQuery, which could be removed, but since I use jQuery in my projects (mostly), I left it in. The jsFiddle link below demonstrates the functionality.

Fiddle: http://jsfiddle.net/FjRxn/65/

Markup:

<select data-bind="options: availableGroups, optionsText: 'Name', optionsValue: 'GroupId', valueAppendText: selectedGroup, optionsCaption: 'Choose...'"></select>

<p>
    I am visible
    You have chosen <span data-bind="textFromOption: selectedGroup"></span>
    <div>
        Group Id: <span data-bind="text: selectedGroup"></span>
    </div>
</p>

Binding Handlers:

ko.bindingHandlers.valueAppendText = {
    init: function(element, valueAccessor, allBindingsAccessor, context) {
      var $element, newValueAccessor, observable, setText;

      observable = valueAccessor();
      observable.selectedOptionText = ko.observable(null);
      newValueAccessor = function() {
        return observable;
      };
      $element = $(element);
      setText = function() {
        return observable.selectedOptionText($element.find("option:selected").text());
      };
      setTimeout(setText, 5);
      $element.change(function() {
        return setText();
      });
      return ko.bindingHandlers.value.init(element, newValueAccessor, allBindingsAccessor, context);
    },
    update: function(element, valueAccessor, allBindingsAccessor, context) {
      return ko.bindingHandlers.value.update(element, valueAccessor, allBindingsAccessor, context);
    }
  };

  ko.bindingHandlers.textFromOption = {
    update: function(element, valueAccessor, allBindingsAccessor, context) {
      var newValueAccessor, observable;

      observable = valueAccessor();
      newValueAccessor = function() {
        if (ko.isObservable(observable.selectedOptionText)) {
          return observable.selectedOptionText();
        }
        return observable();
      };
      return ko.bindingHandlers.text.update(element, newValueAccessor, allBindingsAccessor, context);
    }
  };

Upvotes: 2

DevelopmentIsMyPassion
DevelopmentIsMyPassion

Reputation: 3591

You can also use subscribe function on your observable selectedGroup. I have also created another observable as "selectedGroupId".

On subscribe event i assign value of GroupId to new observable "selectedGroupId"

 self.selectedGroup.subscribe(function(item)
     {
          debugger;
          self.selectedGroupId(item.GroupId);
          return item.Name;
      });

Please see updated Fiddle here

Upvotes: 0

Pete
Pete

Reputation: 6723

Change

<select data-bind="options: availableGroups, optionsText: 'Name', optionsValue: 'GroupId', value: selectedGroup, optionsCaption: 'Choose...'"></select>

To:

<select data-bind="options: availableGroups, optionsText: 'Name', value: selectedGroup, optionsCaption: 'Choose...'"></select>

Upvotes: 0

pomber
pomber

Reputation: 23980

For your original question @Pete's answer is right, but since you need to preserve GroupId as the value you could do this (modified fiddle).

First the selectedGroup property was renamed to selectedGroupId.

Then a new computed observable selectedGroup was defined based on the selectedGroupId:

self.selectedGroup = ko.computed(function () {
  for (var i = 0; i < groups.length; i++) {
    if (groups[i].GroupId == self.selectedGroupId())
      return groups[i];
  }
  return null;
});

Also the var self = this was defined

Upvotes: 2

Related Questions