如何使用一个组件来验证其他两个组件?

时间:2018-10-12 13:54:32

标签: javascript html angular typescript validation

我有三个组件:GalleryAddComponent添加一个新元素GalleryItemComponent,编辑一个元素FieldsComponent,这是我要在组件中使用的形式:{{1} }和GalleryAddComponent。所有组件都在GalleryItemComponent内部。但是,当我转到组件GalleryComponent来添加新元素时,我得到了错误:GalleryAddComponent。同样在组件中:ERROR TypeError: Cannot read property 'controls' of undefined

帮助解决此问题,以便编辑和添加逻辑正确运行。

GalleryAddComponent的模板

GalleryItemComponent

GalleryAddComponent的代码

<div class="card">
    <div class="card-body">
        <form [formGroup]="angForm" novalidate>
                <app-fields [formGroup]="angForm"></app-fields>
            <div class="form-group but-group">
                <button (click)="addPost(title.value, url.value);  angForm.reset(title.value, url.value)"
                        [disabled]="angForm.pristine || angForm.invalid"
                        class="btn btn-primary">Add
                </button>
                <a routerLink="/" class="btn btn-danger">Back</a>
            </div>
        </form>
    </div>
</div>

GalleryItemComponent的模板

export class GalleryAddComponent implements OnInit {
    angForm: FormGroup;
    isAdded: boolean = false;
    constructor(private fb: FormBuilder, private galleryService: GalleryService) {}

    ngOnInit() {
        this.angForm = this.fb.group({
            title: ['', Validators.required],
            url: ['', Validators.required]
        });
    }

    addPost(title: string, url: string): void {
        this.galleryService.add(title, url).subscribe(res => {
            this.isAdded = true;
        });
    }
}

GalleryItemComponent的代码

    <div class="card" *ngIf="toggleEdit">
        <h4>Edit your post</h4>
        <div class="card-body">
            <form [formGroup]="angForm" novalidate>
                <app-fields [formGroup]="angForm"></app-fields>
                <div class="form-group but-group">
                    <input type="button"
                           (click)="updatePost(title.value, url.value)"
                           [disabled]=" angForm.invalid"
                           class="btn btn-primary" value="Update Post">
                </div>
            </form>
        </div>
    </div>

FieldsComponent模板

export class GalleryItemComponent implements OnInit {
   pic: Picture;
   angForm: FormGroup;
   
    constructor(private route: ActivatedRoute,
    private galleryService: GalleryService, private fb: FormBuilder) {}

    ngOnInit() {
        this.angForm = this.fb.group({
            title: ['', Validators.required],
            url: ['', Validators.required]
        });
        this.showPost();
    }

    showPost(): void {
        this.route.params.subscribe(params => {
            this.galleryService.getPicture(params['id']).subscribe(res => {
                this.pic = res;
                this.angForm.setValue({title: res.title, url: res.url})
            })
        })
    }
    updatePost(title: string, url: string): void {
        this.route.params.subscribe(params => {
            this.galleryService.update(title, url, params['id']).subscribe(res => {
                if (res.id === this.pic.id) {
                    this.pic.title = title;
                    this.pic.url = url;
                } 
            });
        });
    }
}

FieldsComponent代码

<div [formGroup]="formGroup">
    <div class="form-group">
        <label class="col-md-4">Picture Title</label>
        <input type="text" class="form-control" formControlName="title" minlength="1" #title/>
    </div>
    <div *ngIf="angForm.controls['title'].invalid && (angForm.controls['title'].dirty || angForm.controls['title'].touched)"
         class="alert alert-danger">
        <div *ngIf="angForm.controls['title'].errors.required">
            Title is required.
        </div>
    </div>
    <div class="form-group">
        <label class="col-md-4">Picture Address (url)</label>
        <input type="url" class="form-control" formControlName="url" #url pattern="https?://.+"
               title="Include http://"/>
    </div>
    <div *ngIf="angForm.controls['url'].invalid && (angForm.controls['url'].dirty || angForm.controls['url'].touched)"
         class="alert alert-danger">
        Address(url) is required.
        <div *ngIf="angForm.controls['url'].errors.required ">

        </div>
    </div>
</div>

3 个答案:

答案 0 :(得分:1)

您收到此错误,是因为您在angForms.controls中引用FieldsComponent,该变量只有一个变量:formGroup

只需将模板HTML代码中的angForms替换为formGroup,即可解决问题。

<div [formGroup]="formGroup">
  <div class="form-group">
    <label class="col-md-4">Picture Title</label>
    <input type="text" class="form-control" formControlName="title" minlength="1" #title />
  </div>
  <div *ngIf="formGroup.controls['title'].invalid && (formGroup.controls['title'].dirty || formGroup.controls['title'].touched)"
    class="alert alert-danger">
    <div *ngIf="formGroup.controls['title'].errors.required">
      Title is required.
    </div>
  </div>
  <div class="form-group">
    <label class="col-md-4">Picture Address (url)</label>
    <input type="url" class="form-control" formControlName="url" #url pattern="https?://.+" title="Include http://" />
  </div>
  <div *ngIf="formGroup.controls['url'].invalid && (formGroup.controls['url'].dirty || formGroup.controls['url'].touched)"
    class="alert alert-danger">
    Address(url) is required.
    <div *ngIf="formGroup.controls['url'].errors.required ">

    </div>
  </div>
</div>

答案 1 :(得分:0)

我认为这里的简单解决方案是在父组件中设置表单组,并将其作为输入传递给子组件,因此在加载子组件html之前将其交给子组件。

我推荐的另一种解决方案是使用Angular提供的Resolve Technique,它使您可以在使用非常简单的设置加载组件之前加载所有数据。

以下是一些参考资料:

答案 2 :(得分:0)

无法读取未定义的属性“控件”。此错误只会出现,而不是您使用 angForm formGroup 。尝试替换为@Wrokar共享的它。另外,据我了解,您想显示合并的错误消息。因此,与其在每个formcontrol的html中进行操作,不如在component.ts中进行处理,并通过订阅如下所示的每个控件的值更改,使其更通用,并显示合并的错误消息。

for (const field in this.formGroup.controls) { // 'field' is a string
  const control = this.form.get(field); // 'control' is a FormControl
  control.valueChanges.subscribe(
    (res) => {
       // check if it is pristine, dirty,  invalid, touched, pattern match if 
           any
       // you can access control.errors
       // create the consolidated list and append it in the list of error 
          messages
    }
  )
}

最好将其设置为通用,因为明天您的表单可以包含其他字段,然后不必更改FieldsComponent。