JSFiddle - React, Tailwind, and code Playground

by sykvel

HTML

Data:
<div class="inputs">
    <!-- ko foreach: computedData -->
    <div>
      <input data-bind="value: name, hasFocus: isSelected" />
      <input data-bind="value: f" />
      <hr/>
    </div>
    
    <!-- /ko -->
    <div>
      <input class="add-field" data-bind="hasFocus: blankLineIsSelected" tabindex=0 readonly/>      
    </div>    
</div>

Output:
<ul data-bind="foreach: computedData">
    <li data-bind="text: name"></li>
</ul>

Data:
<ul data-bind="foreach: data">
    <li data-bind="text: name"></li>
</ul>

CSS

.inputs {
  display: flex;  
  flex-direction: column;
}

.add-field {
    opacity: 0;
    z-index: -1;
    position: absolute;
}

JavaScript

function Item(id, name, isSelected = false) {
    this.id = ko.observable(id);
    this.name = ko.observable(name);
    this.f = ko.observable('');
    this.isEmpty = ko.computed(() => (!this.name() && !this.f()));
    this.isSelected = ko.observable(isSelected);
}

function ItemsViewModel() {
    var self = this;    
    
    self.blankLineIsSelected = ko.observable(false);

    self.data = ko.observableArray([
        new Item(1, "One description"),
        new Item(2, "Two description"),
        new Item(3, "Three description")]);

    self.computedData = ko.computed(function() {
    		self.data(ko.utils.arrayFilter(self.data(), i => !i.isEmpty()));
    		if(self.blankLineIsSelected())
        {
        	self.data().push(new Item(0, "", true));          
        }
        return self.data();
    });       
}


ko.applyBindings(new ItemsViewModel());