Как отменить выбор выбранного option-элемента в select-element, используя Angular 8 - PullRequest
2 голосов
/ 03 ноября 2019

У меня есть следующие требования:

  • Я получил два FormControl объекта для элементов select mainSelect и subSelect, которые required.
  • subSelect изменяется в зависимости от значения mainSelect.
  • Когда mainSelect изменяется на значение, в которое значение из subSelect не включено subSelect необходимостановится invalid, поэтому FormGroup, оба из FormControl являются частью, становится invalid тоже.
  • Но если значение из subSelect включено, subSelect необходимо удерживать егофактическое значение.

(конкретный пример описан после ссылки на StackBlitz.)

Моя проблема при решении этого требования:

Еслизначение mainSelect изменяется и значение subSelect не включается subSelect принимает первое значение списка вместо того, чтобы становиться null / invalid.

Таким образом, РЕШЕНИЕ будет, если выбранное значение 'subSelect' станет нулевым, а в браузере не будет выбрано никакого значения.

Что я пробовал до сих пор:

Я пыталсясоздать компонент и реализовать интерфейс ControlValueAccessor. Кажется, здесь кроется моя проблема. Кажется, я не совсем понимаю, как это работает.

Я смотрел следующее видео на YouTube и читал статьи ( 1 , 2 ) относится к ControlValueAccessor, но все еще не может решить мою проблему.

Это часть моего кода:

Также вы можете найти его на StackBlitz

Пример

Если в браузере MainSelect имеет значение thirdMainSelect, а SubSelect имеет значение fifthSubSelect и MainSelectизменяет его значение на firstMainSelect SubSelect, не должно иметь выбранного значения.

select.component.ts

export class SomeObject {
  value: string;
  parameters: {[parameterName: string]: string} = {};
}

@Component({
  selector: "app-select",
  templateUrl: "./select.component.html",
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: SelectComponent,
    multi: true
  }]
})
export class SelectComponent implements ControlValueAccessor, OnChanges {
  @ViewChild("select", {static: true}) select: ElementRef;
  @Input() tableId: string;
  @Input() filter: { [parameterName: string]: string};

  returnedTable: SomeObject[];

  onChange: (_: any) => void;
  onTouched: () => void;

  selected: string;

  constructor(private tableService: TableService) { }

  loadTable(): void {
    this.tableService.getTable(this.tableId, this.filter)
      .subscribe(table => {
        this.returnedTable = table;
      });
  }

  ngOnChanges(): void {
    this.loadTable();
  }

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

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  writeValue(value: string): void {
    this.selected = value;
  }
}

select.component.html

<select class="form-control" #select (change)="onChange($event.target.value)">
  <option *ngFor="let item of returnedTable" [value]="item.value" [selected]="selected === item.value">{{item.value}}</option>
</select>

app.component.ts

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.scss"]
})
export class AppComponent implements OnInit {

  form: FormGroup;
  containerObject: ContainerObject;

  selectedMainValue: string;

  constructor(private tableService: TableService,
              private formBuilder: FormBuilder) {

  }

  ngOnInit(): void {
    this.tableService.getContainerObject()
      .subscribe(containerObject => {
        this.containerObject = containerObject;
        this.selectedMainValue = containerObject.mainSelect;
        this.initForm();
      });
  }

  private initForm(): void {
    this.form = this.formBuilder.group({
      mainSelect: [this.containerObject.mainSelect, Validators.required],
      subSelect: [this.containerObject.subSelect, Validators.required]
    });
    this.subscribeToMainSelectChanged();
    this.subscribeToSubSelectChanged();
  }

  onSubmit(): void {
    if (this.form.valid) {
      this.containerObject.mainSelect = this.form.get("mainSelect").value;
      this.containerObject.subSelect = this.form.get("subSelect").value;
      this.tableService.saveContainerObject(this.containerObject);
    }
  }

  private subscribeToMainSelectChanged() {
    this.form.get("mainSelect").valueChanges
      .subscribe(mainSelect => {
        this.selectedMainValue = mainSelect;
        console.log(this.form.status);
      });
  }

