1

i have the following HTML Form:

<form fxLayout="column" [formGroup]="setPaymentForm" autocomplete="off">
<div class="input-row" fxLayout="row">
    <form class="example-form" [formGroup]="setPaymentClientName">
        <mat-form-field class="example-full-width">
        <input matInput placeholder="Client Name" formControlName="clientName" (ngModelChange) ="getSearchedClients()" aria-label="Clients" [matAutocomplete]="auto" [formControl]="paymt_client_ctrl">
        <mat-autocomplete #auto="matAutocomplete">
            <mat-option *ngFor="let client of filteredClients | async" [value]="client.name">
            <span>{{client.name}}</span> |
            <small> phone: {{client.phone}}</small>
            <small> | address: {{client.address}}</small>
            </mat-option>
        </mat-autocomplete>
        </mat-form-field>
        <br>
    </form>
</div>
<div class="input-row" fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px">
    <mat-form-field class="inputField" fxFlex>
    <input matInput formControlName="payment_amount" placeholder="Payment Amount" type="text">
    </mat-form-field>
</div>
<div class="input-row" fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px">
    <mat-checkbox[checked]='this.isCash' formControlName="isCash"> Cash</mat-checkbox>
</div>
<div class="modal-footer">
              <button mat-raised-button name="addButton" (click)="submitPayment()" color="primary">Set Payment</button>
            </div>
</form>

there are two forms outer form which is setPaymentForm and inner form i called it setPaymentClientName.

i want to get the data of the both form when submitting, so i made the following function:

submitPayment(){
    this.setPaymentForm = this.fb.group({
      clientName: [this.clientName, Validators.required],
      payment_amount: [this.payment_amount],
      isCash: [this.isCash]
    });

but i am getting the following error once i open the form:

PaymentsComponent.html:23 ERROR Error: formGroup expects a FormGroup instance. Please pass one in.

       Example:


    <div [formGroup]="myGroup">
      <input formControlName="firstName">
    </div>

    In your class:

    this.myGroup = new FormGroup({
       firstName: new FormControl()
    });

i am very new to angular 6, i get used to build my web projects with angularjs which is completely deiiferent than angular6. any help is appreciated.

7
  • 1
    Why do you need 2 forms? Commented Aug 23, 2018 at 23:57
  • because i have auto-complete need to be inside a form Commented Aug 23, 2018 at 23:58
  • 1
    Why don't you just put everything inside your outer form? Commented Aug 24, 2018 at 0:01
  • 1
    The error is because you are instantiating the form in your Submit method, which is wrong. You have to initialise the group in the constructor of the class. Commented Aug 24, 2018 at 0:04
  • @AndreFeijo i need nested forms because the auto complete is server side request, i need to get the client name separately by a function, then other data along with client name will be submitted by other function Commented Aug 24, 2018 at 0:13

2 Answers 2

1

Here is what I think you want to do : you form a form with 3 fields.

  • The first one is an autocomplete from allowing you to search for a client
  • next one is the payement amount for this client
  • then you need to know he is payed cash or not

About the error, she's pretty clear, you added a formGroup in your HTML seem to not reference an instance formGroup when your are loading the page. To simply things a FormGroup is just a description or your form.

Futhermore like people said I don't think you need to have 2 forms, one will be enough

Here is your html (a bit simplified for the exemple) with one form and submit type button.

<form fxLayout="column" [formGroup]="clientPayementForm" (ngSubmit)="submitForm()" autocomplete="off">

  <!-- autocomplete client -->
  <mat-form-field class="example-full-width">
    <input matInput placeholder="Client Name" formControlName="clientName" aria-label="Clients" [matAutocomplete]="auto">
    <mat-autocomplete #auto="matAutocomplete">
      <mat-option *ngFor="let client of filteredClients | async" [value]="client.name">
        <span>{{client.name}}</span> |
        <small> phone: {{client.phone}}</small>
        <small> | address: {{client.address}}</small>
      </mat-option>
    </mat-autocomplete>
  </mat-form-field>

  <!-- payement amount -->
  <mat-form-field class="inputField" fxFlex>
    <input matInput formControlName="payment_amount" placeholder="Payment Amount" type="text">
  </mat-form-field>

  <!-- checkbox -->
  <mat-checkbox [checked]='this.isCash' formControlName="isCash"> Cash </mat-checkbox>

  <div class="modal-footer">
    <button mat-raised-button name="addButton" type="submit" color="primary">Set Payment</button>
  </div>
</form>

In the TS :

export class MyComponent {

 clientAutocompleteControl = new FormControl();
 clientPayementForm : FormGroup;

 constructor(private fb: FormBuilder){
 }

 ngOnInit(){
   // here you initialize the form used by the formGroup
   this.clientPayementForm = this.fb.group({
      clientName: [this.clientName, Validators.required],
      payment_amount: [this.payment_amount],
      isCash: [this.isCash]
    });

    // manage the autocomplete value to make the auto complete component work
    // you should call you getSearchedClients perhaps with a mergeMap pipe from rxjs
    this.clientPayementForm.controls.clientName.statusChanges.subscribe(pipe(debounceTime(500), ...));
 }

 submitForm(){
  if(this.clientPayementForm.valid){
    // your form is valid :)  you can now call you API to save data
  }
 }

}

Hop it can help, tell me if you need more details

Sign up to request clarification or add additional context in comments.

Comments

0

You can implement nested forms in Angular. Have a look at the below link: https://medium.com/spektrakel-blog/angular2-building-nested-reactive-forms-7978ecd145e4

You need to use formGroups to differentiate & also add multiple buttons to get your auto-complete data.

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.