Laurens
Laurens

Reputation: 1031

How to use @HostBinding with @Input properties in Angular 2?

(Angular 2 RC4)

With @HostBinding we should be able to modify properties of the host, right? My question is, does this apply to @Input() properties as well and if so, what is the correct usage? If not, is there another way to achieve this?

I made a Plunker here to illustrate my problem: https://embed.plnkr.co/kQEKbT/

Suppose I have a custom component:

@Component({
  selector: 'custom-img',
  template: `
    <img src="{{src}}">
  `
})
export class CustomImgComponent {
  @Input() src: string;
}

And I want to feed the src property with an attribute directive:

@Directive({
  selector: '[srcKey]'
})
export class SrcKeyDirective implements OnChanges {
  
  @Input() srcKey: string;
  @HostBinding() src;
  
  ngOnChanges() {
    this.src = `https://www.google.com.mt/images/branding/googlelogo/2x/${this.srcKey}_color_272x92dp.png`;
  }
}

Why can't this directive change the [src] input property of the custom component?

@Component({
  selector: 'my-app',
  directives: [CustomImgComponent, SrcKeyDirective],
  template: `<custom-img [srcKey]="imageKey"></custom-img>`
})
export class AppComponent {
  imageKey = "googlelogo";
}

Thanks!

Upvotes: 52

Views: 37787

Answers (6)

nvvetal
nvvetal

Reputation: 1793

@Input() appFallback: string;

@HostBinding('attr.src') @Input() src: string;

@HostListener('error') loadFallback(): void {

  if (this.src === this.appFallback) {
    return;
  }
  this.src = this.appFallback;
}

Upvotes: 3

dabeng
dabeng

Reputation: 1450

  1. declare hostbinding property with input property.

    @HostBinding('attr.aaa') @Input() aaa: boolean = false;
    
  2. set hostbinding property to input property

    @Input() aaa: string;
    @HostBinding('attr.bbb') ccc: string;
    
    ngOnInit(){
      this.ccc = this.aaa;
    }
    

Upvotes: 6

SystemR
SystemR

Reputation: 313

If your @Input is an object, you can do:

@Input() settings: Settings;

@HostBinding('class.active')
public get isActive(): boolean {
  return this.settings.isActive;
}

Upvotes: 20

Frank N
Frank N

Reputation: 10396

BEWARE on using get with hostbinding.

At least I an endless recursion (thousands of cycles). Put a console.log in the get function to check:

@HostBinding('@someAnim') get whatever() {
    console.log('#### traffic.....');
    return true;
}

I even got that trouble, when just changing some class (so nothing around fancy Angular animation) and not even relying on any other class member whatsoever:

@HostBinding('class.foobar') get _____() {
    console.log('#### more traffic.....');
    return true;
}

enter image description here

An addition, it doesn't hurt to have this in your component while developing (as a “free flow canary”):

ngOnChanges(changes: SimpleChanges) {
    console.log('#### more traffic.....');
}

You should only see one log entry per, say, state-change and instantiated component, anyway not thousands...

—At last— I had luck with this one:

  • distinct variable for incoming (@Input) and outgoing (@HostBinding)
  • changing the outgoing upon change
  • → no „free flow“
    @Input() animTileAttrib = false;
    @HostBinding('@animTile') paramPack: AnimParams = { value: false, params: {}};

    ngOnChanges(changes: SimpleChanges) {
        console.log('#### traffic.....');
        if ('animTileAttrib' in changes) {
            this.paramPack = { value: changes.animTileAttrib.currentValue, params: {} };
        }
    }

Upvotes: 0

Piizei
Piizei

Reputation: 1269

You need to combine the decorators like this:

@HostBinding('class.active') @Input() active: boolean = false;

Upvotes: 118

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657268

@HostBinding() doesn't create property bindings to properties of the host component. That might be worth a bug report though ;-)

I got it working by a workaround with exportAs and a template variable but that is quite ugly. https://plnkr.co/edit/TobNVn?p=preview

After some consideration, I think it should work. Otherwise I wouldn't know what @HostBinding() src; would do at all.

@HostBinding('attr.src') src; or @HostBinding('class.src') src; are the more common cases.

Upvotes: 9

Related Questions