JSFiddle - React, Tailwind, and code Playground

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<script src="//rawgit.com/RobinHerbots/jquery.inputmask/3.x/dist/jquery.inputmask.bundle.js"></script>
<table class="table table-condensed table-hover table-striped table-bordered">
    <thead>
        <tr>
            <th>Name</th>
            <th>Phone</th>
            <th></th>
        </tr>
    </thead>
    <tbody data-bind="foreach:numbers">
        <tr>
            <td><span data-bind="text:name"></span>

            </td>
            <td><span data-bind="text:phone"></span>

            </td>
            <td class="form-group">
                <button class="btn btn-sm btnRemove btn-default" type="button" data-bind="click:$root.removeNumber"> <i class="fa fa-trash"></i>

                </button>
            </td>
        </tr>
    </tbody>
    <tfoot data-bind="with:newNumber">
        <tr>
            <td>
                <input type="text" class="input-sm form-control" data-bind="textInput:name" />
            </td>
            <td>
                <input type="text" class="input-sm form-control" data-mask="phone" data-bind="phoneTextInput:phone" />
            </td>
            <td>
                <button class="btn btn-sm btn-default" id="btnAdd" type="button" data-bind="click:$root.addNewNumber"><i class="fa fa-plus"></i>

                </button>
            </td>
        </tr>
    </tfoot>
</table>

<h2>Values</h2>

<p>Numbers: <span data-bind="text:numbersJson"></span>

</p>
<p>New Number: <span data-bind="text:newNumberJson"></span>

</p>

JavaScript

(function () {
    var PhoneNumber = function () {
        this.name = ko.observable();
        this.phone = ko.observable();
    };

    ko.bindingHandlers.phoneTextInput = {
        init: function (element, valueAccessor, allBindings, data, context) {
            ko.bindingHandlers.textInput.init(element, valueAccessor, allBindings, data, context);
            
            $(element).inputmask({
                mask: '(999)999-9999'
            });
        }
    }

    var vm = {
        newNumber: ko.observable(new PhoneNumber()),
        numbers: ko.observableArray([]),
    };

    console.log('vm', vm.numbers());

    vm.numbersJson = ko.computed(function () {
        return ko.toJSON(vm.numbers);
    });
    vm.newNumberJson = ko.computed(function () {
        return ko.toJSON(vm.newNumber);
    });

    //events
    vm.addNewNumber = function () {
        vm.numbers.push(vm.newNumber());
        vm.newNumber(new PhoneNumber());
    };

    vm.removeNumber = function (data) {
        vm.numbers.remove(data);
    };

    ko.applyBindings(vm);


    /*
  $(document).on('click', '#btnAdd', addNewNumber);
  $(document).on('click', '.btnRemove', removeNumber);
  */
})();