Home > Enterprise >  How to process an attribute value by a component
How to process an attribute value by a component

Time:08-25

Let's say I have a very basic component that adds functionality to a given text. For example:

@Component({
  selector: 'app-clickable-key',
  template: '<span (click)="doSomething()">{{ key }}</span>',
  styleUrls: ['./translated-text.component.scss']
})
export class TranslatedTextComponent {
  @Input() key: string;
  
  doSomething(): void {
    this.key = `${this.key} clicked!`;
  }
}

Usage would be:

<app-clickable-key key="Hello!"></app-clickable-key>

Now I would like to append the above functionality not only to tree nodes but also to attribute values:

<3rd-party-input customLabel="How to make this clickable as well?"></3rd-party-input>

...Which is essentially just a wrapper of a label (<label>{{ customLabel }}</label>)

If this functionality was only for a transformation of the text, then I would be able to use pipes, but in this case, I need to change the template of that placeholder. Is that somehow possible?

CodePudding user response:

This seems to be adding behavior to the element. For such a case, I would suggest you extract your functionality in a reusable Directive. The behavior can be attached to any DOM easily.

A directive can be pretty simple, it can use textContent HostBinding decorator, and returned value will be set to DOM node innerText. Just make sure while using directive pass attribute value to it. For eg clickable="key" indicate a directive to read the initial value from key attribute.

Directive

@Directive({
  selector: '[clickable]',
})
export class ClickableTextComponent {
  @Input() clickable: string;
  private text = '';

  constructor(private el: ElementRef) {}

  @HostBinding('textContent') get textContent() {
    return this.text;
  }

  @HostListener('click')
  doSomething(): void {
    this.text = `${this.text} clicked!`;
  }

  ngOnInit() {
    this.text = this.el.nativeElement.getAttribute(this.clickable);
  }
}

Usage

<span 
  clickable="key"
  key="Something is funny">
</span>

<hr />

<label
  clickable="customLabel"
  customLabel="This is label working with Directive"
>
</label>

Stackblitz

CodePudding user response:

For that you can use the control value accessor

<app-custom-input
  label="My Custom label"
  [(ngModel)]="inputOne"
></app-custom-input>

Create component with providers

@Component({
  selector: 'app-custom-input',
  templateUrl: './custom-input.component.html',
  styleUrls: ['./custom-input.component.scss'],

  // Step 1: copy paste this providers property
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomInputComponent),
      multi: true
    }
  ]
})

Here is complete example

  • Related