user6885115
user6885115

Reputation:

Angular 4 Validator with an http observable

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.

Upvotes: 2

Views: 1039

Answers (1)

user6885115
user6885115

Reputation:

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() {
  }
}

Upvotes: 1

Related Questions