简体   繁体   English

在Angular2指令中动态更新自定义属性的值

[英]Dynamically Update value of custom attribute in Angular2 Directive

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. 我已经编写了一个指令和一个组件,我需要将值从Component传递给指令,并相应地隐藏元素。 In simple words I'm trying to create an directive similar to ng-show and ng-hide of Angular1 in Angular2. 用简单的话说,我正在尝试创建类似于Angular2中Angular1的ng-show和ng-hide的指令。

headermenu.component.ts 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 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. 我需要传递从虚拟服务收集的dataFlag值的值, 并将其发送到指令,指令将相应地显示/隐藏该元素。

Note: dataFlag - hold the value true/ false. 注意:dataFlag-保留值true / false。

Currently I am not able to get any output from it so commented the code. 目前,我无法从中获得任何输出,因此注释了代码。

To be able to pass a value to a component or directive use @Input() 为了能够将值传递给组件或指令,请使用@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 但是您也可以使用所有元素都具有的hidden属性

<li [hidden]="!showHeader"

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). 我不明白为什么在具有[hidden]属性和* ngIf(也可以在其中传递函数的位置)的情况下,为什么需要一个自定义指令来隐藏元素。 But anyway to get Information from attribute directive you have to use @Input() with the name of the selector in there like this: 但是无论如何要从属性指令中获取信息,您必须使用@Input()及其中的选择器名称,如下所示:

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 您必须使用OnInit,因为输入值在构造函数中不可用

I tried something, maybe this will help in showing that we can update the values of custom attributes in Angular. 我尝试了一些方法,也许这将有助于显示我们可以更新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. 在这里,我创建了2个组件app-list-displayapp-list-item-detail其思想是使用前者以列表方式显示数据,并且当用户单击列表中的任何项目时,将自定义事件发出,触发对主app组件的操作。

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. 然后, app组件更改变量的值,然后将该变量作为自定义属性提供给另一个app-list-item-detail组件。

Here is the code for app-list-display.html 这是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 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. app-list-item-detail.html这只是一个示例文本,以显示当用户单击列表中的不同项目时数据发生的变化。

<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. app-list-item-detail.ts这是组件的支持ts文件,表明它具有@Input装饰器显示的自定义属性。

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.component.html ,它使用以上两个组件,如下所示

<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 . 如果您在此处在app-list-display组件中注意到,则为自定义事件提供了showSentItem函数。 And to the other component app-list-item-detail a object called someTxData is being injected as a custom attribute. 对于其他组件app-list-item-detail一个名为someTxData的对象作为自定义属性被注入。 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 可以通过一个简单的函数调用来更改在此注入的对象,这也意味着一个简单的自定义事件,在我们的例子中将是showSentItem

So now in app.component.ts 所以现在在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. 如果您看到最后一行, this.someTxData从第一个组件的列表行中分配给对象(由于自定义事件),并且将同一对象馈给第二个组件的custom属性。

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. 抱歉,答案很长。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM