0

I have written a Directive and a Component, I need to pass the value from the Component to the directive and accordingly hide the element. In simple words I'm trying to create an directive similar to ng-show and ng-hide of Angular1 in Angular2.

headermenu.component.ts

import {Component} from 'angular2/core';
import {DataService} from './data-service.service';
import {ShowHeaderDirective} from './show-header.directive';
@Component({
selector: 'header-menu',
template: `
    <header class="login-header">
    <div class="header-top">
        <div class="container">
          <nav class="navbar navbar-default">
            <div class="container-fluid">
             <div>
                <ul class="nav navbar-nav navbar-right">
                  <li [showHeader]="dispFlag"><a href="javascript:void(0)">Mr. Abc!</a></li>
                  <li><span>|</span></li>
                </ul>
              </div>
            </div><!--/.container-fluid -->
          </nav>
        </div>
    </div>
</header>
`,
directives: [ShowHeaderDirective],
providers:[DataService]
})

export class HeaderComponent {
    dispFlag;
constructor(dataService: DataService){
    this.dispFlag=dataService.headerDisplayFlag;
}
}

show-header.directive.ts

import {Directive, ElementRef, Renderer, Input} from 'angular2/core';

@Directive({
    selector: '[showHeader]'
})

export class ShowHeaderDirective{
private _el:HTMLElement;
constructor(private el: ElementRef, private renderer: Renderer){
    debugger;
    /* alert(this.el.nativeElement.attributes.showheader.value);
    if(this.el.nativeElement.attributes.showheader.value=="false"){
        this.el.nativeElement.style.display="none";
    } */
}
}

I need to pass the value of dataFlag value which is collected from dummy service and send it to directive and directive will accordingly show/hide the element.

Note: dataFlag - hold the value true/ false.

Currently I am not able to get any output from it so commented the code.

3 Answers 3

1

I don't understand why do you need a custom directive for hiding elements while you have [hidden] attribute and *ngIf (Where you can pass functions too). But anyway to get Information from attribute directive you have to use @Input() with the name of the selector in there like this:

export class ShowHeaderDirective implements OnInit{

@Input('showHeader') somealias:boolean;
construct(private el: ElementRef){}

 ngOnInit() {
    if(this.somealias === true){
       //do something with your element
    }
 }

You must use OnInit because the input value is not available in the constructor

Sign up to request clarification or add additional context in comments.

Comments

1

To be able to pass a value to a component or directive use @Input()

export class ShowHeaderDirective{

  @Input() isHidden:boolean = false;  

  private _el:HTMLElement;
  constructor(private el: ElementRef, private renderer: Renderer){
    debugger;
    /* alert(this.el.nativeElement.attributes.showheader.value);
    if(this.el.nativeElement.attributes.showheader.value=="false"){
        this.el.nativeElement.style.display="none";
    } */
  }
}

and use it like

<li showHeader isHidden="!showHeader"

You can also use the selector name for the input

@Input() showHeader:boolean = false;  

and use it like

<li [showHeader]="!showHeader"

But you can also use the hidden attribute that all elements have

<li [hidden]="!showHeader"

8 Comments

[showheader]="!showHeader" is not either displaying / hiding the element. Do I need to add some more code in the directive
I have tried to change the value true and false for the showHeader but <li [showHeader]="!showHeader" this line doesn't works for me.
Why don't you just use [hidden]? Can you please elaborate a bit more what the expected behavior is?
Gunter, All the solutions you have provided I have tried to use it as it is, but still I am not able to display or hide the entity. I already have used the [hidden] as well as [showHeader], and there is no any changes which I see. can you please create a simple plunkr if possible, Thanks in advance
Would you mind explaining what you actuallly try to accomplish?
|
1

I tried something, maybe this will help in showing that we can update the values of custom attributes in Angular.

Here I have created 2 components app-list-display and app-list-item-detail the idea is to use the former to show data in a list fashion, and when the user clicks on any of the item in the list an custom event is emitted which triggers an action on the main app component.

app component then changes a value of a variable , this variable is then fed as an custom property to the other app-list-item-detail component.

Here is the code for app-list-display.html

<ul class="list-group" style="float:left margin-left=0px;">
  <li (click)="showItem(item)" *ngFor="let item of items" class="list-group-item list-group-item-action text-justify">{{item.name}}</li>
</ul>

app-list-display.ts

import { Component, OnInit , Input , Output , EventEmitter } from '@angular/core';

@Component({
  selector: 'app-list-display',
  templateUrl: './list-display.component.html',
  styleUrls: ['./list-display.component.css']
})
export class ListDisplayComponent implements OnInit {

  @Input('itemsToBeDisplayed')items:any; 
  @Output('transferItem') transfer = new EventEmitter<{name:string}>();

  constructor() { }

  ngOnInit() {
  }

  showItem(item){
    console.log("in showItem "+JSON.stringify(item,null,2))
    this.transfer.emit(item)
  }

}

app-list-item-detail.html This just has a sample text to show data changing when the user clicks on different items in the list.

<h4>We are in list detail component
{{showSomething.something}}</h4>

app-list-item-detail.ts This is the supporting ts file of the component which indicates that it has a custom attribute shown by the @Input decorator.

import { Component, OnInit , Input} from '@angular/core';

@Component({
  selector: 'app-list-item-detail',
  templateUrl: './list-item-detail.component.html',
  styleUrls: ['./list-item-detail.component.css']
})
export class ListItemDetailComponent implements OnInit {

  @Input()showSomething:any;

  constructor() { }

  ngOnInit() {
  }

}

Now in the app.component.html, which uses the above two components, as shown below

<app-list-display [itemsToBeDisplayed]="someArrayData" (transferItem)="showSentItem($event)">

<app-list-item-detail [showSomething]="someTxData">
</app-list-item-detail>

If you notice here in the app-list-display component the custom event is supplied a function showSentItem. And to the other component app-list-item-detail a object called someTxData is being injected as a custom attribute. The object injected here can be changed by a simple function call, which can also mean a simple custom event which in our case will be showSentItem

So now in app.component.ts

import { Component } from '@angular/core';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
 someArrayData = [{name:"John"},{name:"Jane"}];
  someTxData:any;
  showSentItem(item){
    item.something = item.name
    this.someTxData = item;
  } 
}

If you see the last line this.someTxData is being given the object from the row of the list from the first component(thanks to custom events), and this same object is being fed to the second component custom attribute.

So here ideally, custom event on one component is talking to the custom attribute of the other via the implementor.

Apologies for the long answer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.