1

OK it's a bit more complicated than the headline..

This form I am working on is a form group. It has a few fields ( supplement name, description and tags) the supplement name one is what I need help with as I have not worked on a complicated form like this and want to get it right and not just offer a messy patch job.

Here is the expected logical order of what happens

  1. user adds a new supplement by clicking on the field and begins typing "creatine" for example
  2. there is a query sent out that fetches products based on the entry into the input and returns a JSON that are offered as suggestions
  3. user clicks the suggestion "creatine"
  4. field is populated and binds
  5. we add another entry through the "add option" and repeat for X amount of products we want to add.

What actually happens

  1. user adds new supplement by clicking the field and types "creatine" suggestion request is sent off and populates the dropdown
  2. user clicks on the suggestion "creatine" the field takes that value
  3. value is actually blank
  4. user adds another supplement but the previous selection is in the field
  5. user clears it and types again
  6. value is blank

What needs to happen is the user can add X amount of supplements and able to grab whatever option from the dropdown recommendation and it is added to the form group array and does not interfere with the other form group array values.

I know this is not the right way to bind the form and I don't think it's right the way i'm binding the mat input field to trigger the query and this is the reason why I'm asking the question again, to not offer a patch job.

Component code

import { Subscription } from 'rxjs/Subscription';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { UtilitiesService } from '../../utilities/utilities.service';
import { GetSupplementsService } from './get-supplements.service';
@Component({
  selector: 'app-supplements',
  templateUrl: './supplements.component.html',
  styleUrls: ['./supplements.component.css'],
  providers: [GetSupplementsService],
})

export class SupplementsComponent implements OnInit {
  supplementForm: FormGroup;
  queryField: FormControl = new FormControl();
  private supplementInventoryResults: Array<ISupplementInventoryResponse>;
  private eventForm: FormGroup;
  private searchResults: any;

  private searchSubscription: Subscription;
  private addSupplementSubscription: Subscription;

  subcription: Subscription;

  constructor (
    private bottomSheet: MatBottomSheet,
    private _fb: FormBuilder,
    private ref: ChangeDetectorRef,
    private _utils: UtilitiesService,
    private getSupplements: GetSupplementsService,
    private router: Router
  ) { }

  public ngOnInit(): void {
    this.browsingStackHistory = false;
    this.loading = true;

    
    this.supplementForm = this._fb.group({ // the form in question
      entryArray: this._fb.array([
        this.getUnit()
      ])
    });

    this.searchSubscription =
      this.queryField.valueChanges
        .debounceTime(600)
        .distinctUntilChanged()
        .switchMap((query) => this.getSupplements.search_supplement_by_category(query))
        .subscribe((result) => {
          this.searchResults = result;
        });
  }

  public ngOnDestroy(): void {
    this.subcription.unsubscribe();
  }


  private getUnit(): FormGroup {
    return this._fb.group({
      supplementName: [''],
      description: [''],
      tags: ['']
    });
  }

  private addUnit(): void {
    const control = <FormArray>this.supplementForm.controls['entryArray'];
    control.push(this.getUnit());
  }

  private removeUnit(i: number): void {
    const control = <FormArray>this.supplementForm.controls['entryArray'];
    control.removeAt(i);
  }

  private addSupplement(): void { // this will do the post to the service
    const supplementObject = {
      start: this._utils.get_upload_time(),
      data: this.supplementForm.value,
      rating: 0
    };

  }
}

Template

[![<mat-tab label="Add Stack (Test)">
    <div style="padding:8px;">
      <div fxLayout="row wrap">
        <div fxFlex.gt-sm="50%" fxFlex="100">
          <h1>Add New Supplements Stack</h1>
          <form \[formGroup\]="supplementForm" class="log-workout">
            <!-- Start form units array with first row must and dynamically add more -->
            <div fxLayout="column" fxLayoutAlign="center center" class="row-height">
              <div formArrayName="entryArray">
                <mat-divider></mat-divider>
                <!-- loop throught units -->
                <div *ngFor="let reps of supplementForm.controls.entryArray.controls; let i=index">
                  <!-- row divider show for every nex row exclude if first row -->
                  <mat-divider *ngIf="supplementForm.controls.entryArray.controls.length > 1 && i > 0"></mat-divider>
                  <br>
                  <!-- group name in this case row index -->
                  <div \[formGroupName\]="i">
                    <!-- unit name input field -->
                    <div class="row">
                      <mat-form-field class="example-form">
                        <input matInput placeholder="Supplement Name" \[formControl\]="addSupplementField"
                          formControlName="supplementName" \[matAutocomplete\]="auto">
                        <mat-autocomplete #auto="matAutocomplete">
                          <mat-option *ngFor="let product of supplementResults" \[value\]="product?.product_name">
                            <img class="example-option-img" aria-hidden \[src\]="product?.product_image" height="25">
                            {{product?.product_name}}
                          </mat-option>
                        </mat-autocomplete>
                      </mat-form-field>
                      <mat-form-field class="example-form">
                        <input matInput placeholder="Description" formControlName="description" required>
                      </mat-form-field>
                      <mat-form-field class="example-form">
                        <input matInput placeholder="Tags" formControlName="tags" required>
                      </mat-form-field>
                    </div>
                    <!-- row delete button, hidden if there is just one row -->
                    <button mat-mini-fab color="warn" *ngIf="supplementForm.controls.entryArray.controls.length > 1"
                      (click)="removeUnit(i)">
                      <mat-icon>delete forever</mat-icon>
                    </button>
                  </div>
                </div>
                <!-- New unit button -->
                <mat-divider></mat-divider>
                <mat-card-actions>
                  <button mat-raised-button (click)="addUnit()">
                    <mat-icon>add box</mat-icon>
                    Add Other Product
                  </button>
                </mat-card-actions>
                <button mat-raised-button (click)="addSupplement()">
                  <mat-icon>add box</mat-icon>
                  Add Supplement
                </button>
              </div>
            </div>
            <!-- End form units array -->
          </form>
        </div>
      </div>
    </div>][1]][1]
1

1 Answer 1

0

Having the below when the getUnit() function is called apparently binds it in the sense it will operate independently and without conflicts.

  private getUnit(): FormGroup {
    const formGroup = this._fb.group({
      supplementName: [''],
      review: [''],
      rating: [''],
      notes: [''],
      tags: ['']
    });

    formGroup.get('supplementName').valueChanges
      .debounceTime(300)
      .distinctUntilChanged()
      .switchMap((search) => this.getSupplements.search_supplement_by_category(search))
      .subscribe((products) => {
        this.supplementResults = products;
      });
    return formGroup;
  }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.