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.

1
  • please check this SO Commented Feb 1, 2023 at 8:30

2 Answers 2

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>
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for answering, in #withoutFormTemplate i am not getting values of ngModel. How to get back values from input class to parent class ?
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: <input [(ngModel)]="control" (ngModelChange)="onModelChange($event)">
please check this SO
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

1 Comment

please check this SO

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.