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

Я создал раскрывающийся список в библиотеке angular для использования в наших приложениях. Я использовал 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 показывает мне нулевое значение. Таким образом, значение не отправляется родителю. Любая идея, что я делаю неправильно? Заранее спасибо.


person Tina    schedule 03.07.2018    source источник


Ответы (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);
  }
}
person G. Tranter    schedule 03.07.2018
comment
Большое спасибо! Я пробовал все и был уверен, что где-то есть небольшая ошибка, но я никогда этого не видел. Спасибо. - person Tina; 04.07.2018