Blaise
Blaise

Reputation: 22222

How to maintain the jquery inputmask when the DOM is updated?

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?

Upvotes: 0

Views: 2933

Answers (1)

Roy J
Roy J

Reputation: 43899

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'
        });
    }
}

Upvotes: 3

Related Questions