Как установить и получить значения формы, когда мы используем раскрывающийся список CSS в качестве общего компонента - PullRequest
1 голос
/ 24 апреля 2019

У меня есть общий компонент, который представляет собой раскрывающийся список HTML и CSS.Я вызываю этот общий компонент из родительского компонента с другими данными.

Например, у меня есть 3 экземпляра общего компонента из родительского компонента, поэтому у родительской группы форм будет 3 formControls.Поскольку все 3 формы управления теперь являются общим компонентом.Как установить и получить выбранные данные из всех 3 раскрывающихся списков.

Также, если какой-либо элемент по умолчанию должен быть установлен для любого раскрывающегося списка, как мы можем его достичь.

Основная цель здесь - получить доступ/ получить все значения formControlName в группе форм родительского компонента.

Я приложил демонстрационный код https://stackblitz.com/edit/angular-mncdy5 Пожалуйста, помогите, поскольку я нахожусь в стадии обучения!

Ответы [ 3 ]

3 голосов
/ 24 апреля 2019

Вам необходимо реализовать ControlValueAccessors в общем компоненте, чтобы вы могли присоединять к ним formControls в родительском компоненте. Вот отличная статья о том, что это очень мило.

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 к вашему пользовательскому компоненту, вы можете добавить их в html в вашем app.component:

<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>

И вам нужно будет настроить имена в вашей группе форм, поскольку они не соответствуют HTML-форме

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

formControlName должен соответствовать свойству внутри parentForm.

2 голосов
/ 24 апреля 2019

Я изменил ваш демо-код, проверьте здесь: https://stackblitz.com/edit/angular-sge8r3

В CommonDropdownComponent я добавил Output(), который выдает значение, выбранное из выпадающего списка:

@Output() selectedValue: EventEmitter<string> = new EventEmitter<string>();

Я также изменил метод selectedOpiton, чтобы иметь возможность выдавать выбранное значение:

selectedOption(ctrl: string, value: string) {
  document.getElementById(ctrl).innerHTML = value;
  const ele = document.getElementById(ctrl).parentElement;
  ele.classList.toggle('cs-active');
  this.selectedValue.emit(value);
}

А затем в AppComponent я получаю значение, испускаемое дочерним компонентом, и устанавливаю переменную внутри AppComponent:

например, для первого выпадающего списка:

<app-common-dropdown placeHolder="select district" [dropDownId]="'districtLabel'" [dataList]="['bangalore','chennai','pune']" (selectedValue)="setDistrict($event)"></app-common-dropdown>

, а затем в ts файле я создал метод setDistrict():

setDistrict(value: string): void {
  this.district = value;
}

Вы также можете узнать больше о взаимодействии родителей и детей здесь: https://angular.io/guide/component-interaction

1 голос
/ 24 апреля 2019

Есть несколько способов сделать это. @porgo упоминается один из методов. Пожалуйста, проверьте ниже URL для реализации, используя @ViewChild

https://stackblitz.com/edit/angular-k92uxr

Пожалуйста, обратитесь к указанному ниже URL для связи b.w компонентов
https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...