简体   繁体   中英

Angular 8 - Multiple Variables not Update from Service to Component

I have a function which displays an input field only if the select field before has the "Other" selected value:

inputMotor = 'none';

this.f.get('motorType').valueChanges
    .subscribe((pVal) => {
    pVal === 'Other' ? this.inputMotor = 'flex' : this.inputMotor = 'none';
});

And the template:

<div  class="form-group">
    <label  for="motorType">Motor Type</label>
    <select  class="form-control" formControlName="motorType" id="motorType" type="text">
        <option  value="">Choose the Motor Type</option>
        <option  value="Value 1">Value 1</option>
        <option  value="Value 2">Value 2</option>
        <option  value="Other">Other</option>
    </select>
</div>
<div  class="form-group" [ngStyle]="{'display':inputMotor}">
    <input  class="form-control" formControlName="otherMotorType" placeholder="Other Motor Type" type="text">
</div>

In the example above, I use the function to recognize the selected value in the "motorType" field. The problem is that this function applies to many selection fields. So, I tried to generate a generic function for this. In my service, I tried:

getField(form, field: string, inputField: string) {
  form.get(field).valueChanges
    .subscribe((pVal) => {
      pVal === 'Other' ? inputField = 'flex' : inputField = 'none';
  });
}

And to call the function, I would use:

this.utils.getField(this.f, 'motorType', this.inputMotor);

The call to the component recognizes the first two parameters, but does not update the variable (in the example, inputMotor), always keeping its value as 'none', and not displaying the field for "Other".

I tried as suggested in this post , but it worked fine only for a single variable (it's not reusable).

Also, I'm trying to avoid any code repetition in the component. So, for each form I have, I'm just trying to call the service function and pass the necessary parameters.

How can I achieve this?

我认为如果您在要更改可见性的 div 中使用 *ngIf="form.get('motorType').value === 'Other'" 可能会更容易。

There are at least 2 issues here

  1. The arguments to the function are passed by value. When you're attempting inputField = ... in the service, the value isn't assigned to the this.inputMotor from the component but rather the inputField parameter of the function.

  2. The proper way would be to return the value to function and assign it there. But the function is asynchronous. The value from it can't be returned synchronously. You would need to return the observable from the service and subscribe to it in the component.

Try the following

Service

Create a custom RxJS operator that contains the condition using the map operator

public mapField() {
  return <T>(source: Observable<T>) => {
    return source.pipe(
      map(pVal =>
        pVal === 'Outro' ? 'flex' : 'none'
      )
    );
  };
};

Component

And use it in the component

inputMotor = 'none';

this.f.get('motorType').pipe(
  this.utils.getField()
).subscribe({
  next: pVal => this.inputMotor = pVal
});

Update: Use with other forms

You can pipe in this operator wherever you'd wish to have the comparison.

Form 1

form1Value = 'none';

this.f.get('someValue').pipe(
  this.utils.getField()
).subscribe({
  next: pVal => this.form1Value = pVal
});

Form 2

form2Value = 'none';

this.f.get('someOtherValue').pipe(
  this.utils.getField()
).subscribe({
  next: pVal => this.form2Value = pVal
});

Form 3

form3Value = 'none';

this.f.get('yetOtherValue').pipe(
  this.utils.getField()
).subscribe({
  next: pVal => this.form3Value = pVal
});

and so on.

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