Preselect a value in a dropdown using knockout

2019-07-25 14:45发布

问题:

I have multiple 10 dropdowns to be displayed in the page. I am using knockout to build the page. Basically i have a collection of 'sites' obseravablearray. Inside 'site' array i have a collection of 'users' which is an observablearray. 'users' are displayed as dropdown. I need to preselect a value based inside the dropdowns. However it is not working. I am not able to see the selected value in the dropdown. Please let me know for any help. I would not hardcode any id value for the dropdown as the display of the dropdowns is dynamic.

Below is the sample code using knockout  (aspx)
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication6.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link href="Content/bootstrap.css" rel="stylesheet" />
    <script src="Scripts/jquery-3.0.0.js"></script>
    <script src="Scripts/bootstrap.js"></script>
    <script src="Scripts/knockout-3.4.0.js"></script>
    <script src="primarySetup.js"></script>
</head>
<body>
        <form id="frmPrimarySiteUser">
        <div class="container">
            <div class="row">
                <span>Setup </span>
            </div>
            <div class="row">
                <table class="table-bordered table-condensed table-hover table-responsive" id="tblEncode">
                    <thead>
                        <tr>
                            <th>Site Name</th>
                            <th>User Id</th>
                        </tr>
                    </thead>
                    <tbody data-bind="foreach: PrimarySiteUsers">
                        <tr>
                            <td><span data-bind="text: SiteName"></span></td>
                            <td><select name="ddlUsers" data-bind="options: UserParam, selected: 'SelectedUserId', optionsText: 'UserName', optionsValue: 'UserId', optionsCaption:'-Select-'"></select></td>
                        </tr>
                    </tbody>
                </table>
            </div>           
        </div>
    </form>
</body>
</html>

js file.

function PrimaryUserViewModel() {
    var self = this;

    self.PrimarySiteUsers = ko.observableArray([]);
    self.Users1 = ko.observableArray([]);
    self.Users2 = ko.observableArray([]);

    function addPrimarySiteUser(siteId, siteName, userParam) {
        return {
            SiteId: ko.observable(siteId),
            SiteName: ko.observable(siteName),             
            UserParam: ko.observable(userParam)
        }
    }

    function addUserDropDown(userId, userName, selectedValue) {
        return {            
            UserId: ko.observable(userId),
            UserName: ko.observable(userName),
            SelectedUserId: ko.observable(selectedValue)
        }
    }

    self.Users1().push(new addUserDropDown(1, 'jj', false));
    self.Users1().push(new addUserDropDown(2, 'jk', true));

    self.PrimarySiteUsers.push(new addPrimarySiteUser(1, 'site1', self.Users1()))

    self.Users2().push(new addUserDropDown(1, 'mj', true));
    self.Users2().push(new addUserDropDown(2, 'mk', false));

    self.PrimarySiteUsers.push(new addPrimarySiteUser(1, 'site1', self.Users2()))
}

$(document).ready(function () {
    var primaryUserModel = new PrimaryUserViewModel();
    ko.applyBindings(primaryUserModel);
})

回答1:

There's a lot of weird code in your example, so I'll start with the basics:

You can set selections in your viewmodel by:

  1. Create a list you want to render as options, and an observable to store the current selection

    var vm = {
      choices: [ 1, 2, 3],
      selection: ko.observable(2)
    };
    
  2. Bind the list to options and the observable to value in your <select> box:

    <select data-bind="options: choices, value: selection"></select>
    
  3. Write a value to selection that is also in the array bound to options:

    vm.selection(3); // Selects the last element of the dropdown
    vm.selection(vm.choices[1]) // Select 2
    

To get this to work in your code:

  • Add a value binding and selection observable
  • Store a reference to the prim vm so we can update the selected property
  • Loop up a user and their UserId to set a new selection

function PrimaryUserViewModel() {
  var self = this;

  self.PrimarySiteUsers = ko.observableArray([]);
  self.Users1 = ko.observableArray([]);
  self.Users2 = ko.observableArray([]);

  function addPrimarySiteUser(siteId, siteName, userParam) {
    return {
      SiteId: ko.observable(siteId),
      SiteName: ko.observable(siteName),
      UserParam: ko.observable(userParam),
      selection: ko.observable(null)
    }
  }

  function addUserDropDown(userId, userName, selectedValue) {
    return {
      UserId: ko.observable(userId),
      UserName: ko.observable(userName),
      SelectedUserId: ko.observable(selectedValue)
    }
  }

  self.Users1().push(new addUserDropDown(1, 'jj', false));
  self.Users1().push(new addUserDropDown(2, 'jk', true));

  var primUser1 = new addPrimarySiteUser(1, 'site1', self.Users1());
  self.PrimarySiteUsers.push(primUser1)
  
  // Select jk:
  // 1: find reference to user
  var jkUser = self.Users1()[1];
  // 2: get id (because of `optionsValue: 'UserId'`)
  var jkId = jkUser.UserId();
  // 3: write to selection
  primUser1.selection(jkId);

  self.Users2().push(new addUserDropDown(1, 'mj', true));
  self.Users2().push(new addUserDropDown(2, 'mk', false));

  self.PrimarySiteUsers.push(new addPrimarySiteUser(1, 'site1', self.Users2()))
}

var primaryUserModel = new PrimaryUserViewModel();
ko.applyBindings(primaryUserModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<form id="frmPrimarySiteUser">
  <div class="container">
    <div class="row">
      <span>Setup </span>
    </div>
    <div class="row">
      <table class="table-bordered table-condensed table-hover table-responsive" id="tblEncode">
        <thead>
          <tr>
            <th>Site Name</th>
            <th>User Id</th>
          </tr>
        </thead>
        <tbody data-bind="foreach: PrimarySiteUsers">
          <tr>
            <td><span data-bind="text: SiteName"></span></td>
            <td><select name="ddlUsers" data-bind="options: UserParam, value: selection, optionsText: 'UserName', optionsValue: 'UserId', optionsCaption:'-Select-'"></select></td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</form>

There are many weird things happening in your code that you should also fix:

  • Don't use new when it's not needed
  • Remove data-binds as selected that don't do anything
  • Restructure some of the data definitions and viewmodels
  • Use lowercase characters for properties' first letters and uppercase ones for constructors...


标签: knockout.js