Search code examples
componentsionic2directiveviewchild

Ionic 2 - How to reach a component from inside a directive?


I'm trying to build a directive to display a custom numpad when the control (input) on which the directive is applied is clicked. I'm Working on Ionic 2 RC5.

myPage.html

<ion-content>
  <ion-item>
      <ion-label stacked>Label</ion-label>
      <ion-input dirNumpad type="text" [(ngModel)]="myField"></ion-input>
  </ion-item>
</ion-content>
<ion-footer>
  <numpad #idNumpad hidden></numpad>
</ion-footer>

The Numpad component is in the DOM, at the bottom of the page.

dirNumpad.ts

import { Directive, ElementRef, ViewChild } from '@angular/core';
import { Numpad } from '../../components/numpad/numpad';
@Directive({
  selector: '[dirNumpad]',            // Attribute selector
  host: {
      '(click)':          'onClick()'
  }
})
export class DirNumpad {
  @ViewChild('idNumpad') numpad: Numpad;
  constructor( private el:    ElementRef ) {
  }
  onClick() {
      this.showNumpad();
  }
  showNumpad() {
      console.log(this.numpad);   => undefined
      this.numpad.show();     => error: show property does not exist on undefined
  }
}

numpad.html

<div class="numpad" style="position:absolute; top:auto; left:0; right:0; bottom:0; height:150px;">My Numpad</div>

numpad.ts

import { Component, Input } from '@angular/core';
@Component({
  selector: 'numpad',
  templateUrl: 'numpad.html'
})
export class Numpad {
  constructor() {}
}

My problem: I can not reach the numpad component from inside the directive through ViewChild. console.log(this.numpad) always returns "undefined"! I need it to show the numpad only if user clicks on the input on which the directive is applied...

What am I doing wrong? I'm stucked with this problem, so any help will be appreciated.


Solution

  • ViewChild only applies to the children items of the item. Since the component is not a child in any way of the directive but rather a sibling it cant be received in ViewChild.

    You can pass it as part of an input

    Declare an input in your component

    import { Directive, ElementRef, Input } from '@angular/core';
    import { Numpad } from '../../components/numpad/numpad';
    @Directive({
      selector: '[dirNumpad]',            // Attribute selector
      host: {
          '(click)':          'onClick()'
      }
    })
    export class DirNumpad {
      @Input('numpad') numpad: Numpad;
      constructor( private el:    ElementRef ) {
      }
      onClick() {
          this.showNumpad();
      }
      showNumpad() {
          console.log(this.numpad);   => undefined
          this.numpad.show();     => error: show property does not exist on undefined
      }
    }
    

    and set it in your html

    <ion-content>
      <ion-item>
          <ion-label stacked>Label</ion-label>
          <ion-input dirNumpad [numpad]="idNumpad" type="text" [(ngModel)]="myField"></ion-input>
      </ion-item>
    </ion-content>
    <ion-footer>
      <numpad #idNumpad hidden></numpad>
    </ion-footer>