Search code examples
javascriptknockout.jsdata-bindingdurandaldurandal-2.0

Knockout.JS: Bind change event of select to another UI attribute


I'd like to make the following inputs visible only if the database property is selected (on Bootstrap change event). Is there an elegant and effective solution in Knockout JS to do it inside HTML and if not then what would be the JavaScript way?

<select id="db" class="form-control" data-bind="value: database, valueUpdate: 'change'">
    <option disabled selected> -- select an option -- </option>
    <option>MySQL database format</option>
    <option>PostgreSQL database format</option>
    <option>Other format</option>
</select>

<label>Address :</label>
<input type="text" class="form-control" id="address" data-bind="visible: database">
<label>Port :</label>
<input type="text" class="form-control" id="port">

I'm thinking about using something like data-bind="visible: typeof database != 'undefined'", but such expressions with trying to access database throw Uncaught ReferenceError: database is not defined. Approach with jQuery doesn't work either.


Solution

  • Store your options in an array and bind them to the select input via the options binding. To store the selected value, use (your existing) database observable. Based on that observable, you can show your form fields when the database observable has an selected option (or hide them, if not).

    also, use the optionsCaption binding to show a "please choose" option. otherwise, you need to manually deal with filtering that dummy option out.

    function viewModel(){
      this.databaseOptions = ko.observableArray(["MySQL database format", "PostgreSQL database format", "Other format"]);
      this.database = ko.observable();
    }
    
    ko.applyBindings(new viewModel());
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    <select id="db" class="form-control" data-bind="options: databaseOptions, optionsCaption: ' -- select an option -- ', value: database">
    
    </select>
    <hr />
    <div data-bind="if: database">
      <label>Address :</label>
      <input type="text" class="form-control" id="address" data-bind="visible: database">
      <label>Port :</label>
      <input type="text" class="form-control" id="port">
    </div>