javascript - 当我们使用 css dropdown 作为共享组件时如何设置和获取表单值

标签 javascript angular typescript angular-reactive-forms angular4-forms

我有一个共享组件,它是一个 html 和 css 下拉列表。 我从具有不同数据的父组件调用此共享组件。

例如,我有 3 个来自父组件的共享组件实例,因此父表单组将有 3 个 formControl。由于所有 3 个表单控件现在都是共享组件。如何设置和获取所有 3 个下拉列表中的选定数据。

另外,如果要为任何下拉设置任何默认项,我们如何实现。

这里的主要目标是访问/获取父组件表单组中的所有 formControlName 值。

我附上了演示代码https://stackblitz.com/edit/angular-mncdy5 请帮助我,因为我正处于学习阶段!

最佳答案

您需要在共享组件中实现 ControlValueAccessors,以便您可以在父组件中将 formControl 附加到它们。这是一篇很棒的文章,它非常直接。

https://medium.com/@majdasab/implementing-control-value-accessor-in-angular-1b89f2f84ebf

这就是您的 customDropdown 组件需要如何实现 ControlValueAccessors

import { OnInit } from '@angular/core';
import { Component, forwardRef, HostBinding, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
  selector: 'app-common-dropdown',
  templateUrl: './common-dropdown.component.html',
  styleUrls: ['./common-dropdown.component.css'],
  providers: [     
      {       provide: NG_VALUE_ACCESSOR, 
              useExisting: forwardRef(() => CommonDropdownComponent),
              multi: true     
      }
    ] 
})
export class CommonDropdownComponent implements ControlValueAccessor {

  @Input() placeHolder: string;
  @Input() dropDownId: string;
  @Input() dataList: any;

  onChange: any = () => {}
  onTouch: any = () => {}
  val= "" // this is the updated value that the class accesses

  set value(val){  // this value is updated by programmatic changes if( val !== undefined && this.val !== val){
    this.val = val
    this.onChange(val)
    this.onTouch(val)
  }


  constructor() { }

  ngOnInit() {
  }

  // this method sets the value programmatically
  writeValue(value: any){ 
    this.value = value
  }
  registerOnChange(fn: any){
    this.onChange = fn
  }
  registerOnTouched(fn){
    this.onTouch = fn
  }

  propagateChange(_){

  }

  selectClicked(event: any) {
    const ele = event.srcElement.parentNode;
    ele.classList.toggle('cs-active');
  }

  selectedOption(ctrl: string, value: string) {
    this.onChange(value) // <-- CRUCIAL need to inform formControl to update the value 
    document.getElementById(ctrl).innerHTML = value;
    const ele = document.getElementById(ctrl).parentElement;
    ele.classList.toggle('cs-active');
  }

  closeDropDown(event: any) {
    const ele = event.srcElement;
    ele.classList.remove('cs-active');
  }
}

现在我们已经添加了将 formControls 附加到您的自定义组件的功能,您可以将它们添加到您的 app.component 中的 html:

<form [formGroup]="parentForm">
    <app-common-dropdown placeHolder="select district" [dropDownId]="'districtLabel'" [dataList]="['bangalore','chennai','pune']" formControlName="district" ></app-common-dropdown>
    <app-common-dropdown placeHolder="select distance" [dropDownId]="'distanceLabel'" [dataList]="[100,200,300,400]" formControlName="distance" ></app-common-dropdown>
    <app-common-dropdown placeHolder="select state" [dropDownId]="'stateLabel'" [dataList]="['karnataka','tamil nadu','mumbai']" formControlName="state"  ></app-common-dropdown>
</form>

<button type="submit" (click)="getFormValues()">submit</button>

并且您需要调整 formGroup 中的名称,因为它们与 html 表单不匹配

this.parentForm = this.fb.group({
  district: ['bangalore', Validators.required], <--- SETS THE DEFAULT VALUE OF THE FORM CONTROL
  distance: [''],
  state:['']
});

formControlName 需要匹配 parentForm 中的属性。

关于javascript - 当我们使用 css dropdown 作为共享组件时如何设置和获取表单值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55825893/

相关文章:

javascript - 通过javascript读取excel文件

angular - http get请求Angular 6中的返回字符串

angular - 在渲染 View /模板之前等待 Angular 2 加载/解析模型

javascript - Angular 6 - 比较两个可观察长度

javascript - 如何实现类似于打印分页的div break?

typescript - 为什么这个 Typescript 泛型类型推断失败?

javascript - 查找文本中的确切单词,不包括引用的单词

javascript - 将两个数组合并为一个对象

javascript - 相对定位元素在为其父元素设置动画时消失

angular - 如何将 angular 2 组件创建到 Nativescript 应用程序中?