Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2: passing ALL the attributes to the child component

Don't even know the proper terminology to explain this problem

so, imagine this scenario...

There is a form-input-component and capturing some attributes and passing it down to the markup inside

<form-input placeholder="Enter your name" label="First name" [(ngModel)]="name" ngDefaultControl></form-input>

So, this is the markup, hope is pretty self explanatory...

obviously in the ts I have

  @Input() label: string = '';
  @Input() placeholder: string = '';

and then in the view I have something down these lines

<div class="form-group">
    <label>{{label}}
    <input type="text" [placeholder]="placeholder" [(ngModel)] = "ngModel">
</div>

Now, all works fine so far...

but let's say I want to add the validation rules around it... or add other attributes that I don't capture via @Input()

How can I pass down anything else that comes down from <form-input> to my <input> in the view?

like image 261
DS_web_developer Avatar asked May 04 '17 14:05

DS_web_developer


People also ask

How do you pass data from parent component to child component?

To let Angular know that a property in a child component or directive can receive its value from its parent component we must use the @Input() decorator in the said child. The @Input() decorator allows data to be input into the child component from a parent component.

Which decorator is preferable to pass data from a parent component to a child component?

@Input Decorator: This is used to define an input property and it is used to send data from parent component to child component. @Output Decorator: This is used to bind a property of the type of Angular EventEmitter class and it is used to pass data from child component to parent component.


2 Answers

For the lazy ones:

export class FormInput implements OnInit {
  @ViewChild(NgModel, {read: ElementRef}) inpElementRef: ElementRef;

  constructor(
    private elementRef: ElementRef
  ) {}
  
  ngOnInit() {
    const attributes = this.elementRef.nativeElement.attributes;
    const inpAttributes = this.inpElementRef.nativeElement.attributes;
    for (let i = 0; i < attributes.length; ++i) {
      let attribute = attributes.item(i);
      if (attribute.name === 'ngModel' ||
        inpAttributes.getNamedItemNS(attribute.namespaceURI, attribute.name)
      ) {
        continue;
      }
      this.inpElementRef.nativeElement.setAttributeNS(attribute.namespaceURI, attribute.name, attribute.value);
    }
  }
}

ngAfterViewInit won't work if you nest multiple components which pass attributes, because ngAfterViewInit will be called for inner elements before outer elements. I.e. the inner component will pass its attributes before it received attributes from the outer component, so the inner most element won't receive the attributes from the outer most element. That's why I'm using ngOnInit here.

like image 93
fishbone Avatar answered Sep 18 '22 17:09

fishbone


You could iterate on the DOM attributes of your component :

import { ElementRef } from '@angular/core';
...

export class FormInput {
  constructor(el: ElementRef) {
    // Iterate here over el.nativeElement.attributes
    // and add them to you child element (input)
  }
}
like image 23
soywod Avatar answered Sep 17 '22 17:09

soywod