【问题标题】:populating Form from child custom component从子自定义组件填充表单
【发布时间】:2021-02-12 05:29:57
【问题描述】:

所以,我正在尝试创建一个自定义组件,以便在整个应用程序中、在表单内或作为独立组件使用。这是我目前所拥有的。

custom-select.ts

@Component({
  selector: 'app-custom-select',
  templateUrl: './custom-select.component.html',
  styleUrls: ['./custom-select.component.scss'],
  viewProviders: [{
    provide: ControlContainer,
    useExisting: FormGroupDirective
  }]
})

export class CustomSelectComponent implements OnInit {
    @Input()
    public selection: any[] = [];

    @Input()
    public controlName: string;

    @Output()
    selectionChange: EventEmitter<any> = new EvenEmitter<an>();

    constructor() {}
    ngOnInit() { //sort option list and do other stuff }

    onSelectionChange(event) {
      this.selectionChange.emit(event)
    }
}

custom-select.html

<ng-select>
  [items]="selection"
  bindValue= "id"
  bindLabel="label"
  [formControlName]="controlName"
  (change)="onSelectionChange($event)"
</ng-select>

现在到父组件 app-component.ts

export class appComponent implements OnInit {
    testForm: FormGroup = new FormGroup({
      City: new FormControl(null),
      State: new FormControl(null)
    });

    cities: any[] = [];
    states: any[] = [];

    constructor() {}
    ngOnInit() { // populate cities & states}
    .....
    .....
    onSubmit() {
      console.log("Form Values", this.testFrom.value);
    } 

    testCity(event) { console.log("City: ", event); }
    testState(event) { console.log("State: ", event); }
}

app-component.html

<form [ngForm]="testForm">
  <custom-select
   [selection]="cities"
   controlName="City"
   (onSelectionChange)="testCity($event)"
  ></custom-select>
  <custom-select
   [selection]="states"
   controlName="State"
   (onSelectionChange)="testState($event)"
  ></custom-select>
</form>

结果:

City: {id: 101, label: "Chicago"}  //correct value

State: {id: 20, label: "Illinois"}  //correct value

FormValues: {City: 3, State: 1}     //needs to hold above objects instead of list position of selected items

问题:我在 “事件” 中得到了正确的选择,但是在提交表单时,我得到的选项列表中所选值的位置不是实际值。

如何根据 controlName 将事件传递给表单本身?

【问题讨论】:

    标签: angular angular-components angular-forms custom-component


    【解决方案1】:

    您的代码似乎有几项可以改进

    • 使用FormBuilder 生成您的formGroup 实例

    app.component.ts

    constructor (private fb: FormBuilder) {}
    export class AppComponent {
      constructor(private fb: FormBuilder) {}
      testForm: FormGroup = this.fb.group({
        City: [null],
        State: [null]
      });
    
      cities: any[] = [];
      states: any[] = [];
    
      ngOnInit() {
        this.cities = [{ id: 100, label: "NY City" }];
        this.states = [{ id: 10, label: "NY State" }];
        // populate cities & states}
      }
      onSubmit() {
        console.log("Form Values", this.testForm.value);
      }
    }
    
    

    app.component.html

    <hello name="{{ name }}"></hello>
    <form [formGroup]="testForm" (submit)="onSubmit()">
        <custom-select [selection]="cities" formControlName="City"></custom-select>
        <custom-select [selection]="states" formControlName="State"></custom-select>
      <button>Submit</button>
    </form>
    
    • 创建custom-control 实现ControlValueAccessor custom-select.component.ts
    @Component({
      selector: "custom-select",
      templateUrl: "./custom-select.component.html",
      styleUrls: ["./custom-select.component.css"],
      providers: [
        {
          provide: NG_VALUE_ACCESSOR,
          useExisting: CustomSelectComponent,
          multi: true
        }
      ]
    })
    export class CustomSelectComponent implements ControlValueAccessor {
      @Input() selection: any[];
      onChanges: any = () => {};
      onTouch: any = () => {};
      value: any;
      disabled: boolean;
      constructor() {}
      writeValue(value: any): void {
        this.value = value;
      }
      registerOnChange(fn: any): void {
        this.onChanges = fn;
      }
      registerOnTouched(fn: any): void {
        this.onTouch = fn;
      }
      setDisabledState?(isDisabled: boolean): void {
        this.disabled = isDisabled;
      }
    }
    
    

    custom-select.component.html

    <ng-select 
      [items]="selection" 
      bindValue="id" 
      bindLabel="label" 
      [(ngModel)]="value" 
      (ngModelChange)="onChanges(value)">
    </ng-select>
    

    想法是创建一个自定义表单控件,See this demo

    【讨论】:

    • 感谢您对更好代码的详细回答和建议。但是,当我遵循您的逻辑时,有两件事:1)我收到关于 ngModel cannot be used to register form controls with a parent formGroup directive 的错误 2)我可以让表单保存名称而不是 id 吗?
    • 是的,你可以。您只需将bindValue="id" 更改为bindValue="name" ,这样&lt;ng-select&gt; 标签将返回名称而不是ID。看到这个分叉stackblitz.com/edit/angular-ivy-custom-form-control-sjpdgt
    • 如果你必须使用ngModel,那么我建议你看看这个答案stackoverflow.com/a/40588951/13680115
    猜你喜欢
    • 2019-10-10
    • 2014-07-08
    • 2014-04-29
    • 1970-01-01
    • 2022-11-11
    • 2021-12-21
    • 2023-04-06
    • 2013-03-04
    • 1970-01-01
    相关资源
    最近更新 更多