Katana24
Katana24

Reputation: 8959

Adding more than one input to a structural directive

I've been following along with an example of how to use structural directives here - but one thing I'd like to be-able to do would be to pass in some data from the card.component class into the delay.directive.ts. How do I do this?

export class DelayContext {
  /**
    - Line below demonstrated passing into an array of functions that can be called in the HTML
  */
  // constructor(private loadTime: number, private myFunc: Array<Function>) {}
  constructor(private loadTime: number, private delayService: DelayService) {}
}

@Directive({ selector: '[delay]'})
export class DelayDirective {
  constructor(
    private templateRef: TemplateRef<DelayContext>,
    private viewContainerRef: ViewContainerRef
  ) { }

  @Input('delay')
  set delayTime(time: number) {
    setTimeout(
      () => {
        let embedView = this.viewContainerRef.createEmbeddedView(
          this.templateRef,
          // new DelayContext(performance.now(),[this.foo,this.bar])
          new DelayContext(performance.now(), new DelayService())
        );
        console.log(embedView);
      },
      time);
  }
}

I've tried defining another input parameter like so:

@Input('foo')
  set fooParameter(parameters) {
    console.log(parameters);
  }

and then attempted to pass it data in the HTML several different ways, of which none worked. Here's what I've tried:

 <card *delay="500 * item; let loaded = loadTime; foo: 'test'">
        <div class="main">
          <button>{{item}}</button> 
        </div>
        <div class="sub">{{loaded | number:'1.4-4'}}</div>
      </card>

This throws an error - Can't bind to 'delayFoo' since it isn't a known property of 'card' I didn't expect this error because we are in the binding parts for the delay directive.

Can this directive take any more input?

EDIT

Thanks to Gunter for answering the first part of the question. But if I define an object in the card.component.ts like this:

bar: Object = {
        val: 'Some Value'
    };

and then attempt to pass it to the directive:

<card *delay="500 * item; let loaded = loadTime; foo: bar">

this always prints undefined:

 @Input('delayFoo')
  set setFoo(obj) {
    console.log(obj)
  }

Are we outside the context of card here? Also - the complete card component:

import { Component } from '@angular/core';
import { DelayService } from './delay.service';

@Component({
    selector: 'card',
    template: `
      <ng-content select=".main"></ng-content>
    <ng-content select=".sub"></ng-content>`,
    styles: [
        `
        :host {
      display: inline-block;
      font-family: 'Helvetica', sans-serif;
      font-weight: 300;
      margin: 1rem;
      animation: fade-in 2s;
    }

    :host >>> .main {
      padding: 2rem;
      background: #e3f2fd;
      font-size: 2rem;
      text-align: center;
    }

    :host >>> .sub {
      padding: 0.4rem;
      background: #ef5350;
    }
    @keyframes fade-in {
          from { opacity: 0; }
          to   { opacity: 1; }
        }
        /* Firefox < 16 */
        @-moz-keyframes fade-in {
          from { opacity: 0; }
          to   { opacity: 1; }
        }
        /* Safari, Chrome and Opera > 12.1 */
        @-webkit-keyframes fade-in {
          from { opacity: 0; }
          to   { opacity: 1; }
        }
        `
    ]
})
export class CardComponent {
    bar: Object = {
        val: 'Some Value'
    };
    ngOnInit() {}
}

EDIT

A working plunker can be found here

Upvotes: 3

Views: 3229

Answers (1)

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

Reputation: 657308

Rename it to

@Input('delayFoo')

Inputs in structural directives need to include the selector.

Upvotes: 3

Related Questions