Отключить ввод формы Angular Reactive на основе значения выбора

У меня есть форма (с использованием Angular Material), и я хочу отключить некоторые поля ввода на основе значений выбора. Мой код выглядит так:

HTML

<mat-form-field class="someclass">
   <mat-select placeholder="Select payment method" formControlName="paymentMethod">
      <mat-option *ngFor="let payment of paymentMethodOptions" [value]="payment.value">
         {{payment.viewValue}}
      </mat-option>
   </mat-select>
</mat-form-field>

<mat-form-field class="someclass">
   <input matInput placeholder="Some input" formControlName="testInput">
</mat-form-field>

TS

paymentMethodOptions: payment[] = [
   { value: "opt-1", viewValue: "somevalue" },
   { value: "opt-2", viewValue: "anothervalue" }
];

paymentForm = new FormGroup({
   paymentMethod: new FormControl("", Validators.required),
   testInput: new FormControl({ value: "", disabled: true }, [
      Validators.required
   ])
});

Я хочу отключить testInput, если значение выбора равно "opt-1". Я пробовал несколько вариантов, но получил разные ошибки и не смог их решить. Есть ли какое-нибудь рабочее решение для этого? Заранее спасибо!


person Andrew    schedule 21.11.2018    source источник
comment
Мне нравится enabledDirective (это похоже на обходной путь, но у него есть то преимущество, что .html с включенным управлением) stackoverflow.com/questions/47937639/   -  person Eliseo    schedule 21.11.2018


Ответы (3)


Вы можете использовать свойство selectionChange @Output на MatSelect и отреагировать соответствующим образом:

onSelectionChanged({value}) {
  console.log(value);
  if(value === 'opt-1') {
    this.paymentForm.get('testInput').disable();
  } else {
    this.paymentForm.get('testInput').enable();
  }
}

И в шаблоне

<mat-select ... (selectionChange)="onSelectionChanged($event)">

Вот Образец StackBlitz для вашего исх.

ПРИМЕЧАНИЕ. В случае, если в вашей форме больше элементов управления, чем просто mat-select, прослушивание valueChanges во всей форме может быть дорогостоящим, так как это будет срабатывать каждый раз при изменении любого элемента управления формы. Все, что нас беспокоит, - это изменение mat-select выбора.

person SiddAjmera    schedule 21.11.2018
comment
@Andrew, если какой-либо из этих ответов помог вам с вашей проблемой, подумайте о том, чтобы пометить любой из них как решение для закрытия цикла. - person SiddAjmera; 21.11.2018

Вы можете прослушать valueChanges событие формы:

this.paymentForm.valueChanges.subscribe((value) => {
  if(value.paymentMethod == 'opt-1'){
   this.paymentForm.controls['testInput'].disable();
  }else{
   this.paymentForm.controls['testInput'].enable();
  }
});

Таким образом, каждый раз, когда select изменяется, вызывается событие valueChanges, срабатывают условия, и оно включает или отключает formControl.

person CruelEngine    schedule 21.11.2018
comment
Похоже, ваше решение тоже работает. Большое спасибо! - person Andrew; 21.11.2018
comment
Почему вы слушаете valueChanges всю форму? Разве он не будет запускаться каждый раз, когда в форме будут какие-либо изменения? Здесь нас должно интересовать только изменение значения mat-select. - person SiddAjmera; 21.11.2018
comment
@SiddAjmera formControl привязан к выбранному элементу. В противном случае я бы тоже использовал событие selectionChange. - person CruelEngine; 21.11.2018
comment
Разве не было бы безопасно предположить, что OP был простой абстракцией исходной реализации и что в форме будет гораздо больше элементов управления формой, а не просто mat-select? - person SiddAjmera; 21.11.2018
comment
@SiddAjmera, я согласен с тем, что вы пытаетесь сказать, но если мы продолжим это предположение, то может быть случай, когда он может захотеть сохранить valueChange и также сделать вызовы api. - person CruelEngine; 21.11.2018
comment
Точка. Я беру свои слова обратно в этом случае. Прости за это. :) - person SiddAjmera; 21.11.2018
comment
@SiddAjmera без проблем :) - person CruelEngine; 21.11.2018
comment
Оба решения работают хорошо, попробую использовать оба и решу, какое из них лучше подходит для моего случая. Спасибо за поддержку :) - person Andrew; 21.11.2018
comment
@ Андрей счастлив кодить :) - person CruelEngine; 21.11.2018

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

Создал демонстрацию Stackblitz ссылку

  <!-- INPUT FIELD --> 
  <mat-form-field formControlName="testInput">
    <input matInput 
           placeholder="Some input"
           [disabled]="paymentForm.get('paymentMethod').value === 'opt-1'">   // Disables the input once paymentMethod's formControlName value is opt-1    
  </mat-form-field>     
person KShewengger    schedule 21.11.2018
comment
Не работает. В этом случае вам придется использовать attr.disabled. Также он не изменил состояние disabled, если сначала было выбрано opt-1, а затем было выбрано opt-2. - person SiddAjmera; 21.11.2018
comment
Случайно удалил [disabled] при вводе из присланной мной демонстрационной ссылки Stackblitz. Теперь он действительно меняет свое состояние, вы можете попробовать. Вы узнаете, что он отключается, когда вы больше не можете нажимать на ввод, и у него пунктирная рамка вместо сплошной stackblitz.com/edit/angular-nuygok - person KShewengger; 21.11.2018
comment
Действительно работает. Так что хитрость в том, чтобы использовать paymentForm.get('paymentMethod').value вместо paymentForm.value.paymentMethod - person SiddAjmera; 21.11.2018