gh0st
gh0st

Reputation: 1714

Using directives to add form inputs to component

I have a single component which handles form input. This component takes care of validation and the template for the form and then passes the form data up to it's parent component when valid. I'm sharing this component across many other modules in my app which share the same responsibility. I've come to a point though now where the inputs for the form will change ever so slightly. So I thought maybe I can use directives in this situation. This is what I was thinking.

Right now the component is as such

<search-form
    (onSubmit)=submitEvent...
    (onClear)=clearEvent...></search-form>

And then the template has 6 input fields. But how might one go about turning those 6 input fields into directives? So that I could change the above into

<search-form
    firstName
    lastName
    dateOfBirth
    (onSubmit)=...
    (onClear)=...></search-form>

Or perhaps is there no good way going about this?

Upvotes: 0

Views: 252

Answers (1)

lenilsondc
lenilsondc

Reputation: 9800

Directives are meant to attach behavior to elements in the DOM; therefore, I think it's not the right tool for the job. Using child components however, might be a solution for you depending on your goals. In addition, using child components is a more component-like way to do things and will make things more readable and easier to understand.

<search-form (onSubmit)="submitEvent($event)" (onClear)="clearEvent($event)">
    <search-field name="firstName"></search-field>
    <search-field name="lastName"></search-field>
    <search-field name="dateOfBirth"></search-field>
</search-form>

This way you can use @ContentChildren() as a decorator property to extract a QueryList<SearchField> containing all SearchField and iterate over each one to render your inputs.

import { Component, ContentChildren, QueryList, Input } from '@angular/core';

@Component({
  selector: 'search-field',
  template: ``
})
export class SearchFieldComponent {
  @Input('name') name: string;
}

@Component({
  selector: 'search-form',
  template: `
    <div *ngFor="let field of fields">
      <label [for]="field.name">{{ field.name }}</label>
      <input [name]="field.name" [placeholder]="field.name" type="text">
    </div>
  `
})
export class SearchFormComponent {
  @ContentChildren(SearchFieldComponent) fields: QueryList < SearchFieldComponent > ;
}

Working Example on Plunkr

Upvotes: 1

Related Questions