简体   繁体   中英

How to populate select options with unique data and return a value as selected item?

I have a data object passed to an observableArray that looks like this:

self.Players = ko.observableArray([{

    "LastName": "Jordan",
        "FirstName": "Michael",
        "Team": "Chicago Bulls",
        "Jersey": "23"
}, {
    "LastName": "Duncan",
        "FirstName": "Tim",
        "Team": "San-Antonio Spurs",
        "Jersey": "21"
}, {
    "LastName": "Duncan",
        "FirstName": "Tim",
        "Team": "San-Antonio Spurs",
        "Jersey": "21"
}, {
    "LastName": "Jordan",
        "FirstName": "Michael",
        "Team": "Chicago Bulls",
        "Jersey": "23"
}
    ]);

I need to populate a Select Options with the unique First and Last Name of each player while also passing the Jersey value as Selected value. The data can have duplicates.

So each time a player is selected, I need the Jersey number passed to:

self.SelectedPlayer = ko.observable('');

I attempted to do something like this:

self.UniquePlayers = ko.computed(function () {
       var uniquePlayers = ko.utils.arrayMap(self.Players(),

           function (data) {
               return data.FirstName + ' ' + data.LastName
           });

       return ko.utils.arrayGetDistinctValues(uniquePlayers).sort();
   });

This works, except I do not get the Jersey as it is not returned.

I also tried returning the data object:

           function (data) {
               return data
           });

This allows me to specify the optionsValue and optionsText .

  <select class="form-control" 
  data-bind="options: UniquePlayers,
             optionsText: function(item){return item.FirstName + ' ' + item.LastName},
             optionsValue: 'Jersey',
  value: SelectedPlayer"></select>

But I do not get unique values and I am not able to access the optionsValue :

self.SelectedPlayer().Jersey;

How so I display the unique player first and last name and also get the jersey as optionsValue?

Writing anonymous functions in viewmodel isn't the best idea, also I think you complicated your code too much, I don't think you really need ko.computed in this case, anyway, why don't you go for something like:

function (data) {
    var obj = data;
    obj.fullName = data.FirstName + ' ' + data.LastName;
    return obj;
});

If you would create a jsfiddle demo it would easier to play with.

You can't use ko.utils.arrayGetDistinctValues() for an array that contains objects. This function works on primitive values only, objects on the other hand can have identical properties without being identical themselves.

Use something like this:

self.UniquePlayers = ko.computed(function () {
    var uniquePlayers = [], index = {};

    ko.utils.arrayForEach(self.Players(), function (p) {
        var fullName = p.FirstName + ' ' + p.LastName;
        if ( !(fullName in index) ) {
            uniquePlayers.push({text: fullName, player: p});
            index[fullName] = true;
        }
    });

    return uniquePlayers.sort();
});

and

<select class="form-control" data-bind="
    options: UniquePlayers,
    optionsText: 'fullName',
    optionsValue: 'player',
    value: SelectedPlayer
"></select>

Of course it would be sensible to precalculate the fullName values once and store then in the player objects during viewmodel init.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM