0

I have created common input field which can be usable across app and it will work with or without reactive form.

For e.g.: I have created common input angular component but it works with reactive form only as it has formGroup and formControlName.

input.html:

    <div class="form-control" *ngIf="isRequired" [formGroup]="parentForm">
      <label class="label">
        {{labelText}}
      </label>
      <input [type]="inputType" class="input"  [control]="control" [formControlName]="formControlNameText" [placeholder]="placeholderText">
    </div>

input.ts:

    import { Component, OnInit, Input } from '@angular/core';
    
    @Component({
      selector: 'app-input',
      templateUrl: './input.component.html',
      styleUrls: ['./input.component.scss'],
    })
    export class InputComponent implements OnInit {
    
      @Input() parentForm: any;
      @Input() labelText: string;
      @Input() inputType: string = "text";
      @Input() formControlNameText: string;
      @Input() placeholderText: string;
      @Input() isRequired: boolean = false;
      @Input() requiredMsg: string;
      @Input() maxlengthMsg: string;
      @Input() control: any;
      @Input() type: string;
    
      constructor() { }
    
      ngOnInit() { }
    
    }

Call from one of my form Page:

<app-input parentForm="surveyResponseForm" labelText="test" inputType="text" placeholderText="placeholder"  
    formControlNameText="authorName"  control="" isRequired=true id="authorName">
</app-input>

How do I use this common input if I want to use this without form? I mean how do I use this selector: app-input in a component which doesn't have any form.

Sunil Kumar Das
  • 372
  • 1
  • 2
  • 12
Krunal Lathia
  • 75
  • 2
  • 14
  • please check [this SO](https://stackoverflow.com/questions/73455294/how-do-i-get-access-to-from-control-from-another-component-in-angular/73457780#73457780) – Eliseo Feb 01 '23 at 08:30

2 Answers2

1

You could add an @Input() property to your component, for example useInForm: boolean, and check its value in your template. If useInForm is true, you would use the [formGroup] and formControlName properties, otherwise you would use a regular element without those properties example in the withoutFormTemplate.

<div class="form-control" *ngIf="isRequired && useInForm; else withoutFormTemplate" [formGroup]="parentForm">
  <label class="label">
    {{labelText}}
  </label>
  <input [type]="inputType" class="input"  [control]="control" [formControlName]="formControlNameText" [placeholder]="placeholderText">
</div>

<ng-template #withoutFormTemplate>
    <input [(ngModel)]="control" [type]="inputType" class="input" [placeholder]="placeholderText">
<ng-template>
sfelli
  • 176
  • 5
  • Thank you for answering, in #withoutFormTemplate i am not getting values of ngModel. How to get back values from input class to parent class ? – Krunal Lathia Jan 19 '23 at 15:27
  • 1
    Wlc we are already had the two-way data binding by doing '[(ngModel)]' , you can also use the (ngModelChange) event to listen for changes to the input element's value, like this: – sfelli Jan 20 '23 at 13:52
  • please check [this SO](https://stackoverflow.com/questions/73455294/how-do-i-get-access-to-from-control-from-another-component-in-angular/73457780#73457780) – Eliseo Feb 01 '23 at 08:30
0

I solve more or less same problem by creating a FormGroup. It's not easiest solution, but that working on multiple scenarios. If not, maybe that give you some clues how to solve your problem...

Form component ts

// Reactive Forms
form: FormGroup;    

constructor(private formBuilder: FormBuilder) { }

ngOnInit() {
  // Form structure and validators
  this.form = this.formBuilder.group({
    'user' : this.formBuilder.group({
      'username' : ['', Validators.required],
      'email' : ['', [Validators.required, Validators.email]]
    }),
    'identity' : this.formBuilder.group({
      'firstname' : ['', Validators.required],
      'lastname'  : ['', Validators.required],
      'address' : this.formBuilder.group({
        'street' : ['', Validators.required],
        'city'  : ['', Validators.required],
      })
    })
  });        
}

onSubmit() {
    // Get object with same structure as form but only with values
    console.log(this.form.value);
    alert('Form is ' + (this.form.invalid ? 'invalid' : 'valid'));
}

Form component html

<form [formGroup]="form" (ngSubmit)="onSubmit()">
    <form-text [formGroupParent]="form.get(['user'])"
               [formGroupControlName]="'username'">
    </form-text>
    <form-text [formGroupParent]="form.get(['user'])"
               [formGroupControlName]="'email'">
    </form-text>
    <hr>
    <form-text [formGroupParent]="form.get(['identity'])"
               [formGroupControlName]="'firstname'">
    </form-text>
    <form-text [formGroupParent]="form.get(['identity'])"
               [formGroupControlName]="'lastname'">
    </form-text>
    <hr>
    <form-text [formGroupParent]="form.get(['identity','address'])"
               [formGroupControlName]="'street'">
    </form-text>
    <form-text [formGroupParent]="form.get(['identity','address'])"
               [formGroupControlName]="'city'">
    </form-text>
    <button type="submit">Submit</button>
</form>

Custom input component ts (form-text)

// Needed to bind formControlName
@Input() formGroupParent: FormGroup;
@Input() formGroupControlName: string;
// FormControl store validators
control: FormControl;

ngOnInit() {
    // Fetch Form control (validator) from FormGroup parent
    this.control = <FormControl>this.formGroupParent.get(this.formGroupControlName);
}

Custom input component html (form-text)

<ng-container [formGroup]="formGroupParent">
  <label>{{formGroupControlName}}</label> 
  <input type="text" formControlName="{{formGroupControlName}}">
</ng-container
Camille
  • 2,439
  • 1
  • 14
  • 32
  • 1
    please check [this SO](https://stackoverflow.com/questions/73455294/how-do-i-get-access-to-from-control-from-another-component-in-angular/73457780#73457780) – Eliseo Feb 01 '23 at 08:30