title: Angular - Uniqueness validator in FormArray
body: <p>I created a custom validator to validate uniqueness in my <code>FormArray</code>. I want to show error when specific(s) value(s) is/are already in array.</p>
  
  <p>The problem is that it isn't working as expected. </p>
  
  <p><strong>Actual behavior:</strong></p>
  
  <p>Steps to reproduce:</p>
  
  <ul>
  <li>Add 3 "inputs" - address;</li>
  <li>Fill input 1;</li>
  <li>Fill input 2 with different value;</li>
  <li>Fill input 3 with the same value of input 1; (no errors appear, neither in input 1 nor in input 3)</li>
  </ul>
  
  <hr>
  
  <p><strong>Expected behavior</strong>:</p>
  
  <p>If the same values appears in "X groups", their specific inputs must show the error.</p>
  
  <p>In the case described above the errors should appear on input 1 and 3.</p>
  
  <p>Supposing that I have 4 inputs:</p>
  
  <ol>
  <li>value: stack </li>
  <li>value: overflow </li>
  <li>value: stack </li>
  <li>value: overflow</li>
  </ol>
  
  <p>The 4 inputs must show an error, because all of them are duplicates.</p>
  
  <hr>
  
  <pre><code>static uniqueBy = (field: string, caseSensitive = true): ValidatorFn =&gt; {
    return (formArray: FormArray): { [key: string]: boolean } =&gt; {
      const controls = formArray.controls.filter(formGroup =&gt; {
        return isPresent(formGroup.get(field).value);
      });
      const uniqueObj = { uniqueBy: true };
      let found = false;
  
      if (controls.length &gt; 1) {
        for (let i = 0; i &lt; controls.length; i++) {
          const formGroup = controls[i];
          const mainControl = formGroup.get(field);
          const val = mainControl.value;    
          const mainValue = caseSensitive ? val.toLowerCase() :  val;
  
          controls.forEach((group, index) =&gt; {
            if (i === index) {
              // Same group
              return;
            }
  
            const currControl = group.get(field);
            const tempValue = currControl.value;
            const currValue = caseSensitive ? tempValue.toLowerCase() : tempValue;
            let newErrors;
  
            if ( mainValue === currValue) {
              if (isBlank(currControl.errors)) {
                newErrors = uniqueObj;
              } else {
                newErrors = Object.assign(currControl.errors, uniqueObj);
              }
  
              found = true;
            } else {
              newErrors = currControl.errors;
  
              if (isPresent(newErrors)) {
                // delete uniqueBy error
                delete newErrors['uniqueBy'];
  
                if (isBlank(newErrors)) {
                  // {} to undefined/null
                  newErrors = null;
                }
              }
            }
  
            // Add specific errors based on condition
            currControl.setErrors(newErrors);
          });
        }
  
        if (found) {
          // Set errors to whole formArray
          return uniqueObj;
        }
      }
  
      // Clean errors
      return null;
    };
  }
  </code></pre>
  
  <p>You can check it here <kbd><a href="http://plnkr.co/edit/NgRTOaFgfKHZow6qNU8V?p=info" rel="nofollow noreferrer"><strong>DEMO</strong></a></kbd>.</p>