0

Hard to describe. Here is a snippet.

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

  $('[data-mask="phone"]').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);
  });

  ko.applyBindings(vm);


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

  function removeNumber() {
    var item = ko.dataFor(this);
    var remVal = _.reject(vm.Numbers(), function(el) {
      return el.name === item.name;
    });
    vm.Numbers(remVal);
  };

  $(document).on('click', '#btnAdd', addNewNumber);
  $(document).on('click', '.btnRemove', removeNumber);
})();
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet" />
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" />

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://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"> <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="textInput:phone" />
      </td>
      <td>
        <button class="btn btn-sm btn-default" id="btnAdd" type="button"><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>

Please note there is phone inputmask in place when DOM is ready. When we type in the Phone textbox, the input mask is effective.

But after the first record added into the array and the textbox is cleared, the input mask is lost.

Question: how can we keep the input mask on the textbox?

Blaise
  • 21,314
  • 28
  • 108
  • 169
  • 3
    Use a custom binding that you can data-bind to the phone input. It would be responsible for adding the mask. Using scripts that do something "onLoad" is almost always the wrong way to do it when using Knockout. – CrimsonChris Jun 02 '15 at 20:13
  • I'm getting "_ is not defined" in removeNumber. – Roy J Jun 02 '15 at 20:24
  • @RoyJ The OP is using underscoreJS. – CrimsonChris Jun 02 '15 at 20:25
  • O yes, it is underscoreJS. I forgot to reference but it appears SO knows what it is. – Blaise Jun 02 '15 at 20:27
  • @CrimsonChris, I think you points to the correct direction. Can you please clarify a bit more, or post a link to some example/article? – Blaise Jun 02 '15 at 20:29

1 Answers1

2

The easiest thing to do is to put mask-setting code in the addNewNumberroutine.

function setMask() {
    $('[data-mask="phone"]').inputmask({
        mask: '(999)999-9999'
    });
}

vm.addNewNumber = function () {
    vm.numbers.push(vm.newNumber());
    vm.newNumber(new PhoneNumber());
    setTimeout(setMask, 0);
};

I made a Fiddle. It would probably be better to do with a custom binding, but, as I said, this is easiest.

Now I've made a custom binding handler in another Fiddle. It saves on searching for elements to mask, because it knows what element it is on.

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'
        });
    }
}
Roy J
  • 42,522
  • 10
  • 78
  • 102