0

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?

Atoyansk
  • 233
  • 5
  • 20

2 Answers2

0

I think it might be easier if you used *ngIf="form.get('motorType').value === 'Other'" inside the div that you want to change visibility.

armgjoka
  • 11
  • 4
0

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.

ruth
  • 29,535
  • 4
  • 30
  • 57
  • is there a way to call the 3 elements as parameters in the component, using the format "getField(form, selectionField, inputField)"? That's because I have many selection fields! – Atoyansk Nov 24 '20 at 10:04
  • You can use this operator anywhere you'd like to have the comparison. I've updated the answer. – ruth Nov 24 '20 at 11:37
  • About your update: what I'm trying to achieve is precisely to avoid this repetition of code snippets. Note that in your examples, the functions are repeated as much as the number of forms I have, as in "this.f.get ('someValue').pipe (this.utils.getField ()).subscribe({...})". – Atoyansk Nov 24 '20 at 13:44