joc
joc

Reputation: 1466

not allow duplicates in a pureComputed element

Having this element (note the computed field) fullNumber

var NumberField = function () {
  var self = this;
  self.maskFormat = "0";
  self.firstNumber = ko.observable("");
  self.secondNumber = ko.observable("");
  self.thirdNumber = ko.observable("");
  self.fourthNumber = ko.observable("");
  self.fifthNumber = ko.observable("");

  self.fullNumber = ko.pureComputed(function() {
    return [
      self.firstNumber,
      self.secondNumber,
      self.thirdNumber,
      self.fourthNumber,
      self.fifthNumber ].map(ko.unwrap);
  }
}

Then I use it like:

<div class="numberFields" data-bind="with: numbers">

  <input id="0" class="number-ball" maxlength="2" type="tel" data-bind="twoDigits: firstNumber, maxNumber: 68">
  <input id="1" class="number-ball" maxlength="2" type="tel" data-bind="twoDigits: secondNumber, maxNumber: 68">
  <input id="2" class="number-ball" maxlength="2" type="tel" data-bind="twoDigits: thirdNumber, maxNumber: 68">
  <input id="3" class="number-ball" maxlength="2" type="tel" data-bind="twoDigits: fourthNumber, maxNumber: 68">
  <input id="4" class="number-ball" maxlength="2" type="tel" data-bind="twoDigits: fifthNumber, maxNumber: 68">

</div>

How can I ensure there are no duplicated values in fullNumber?

Upvotes: 1

Views: 53

Answers (1)

user3297291
user3297291

Reputation: 23372

In your computed you can chain all kinds of functions that map over your numbers. Essentially, you're doing three things:

  1. Move from observable to Number by calling ko.unwrap,
  2. Check if the unwrapped value already exists, i.e.: filter uniques
  3. Make sure there are no ugly null or undefined values in your array that could result from empty inputs

In plain javascript, but with some "modern" features (Array.from, Set):

var uniques = function(arr) {
   // There are many implementations of a unique method.
   // google/search for `unique js values` to learn more
   return Array.from(new Set(arr));
};

var arrUnwrap = function(arr) {
  return arr.map(ko.unwrap);
};

var truethyValues = function(arr) {
  return arr.filter(function(val) {
    return val;
  });
};

var NumberField = function () {
  var self = this;
  self.maskFormat = "0";
  self.firstNumber = ko.observable("");
  self.secondNumber = ko.observable("");
  self.thirdNumber = ko.observable("");
  self.fourthNumber = ko.observable("");
  self.fifthNumber = ko.observable("");
  
  var numbers = [
      self.firstNumber,
      self.secondNumber,
      self.thirdNumber,
      self.fourthNumber,
      self.fifthNumber ];
  
  
  // Read from right to left: 
  //  fullNumber is: unwrapped, unique, truethy numbers
  self.fullNumber = ko.pureComputed(function() {
    return truethyValues(uniques(arrUnwrap(numbers)));
  });
}
                                    
ko.applyBindings(new NumberField());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<div>
  <input data-bind="textInput: firstNumber">
  <input data-bind="textInput: secondNumber">
  <input data-bind="textInput: thirdNumber">
  <input data-bind="textInput: fourthNumber">
  <input data-bind="textInput: fifthNumber">
</div>

<h1 data-bind="text: fullNumber"></h1>

Upvotes: 1

Related Questions