JSFiddle - React, Tailwind, and code Playground

by aman1981

HTML

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.16/css/dataTables.bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.16/js/jquery.dataTables.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.16/js/dataTables.bootstrap.min.js"></script>
<table class="table table-bordered">
  <thead class="mbhead">
    <tr class="mbrow">
      <th>Input</th>
      <th>First Name</th>
      <th>Last Name</th>
      <th>Separator</th>
      <th>Address</th>
    </tr>
  </thead>
  <tbody data-bind="foreach: items">
    <tr data-bind="css: { invalidRow: isInvalid }">
      <td id="tdName"><select class="form-control" data-bind="options: $parent.ddl, optionsText: 'firstName', value: selectedValue, optionsCaption: '--Select--',  attr: { name: 'Items[' + $index() + '].Name', id: 'Items[' + $index() + '].Name'}"> </select></td>
      <td data-bind="with: selectedValue">
        <span data-bind="text: firstName"></span>
      </td>
      <td data-bind="with: selectedValue">
        <span data-bind="text: lastName"></span>
      </td>
      <td>
        <select class="form-control" data-bind="value: selectedSeparator">
           <option value="">--Select--</option>
           <option value="#">#</option>
           <option value="@">@</option>          
         </select>
      </td>
      <td><span class="input-small" data-bind="text: computedValue()" /></td>
      <td>
        <input type="button" value="Remove Row" data-bind="click: $parent.removeRow" class="btn btn-danger"...

CSS

.invalidRow {
  background-color: #ffb8b5;
}

JavaScript

(function() {
  var ViewModel = function() {
    var self = this;

    //Empty Row
    self.items = ko.observableArray([]);
    self.ddl = ko.observableArray();

    self.addRow = function() {
      self.items.push(new Item());
    };

    self.removeRow = function(data) {
      self.items.remove(data);
    };
    
    self.Save = function(){
        for (i in self.items()) {
          if (typeof self.items()[i].selectedValue() == "undefined") {
            self.items()[i].isInvalid(true);
            alert("Select all dropdown")
          }
        }
		};
    
    
    self.GetData = function() {
      var c = '[{"FirstName":"Alex","LastName":"Sanders","Address":123},{"FirstName":"Sam","LastName":"Billings","Address":"Mahony Street"}]';
      var jsonResult = JSON.parse(c);
      for (key in jsonResult) {
        var item = {
          firstName: jsonResult[key].FirstName,
          lastName: jsonResult[key].LastName,
          address: jsonResult[key].Address
        };
        self.ddl.push(item);
      }

    }

  }

  var Item = function(fname, lname, address) {
    var self = this;
    self.selectedValue = ko.observable();
    self.selectedSeparator = ko.observable();
    self.firstName = ko.observable(fname);
    self.lastName = ko.observable(lname);
    self.isInvalid = ko.observable(false);
    self.computedValue = ko.computed(function() {
     
     // this works and selected dropdown value is populated in address field
      //return self.selectedSeparator();
     
     //this does not work
		 if (self.selectedValue()) {
       return self.selectedSeparator() + ',' + self.selectedValue().firstName;
			 } else {
			 return null;
			 }
    });
  };

  vm = new ViewModel()
  ko.applyBindings(vm);

})();