Igor Levashov
Igor Levashov

Reputation: 328

Getting selected value from dropdown list in Knockout.js

I am new to knockout, and have a problem getting a selected value from dropdown list. I tried to change value to 'selectedCity' and I am getting [Object object]. Thanks!

My HTML

<select data-bind="options: Cities, optionsText: 'CityNameRu', value: selectCity">
</select>

<span data-bind="text: selectedCity"></span>

Knockout

function CityModel(data) {
    var self = this;
    this.CityId = ko.observable(data.CityId);
    this.CityNameRu = ko.observable(data.CityNameRu);
    this.CityName = ko.observable(data.CityName);
}

function ViewModel() {
    var self = this;
    self.Cities = ko.observableArray([]);
    self.selectedCity = ko.observable();

    self.selectCity = function (city) {
        self.selectedCity(city.CityNameRu);
    };

    self.GetCities = function () {
        $.ajax({
            type: "GET",
            url: '/FetchCities',
            dataType: "json",
            success: function (data) {
                self.SuccessfullyRetrievedModelsFromAjax(data);

            },
            error: function (err) {
                alert(err.status + " : " + err.statusText);
            }
        });
    };

    this.SuccessfullyRetrievedModelsFromAjax = function (models) {
        ko.utils.arrayForEach(models, function (model) {
            self.Cities.push(new CityModel(model));
        });
    };

JSON response:

[{"CityId":1,"CityName":"philadelphia","CityNameRu":"Филадельфия"},{"CityId":2,"CityName":"new-york","CityNameRu":"Нью Йорк"}

Upvotes: 2

Views: 4441

Answers (2)

Jeroen
Jeroen

Reputation: 63729

Change a few things:

  • No need for a selectCity function, just bind value straight to the observable.
  • The span text is bound to an observable which holds a reference to a city, so the text will try to render that reference as well as it can by e.g. "Object object". Instead, execute the observable to get its value, and then choose which property to show as text.

    <span data-bind="text: !!selectedCity() ? selectedCity().CityNameRu : ''"></span>
    

Alternatively, you could utilize the with binding. Here's how:

var data = [{"CityId":1,"CityName":"philadelphia","CityNameRu":"Филадельфия"},{"CityId":2,"CityName":"new-york","CityNameRu":"Нью Йорк"}];

var $ = { ajax: function(opts) { opts.success(data); } };

function CityModel(data) {
  var self = this;
  this.CityId = ko.observable(data.CityId);
  this.CityNameRu = ko.observable(data.CityNameRu);
  this.CityName = ko.observable(data.CityName);
}

function ViewModel() {
  var self = this;
  
  self.Cities = ko.observableArray([]);
  self.selectedCity = ko.observable();

  self.GetCities = function() {
    $.ajax({
      success: function(data) {
        self.SuccessfullyRetrievedModelsFromAjax(data);
      }
    });
  };

  self.SuccessfullyRetrievedModelsFromAjax = function(models) {
    ko.utils.arrayForEach(models, function(model) {
      self.Cities.push(new CityModel(model));
    });
  };
  
  self.GetCities();
}

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>

<select data-bind="options: Cities, optionsText: 'CityNameRu', value: selectedCity">
</select>

<div data-bind="with: selectedCity">
  <span data-bind="text: CityId"></span> -
  <span data-bind="text: CityName"></span> -
  <span data-bind="text: CityNameRu"></span>
</div>

<hr>

Debug info: <pre data-bind="text: ko.toJSON($root, null, 2)"></pre>

Upvotes: 2

Michał
Michał

Reputation: 905

Set the whole city object as value for selectedCity. You can also add a computed observable for retrieving text.

function ViewModel() {
    var self = this;
    self.Cities = ko.observableArray([]);
    self.selectedCity = ko.observable();

    self.selectCity = function (city) {
        self.selectedCity(city);
    };

    self.selectedCityNameRu = ko.pureComputed(function () {
        var selectedCity = self.selectedCity();
        return selectedCity ? selectedCity.CityNameRu : '';
    }, self);

Then in your html bind to selectedCityNameRu

<span data-bind="text: selectedCityNameRu"></span>

Upvotes: 2

Related Questions