2

I have an input component that on keyup I want to delay with a debounce and then fire off an http request which works

import { Component, EventEmitter, OnInit, Input, Output } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { KeywordsApiService } from '../keywords-api.service';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/catch';

@Component({
  selector: 'input-group',
  templateUrl: './input-group.component.html',
  styleUrls: ['./input-group.component.scss']
})
export class InputGroupComponent implements OnInit {

  @Input() data: any;
  valid: boolean;
  invalidName: boolean;
  complexForm: FormGroup;
  pattern: RegExp;

  @Output() clicked: EventEmitter<boolean> = new EventEmitter();
  @Output() keyedup: EventEmitter<boolean> = new EventEmitter();

  constructor(private fb: FormBuilder, private keywordsApiService: KeywordsApiService) { }

  ngOnInit() {
    console.log(this.data);

    this.complexForm = this.fb.group({
      input: ['', Validators.pattern(this.data.pattern), this.invalidName]
    });
    console.log(this.complexForm.controls['input']);

    this.complexForm.valueChanges
      .subscribe(x => console.log(x));

    this.complexForm.valueChanges
      .debounceTime(500)
      .switchMap(val => this.keywordsApiService.getGroups())
      .subscribe(data => {
          this.invalidName = data.some(item => {
            return item == this.data.value
          });
          console.log(this.invalidName);
        });

  }

  click() {
    console.log(this.data.value);
    this.clicked.emit(true);
  }

  onKey() {
  }
}

I have a pattern validator on the input but I want to also check whether this.validName is true or false and use this in the validators.

I have updated the code above.

If return item == this.data.value returns true then I want to get this.complexForm to say input is not valid.

  • Possible duplicate of [How to add debounce time to an async validator in angular 2?](https://stackoverflow.com/questions/36919011/how-to-add-debounce-time-to-an-async-validator-in-angular-2) – n00dl3 Aug 10 '17 at 11:57
  • **I want to delay with a debounce and then fire off an http request which works** It works or not works? Or what is the question? :) – AT82 Aug 10 '17 at 13:35
  • @AJT_82 ok well the request for this.keywordsApiService.getGroups() fires and console.log(this.validName); states true or false but if its true I want the validator to fail the validation –  Aug 10 '17 at 13:41
  • Have updated the code –  Aug 10 '17 at 13:44
  • So basically you want an additional validator? :) – AT82 Aug 11 '17 at 08:20
  • @AJT_82 yeah! I think I might have got it actually –  Aug 11 '17 at 08:21
  • Oh okay, if it doesn't work out, let me know, I have an idea in my head on how to possibly solve this :) – AT82 Aug 11 '17 at 08:23
  • And of course if you solve it, please post answer, I'm curious to see your solution :) – AT82 Aug 11 '17 at 08:24
  • @AJT_82 posted the answer –  Aug 11 '17 at 09:10
  • Not really looking at else code :P Okay, well if the code in your question, I would have just added a couple of lines of code and based on the boolean set a error on the form itself, or remove it. Don't know if it's suitable. But I don't see why not though if you want to set a error in your form if `this.invalidName` is true. – AT82 Aug 11 '17 at 10:24

1 Answers1

1

I changed my code around quite a bit, I didn't need to do an http request on each type so I moved that to the parent component and passed the results down to this component with one-way binding.

it seems all I was missing was wrapping my 2 validators in Validators.compose([])

I also needed to changed the segmentValidator to compare the array of segments to see if the control.value of 'input' matches which is done in the manner below.

import { Component, EventEmitter, OnInit, Input, Output } from '@angular/core';
import { AbstractControl, FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/catch';

@Component({
  selector: 'input-group',
  templateUrl: './input-group.component.html',
  styleUrls: ['./input-group.component.scss']
})
export class InputGroupComponent implements OnInit {

  @Input() data: any;
  @Input() segments: any[];
  valid: boolean;
  invalidName: boolean;
  complexForm: FormGroup;
  pattern: RegExp;

  @Output() clicked: EventEmitter<boolean> = new EventEmitter();
  @Output() keyedup: EventEmitter<boolean> = new EventEmitter();

  constructor(private fb: FormBuilder) { }

  segmentValidator(control: AbstractControl): {[key: string]: any} {
    const input = control.value;
    if (this.segments) {
      return this.segments.includes(input) ? { nomatch: true } : null;
    }

  }

  ngOnInit() {
    console.log(this.data);

    this.complexForm = this.fb.group({
      'input': ['', Validators.compose([Validators.pattern(this.data.pattern), this.segmentValidator.bind(this)])]
    });

    console.log(this.complexForm.controls['input']);

    this.complexForm.valueChanges
      .subscribe(x => x);

    this.complexForm.valueChanges
      .debounceTime(500)
      .subscribe(data => {
          this.keyedup.emit(this.data.value);
      });

  }

  click() {
    console.log(this.data.value);
    this.clicked.emit(true);
  }

  onKey() {
  }
}