  private subscribeToSubSelectChanged() {
    this.form.get("subSelect").valueChanges
      .subscribe(() => {
        console.log(this.form.status);
      });
  }
}

app.component.html

<div>
  <form id="wrapper" [formGroup]="form" (ngSubmit)="onSubmit()">
    <div id="left" class="form-group row">
      <label for="mainSelect" class="col-form-label col-sm-2">MainSelect</label>
      <div class="col-sm-6">
        <app-select
          id="mainSelect"
          formControlName="mainSelect"
          [tableId]="'mainSelectTable'"
          [filter]="{firstType: 'firstParameter'}"
        ></app-select>
      </div>
    </div>
    <div id="right" class="form-group row">
      <label for="subSelect" class="col-form-label col-sm-2">SubSelect</label>
      <div class="col-sm-6">
        <app-select
          id="subSelect"
          formControlName="subSelect"
          [tableId]="'firstParameter'"
          [filter]="{firstType: 'firstParameter', secondType: selectedMainValue}"></app-select>
      </div>
    </div>
    <p></p>
    <button id="button" type="submit">Submit</button>
  </form>
</div>

Ответы [ 3 ]

0 голосов
/ 10 ноября 2019

Через некоторое время, пытаясь решить эту проблему только с помощью SelectComponent и особенно writeValue, следующий код сделал работу:

Я изменил select.component.ts следующим образом:

export class SomeObject {
  value: string;
  parameters: {[parameterName: string]: string} = {};
}

@Component({
  selector: "app-select",
  templateUrl: "./select.component.html",
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: SelectComponent,
    multi: true
  }]
})
export class SelectComponent implements ControlValueAccessor, OnChanges {
  @ViewChild("select", {static: true}) select: ElementRef;
  @Input() tableId: string;
  @Input() filter: { [parameterName: string]: string};

  returnedTable: SomeObject[];

  onChange: (_: any) => void;
  onTouched: () => void;

  selected: string;

  constructor(private tableService: TableService) { }

  loadTable(): void {
    this.tableService.getTable(this.tableId, this.filter)
      .subscribe(table => {
        this.returnedTable = table;
        if (!!this.select && !!this.select.nativeElement.value) {
          this.writeValue(this.select.nativeElement.value);
          this.onChange(this.selected);
        }
      });
  }

  ngOnChanges(): void {
    this.loadTable();
  }

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

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  writeValue(value: string): void {
    if (!!this.returnedTable && !this.returnedTable.some(item => item.value === value)) {
      this.selected = null;
    } else {
      this.selected = value;
    }
  }
}

А select.component.html вот так:

<select class="form-control" #select (change)="onChange($event.target.value)">
  <option hidden *ngIf="!selected" value=""></option>
  <option *ngFor="let item of returnedTable" [value]="item.value" [selected]="selected === item.value">{{item.value}}</option>
</select>

0 голосов
/ 10 ноября 2019

Чтобы отменить выбор параметра: - option.selected = false.

Библиотека Angular с декомпиляцией функции в ее ядре для $scope и вложенных форм, функция Angular, указывающая на то, что группа Angular не знает, как эффективноиспользовать HTML. HTML не допускает вложенных форм, так зачем, черт возьми, вы пытаетесь использовать язык для этого? Больше проблем, чем стоит. Конечно, от парней вроде Брэдли Грина, бывшего менеджера Angular JS, нельзя ожидать большего.

0 голосов
/ 04 ноября 2019

Я думаю, что это только использовать valuesChange. Если у вас есть два массива данных и подданных и форма, подобная

form = new FormGroup({
    prop1: new FormControl(),
    prop2: new FormControl()
  });

Простого

this.form.get("prop1").valueChanges.subscribe(res => {
  this.dataService.getData(res).subscribe(data=>{
    this.subdata=data;
    if (!this.subdata.find(x=>x.value==this.form.get("prop2").value))
      this.form.get("prop2").setValue(null);
  }).unsubscribe()
});

должно быть достаточно, см. stackblitz

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