Выбранное значение в mat-select не отправляется родителю

Я создал выпадающий список в угловой библиотеке для использования в наших приложениях. Я использовал angular-material2 для выпадающего списка (mat-select и mat-autocomplete).

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

Я прокомментировал большую часть этого, и я пытаюсь решить самую простую версию, но даже в этом случае я не получаю значение. Вот что у меня сейчас:

Библиотека DropdownComponent.html:

<mat-form-field appearance="outline">
    <mat-select disableOptionCentering (selectionChange)="writeValue($event)" [multiple]="multi">
      <mat-option *ngFor="let item of list" [value]="item">
        {{ item }}
      </mat-option>
    </mat-select>
</mat-form-field>

Библиотека DropdownComponent.ts:

import {Component, OnInit, ViewEncapsulation, Input, forwardRef} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormControl} from '@angular/forms';
import {Observable} from 'rxjs';

@Component({
  selector: 'pux-dropdown',
  templateUrl: './dropdown.component.html',
  styleUrls: ['./dropdown.component.scss'],
  encapsulation: ViewEncapsulation.None,
  providers: [
    { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DropdownComponent), multi: true },
    { provide: NG_VALIDATORS, useExisting: forwardRef(() => DropdownComponent), multi: true }
  ]
})
export class DropdownComponent implements OnInit, ControlValueAccessor {
  @Input() list: any[] = [];
  @Input() selected: any;
  @Input() multi = false;
  @Input() search = false;
  items: any[] = [];
  propagateChange = (_: any) => {};
  validateFn: any = () => {};

  constructor() { }

  ngOnInit() {
    this.items = this.list;
  }

  // Form

  get value(): any { return this.selected; }
  set value(newValue: any) {
   if (newValue !== this.selected) {
     this.writeValue(newValue);
     this.registerOnChange(newValue);
     this.selected = newValue;
    }
  }

  registerOnChange(fn: any): void { this.propagateChange = fn; }

  registerOnTouched(fn: any): void {}

  setDisabledState(isDisabled: boolean): void {}

  writeValue(obj: any): void {
    if (obj !== null) {
      this.selected = obj.value;
      this.registerOnChange(this.selected);
      console.log(this.selected);
    }
  }

  validate(c: FormControl) { return this.validateFn(c); }
}

DropDownComponent.html приложение:

<div>
    <form [formGroup]="selectForm" (ngSubmit)="saveSelect(selectForm)" #form1="ngForm">
        <div>
            <pux-dropdown formControlName="selectValue" [list]="list1"> </pux-dropdown>
        </div> <br>
        <button mat-flat-button="primary" type="submit" class="btn btn-primary">Save</button>
    </form> <br>
    <div>
         Saved Value: {{selectValue | json}}
    </div>
</div>

Приложение DropdownComponent.ts:

import {Component, OnInit} from '@angular/core';
import {FormGroup, FormBuilder} from '@angular/forms';

const states = [
  'Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware',
  'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky',
  'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi',
  'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico',
  'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania',
  'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont',
  'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'
];

@Component({
  selector: 'app-dropdown',
  templateUrl: './dropdown.component.html',
  styleUrls: ['./dropdown.component.scss']
})
export class DropdownComponent implements OnInit {
  list1;
  multi: boolean;
  selected: any;
  search: boolean;
  // Form
  selectForm: FormGroup;
  selectValue: string;

  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.list1 = states;
    // Form
    this.selectForm = this.fb.group({
      selectValue: this.selected
    });
  }

  saveSelect(formValues) {
    console.log(formValues.value.selectValue);
    this.selectValue = formValues.value.selectValue;
  }
}

Console.log в writeValue в библиотеке дает мне значение, выбранное в раскрывающемся списке, но console.log в saveSelect показывает мне ноль. Таким образом, значение не отправляется родителю. Есть идеи, что я делаю не так? Заранее спасибо.

1 ответ

Решение

Ваш writeValue реализация должна вызывать функцию изменения, но вместо этого она вызывает registerOnChange функция, которая существует для управления формой, чтобы зарегистрировать свою функцию изменения. Попробуйте что-то вроде этого:

propagateChange: (value: any) => void = () => {};

registerOnChange(fn: (value: any) => void) { this.propagateChange = fn; }

writeValue(obj: any): void {
  if (obj !== null && obj !== this.selected) {
    this.selected = obj.value;
    this.propagateChange(this.selected);
  }
}
Другие вопросы по тегам