简体   繁体   中英

Reactive Forms - Set the input of selected <option> of a <select> FormControl dynamically by condition

I need to set two inout value depending on select option in

I have an array with the options and when the user select one option in the input have to set with other option of the array. Example: When I select the option "Risco de alergias", one input have set to "Orientar o paciente a sempre informar as alergias em caso de troca de coberturas e medicamentos." and other input have set to "Paciente não devera apresentar alergias durante a execução do tratamento" values of the array riscos

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

component.ts

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


@Component({
    selector: 'my-app',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
    planoCuidadosForm: FormGroup;
    risco: FormArray;


    riscos = [
        {
            Risco: "Risco de alergias",
            Cuidados:
            "Orientar o paciente a sempre informar as alergias em caso de troca de coberturas e medicamentos.",
            Resultado:
            "Paciente não devera apresentar alergias durante a execução do tratamento"
        },
        {
            Risco: "Risco de baixa autoestima ",
            Cuidados:
            "Promover conforto psicológico ao paciente visando a promoção da autoestima",
            Resultado:
            "Paciente não devera apresentar alterações da autoestima durante a execução do tratamento"
        },
        {
            Risco: "Risco de distúrbio na identidade pessoal",
            Cuidados:
            "Auxiliar o paciente no processo de aceitação com as condições atuais",
            Resultado:
            "Paciente não devera apresentar disturbios na identidade pessoal durante a execução do tratamento"
        }
    ];

    constructor(
        private datePipe: DatePipe,
        private fb: FormBuilder,
    ) { }   

    ngOnInit() {
        this.createFormPlanos();
    }

    createFormPlanos() {
        this.planoCuidadosForm = this.fb.group({
            planoDeCuidadosId: [null],
            evolucao: [null],
            riscos: this.buildRiscos(),
        });

    }

    buildRiscos() {
        return this.fb.array([
            this.fb.group({
            Risco: "",
            Cuidados: "",
            Resultado: ""
            })
        ]);
    }

    addRiscos(): void {
        this.risco = this.planoCuidadosForm.get("riscos") as FormArray;
        this.risco.push(this.buildRiscos());
    }

    get getRiscos(): FormArray {
        return this.planoCuidadosForm.get('riscos') as FormArray;
    }

    selRiscos(event: any) {
        console.log("Risco: ", event.target.value)

        const id = this.riscos.find(r => r.Risco == event.target.value);
        console.log("Id: ", id);

        (this.planoCuidadosForm.get(['riscos']) as FormArray)
        .patchValue([{ Risco: id.Risco, Cuidados: id.Cuidados, Resultado: id.Resultado }]);

    }

}

component.html

<form class="form-horizontal ml-2 mr-2 mt-2" [formGroup]="planoCuidadosForm" (ngSubmit)="onSubmitPlanoCuidados()">
    <div class="form-row">
        <div class="form-group col-md-12">
            <label for="evolucao">Evolução:</label>
            <textarea class="form-control" id="evolucao" rows="3" formControlName="evolucao"></textarea>
        </div>
    </div>
    <div formArrayName="riscos" class="form-group col-md">
        <table class="table table-hover">
            <thead>
                <tr class="bg-primary text-light">
                    <th style="width: 20%">Riscos</th>
                    <th style="width: 40%">Cuidados Relacionados aos riscos</th>
                    <th style="width: 30%">Resultado Esperado</th>
                    <th style="width: 5%">
                    <button type="button" class="btn btn-sm btn-primary flex-end mt-auto" (click)="addRiscos()">
                    <i class="fas fa-plus"></i>
                    </button>
                    </th>
                </tr>
            </thead>
            <tbody>
                <tr class="table-light" *ngFor=" let item of getRiscos.controls;let i = index;">
                    <td>
                        <select class="form-control" [formControlName]="i" (change)="selRiscos($event)">
                            <option [value]="null"> -- Selecione -- </option>
                            <option *ngFor="let opcao of riscos;let op = index;" value="riscos.Risco"> {{opcao.Risco }} </option>
                        </select>
                    </td>
                    <td>
                        <input type="text" class="form-control" formControlName="Cuidados" id="Cuidados" />
                    </td>
                    <td>
                        <input type="text" class="form-control" formControlName="Resultado" id="Resultado" />
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</form>

you has a FormArray of FormGroup, so you need use

<!--see that use [formGroupName]="i" in the tag with *ngFor-->
<tr class="table-light" *ngFor=" let item of getRiscos.controls;let i = index;"
       [formGroupName]="i">
   <td>
   <!--see that you use formControlName="Risco"-->
    <select class="form-control" formControlName="Risco" (change)="selRiscos($event)">
        <!--I prefer use [ngValue] over value-->
        <option [ngValue]="null"> -- Selecione -- </option>
        <option *ngFor="let opcao of riscos;let op = index;" [ngValue]="opcao.Risco"> 
             {{opcao.Risco }} 
        </option>
    </select>
   </td>
   ...
</tr>

Your function buildRisco should return a formGroup, not a FormArray, else your function addRiscos() has no sense -you are pushing a FormArray

 buildRiscos() {
   return group=this.fb.group({
        Risco: "",
        Cuidados: "",
        Resultado: ""
      })

And use when create the form as

createFormPlanos() {
    this.planoCuidadosForm = this.fb.group({
      planoDeCuidadosId: [null],
      evolucao: [null],
      riscos: this.fb.array([this.buildRiscos()]), //<--here put the formArray
     });

  }

Well, if we want control the cange in a Reactive Form is suggested subscribe to valuesChanges (not use (change) in the .html, so your function buildRiscos becomes finally as

buildRiscos() {
   const group=this.fb.group({
        Risco: "",
        Cuidados: "",
        Resultado: ""
      })

    group.get('Risco').valueChanges.subscribe(res=>{
        const risco=this.riscos.find(r => r.Risco == res);
        group.get('Cuidados').setValue(risco?risco.Cuidados:null)
        group.get('Resultado').setValue(risco?risco.Resultado:null)
    })
    return group
  }

NOTE: Well,(sorry for the long answer) Really if you dont has plans to change the fields "cuidados" and "Resultado". You can use in the select [ngValue]="opcao" and not use an input else {{risco.Cuidados}} and {{risco.Resultado}}

In this case is a FormArray of FormControls

 this.form=this.fb.group({
   riscos:this.fb.array([this.fb.control(null)])
 })

So, you use [formControlName]="i"

<form *ngIf="form" [formGroup]="form">
    <div formArrayName="riscos" class="form-group col-md">
        <tr *ngFor="let item of getRiscos2.controls;let i=index">
            <select class="form-control" [formControlName]="i" >
         <option [ngValue]="null"> -- Selecione -- </option>
         <option *ngFor="let opcao of riscos;let op = index;" [ngValue]="opcao"> {{opcao.Risco }} </option>
      </select>
        <td>{{getRiscos2.value[i]?.Cuidados}}</td>
        <td>{{getRiscos2.value[i]?.Resultado}}</td>
        </tr>
    </div>
</form>

See that, [ngValue]="opcao" the whole object! thats allow us use getRiscos2.value[i].Cuidados

I fork your stackblitz with all this concepts, I hope this help you

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM