【问题标题】:How to pass multiple parameter to @Directives (@Components) in Angular with TypeScript?如何使用 TypeScript 将多个参数传递给 Angular 中的 @Directives (@Components)?
【发布时间】:2016-12-15 01:47:01
【问题描述】:

由于我将@Directive 创建为SelectableDirective,我有点困惑,关于如何将多个 值传递给自定义指令。我进行了很多搜索,但没有在 Angular 中使用 Typescript 找到正确的解决方案。

这是我的示例代码:

父组件为MCQComponent:

import { Component, OnInit } from '@angular/core';
import { Question } from '../question/question';
import { AppService } from '../app.service/app.service';
import { SelectableDirective } from '../selectable.directive/selectable.directive';
import { ResultComponent } from '../result-component/result.component';

@Component({
    selector: 'mcq-component',
    template: "
         .....
        <div *ngIf = 'isQuestionView'>
            <ul>
                <li *ngFor = 'let opt of currentQuestion.options' 
                    [selectable] = 'opt'
                    (selectedOption) = 'onOptionSelection($event)'>
                    {{opt.option}}
                </li>
            </ul>
            .....
        </div>

    "
    providers: [AppService],
    directives: [SelectableDirective, ResultComponent]
})
export class MCQComponent implements OnInit{
    private currentIndex:any = 0;
    private currentQuestion:Question = new Question();
    private questionList:Array<Question> = [];
    ....
    constructor(private appService: AppService){}
    ....
}

这是一个具有自定义指令 [selectable] 的父组件,它接受一个名为 opt 的参数。

这是该指令的代码:

import { Directive, HostListener, ElementRef, Input, Output, EventEmitter } from '@angular/core'
import { Question } from '../question/question';

@Directive({
    selector: '[selectable]'
})
export class SelectableDirective{
    private el: HTMLElement;
    @Input('selectable') option:any;

    ...
}

所以这里我想从父组件传递更多参数,我该如何实现呢?

【问题讨论】:

    标签: javascript angular typescript angular6


    【解决方案1】:

    与上述解决方案类似,我在指令中使用了@Input(),并且能够在指令中传递多个值数组。

    selector: '[selectorHere]',
    
    @Input() options: any = {};
    

    输入.html

    <input selectorHere [options]="selectorArray" />
    

    TS 文件中的数组

    selectorArray= {
      align: 'left',
      prefix: '$',
      thousands: ',',
      decimal: '.',
      precision: 2
    };
    

    【讨论】:

      【解决方案2】:

      另一个巧妙的选择是将Directive 用作元素而不是属性。

      @Directive({
         selector: 'app-directive'
      })
      export class InformativeDirective implements AfterViewInit {
      
          @Input()
          public first: string;
      
          @Input()
          public second: string;
      
          ngAfterViewInit(): void {
             console.log(`Values: ${this.first}, ${this.second}`);
          }
      }
      

      这个指令可以这样使用:

      <app-someKindOfComponent>
          <app-directive [first]="'first 1'" [second]="'second 1'">A</app-directive>
          <app-directive [first]="'First 2'" [second]="'second 2'">B</app-directive>
          <app-directive [first]="'First 3'" [second]="'second 3'">C</app-directive>
      </app-someKindOfComponent>`
      

      简单、整洁且功能强大。

      【讨论】:

      • 谢谢,这也是最简单的方法。
      • 我没有意识到指令可以用作元素。太棒了。
      【解决方案3】:

      来自Documentation

      与组件一样,您可以添加尽可能多的指令属性绑定 您需要通过在模板中将它们串起来。

      HighlightDirective 添加一个名为defaultColor 的输入属性:

      @Input() defaultColor: string;
      

      标记

      <p [myHighlight]="color" defaultColor="violet">
        Highlight me too!
      </p>
      

      Angular 知道 defaultColor 绑定属于 HighlightDirective,因为您使用 @Input 将其公开 装饰器。

      不管怎样,@Input 装饰器告诉 Angular 这个属性是 public 并且可用于由父组件绑定。没有 @Input,Angular 拒绝绑定到该属性。

      举个例子

      有很多参数

      使用 @Input() 装饰器将属性添加到 Directive 类中

      @Directive({
          selector: '[selectable]'
      })
      export class SelectableDirective{
          private el: HTMLElement;
      
          @Input('selectable') option:any;   
          @Input('first') f;
          @Input('second') s;
      
          ...
      }
      

      并在模板中将绑定属性传递给您的li 元素

      <li *ngFor = 'let opt of currentQuestion.options' 
          [selectable] = 'opt' 
          [first]='YourParameterHere'
          [second]='YourParameterHere'
          (selectedOption) = 'onOptionSelection($event)'>
          {{opt.option}}
      </li>
      

      li 元素上,我们有一个名为selectable 的指令。在selectable 中,我们有两个@Input()f 的名称为firsts 的名称为second。我们已将这两个应用到名称为[first][second]li 属性上。我们的指令将在 li 元素上找到这些属性,这些属性是使用 @Input() 装饰器为他设置的。所以selectable[first][second] 将绑定到li 上的每个指令,这些指令具有这些名称的属性。

      单参数

      @Directive({
          selector: '[selectable]'
      })
      export class SelectableDirective{
          private el: HTMLElement;
      
          @Input('selectable') option:any;   
          @Input('params') params;
      
          ...
      }
      

      标记

      <li *ngFor = 'let opt of currentQuestion.options' 
          [selectable] = 'opt' 
          [params]='{firstParam: 1, seconParam: 2, thirdParam: 3}'
          (selectedOption) = 'onOptionSelection($event)'>
          {{opt.option}}
      </li>
      

      【讨论】:

      • 但是父组件应该写什么呢?
      • @Shree 查看编辑后的答案。在li 中你以同样的方式传递一个参数
      • 但是如果我有多个 attr 指令呢?
      • 您将使用@Input 装饰器给出它所对应的参数
      • @ChrisTarasovs 当你使用[defaultColor]="violet" 时,它会尝试执行正确的部分并找到一个名为紫罗兰色的属性,没有[] 括号它使用正确的部分作为字符串
      【解决方案4】:

      要传递许多选项,您可以将对象传递给 @Input 装饰器,并在一行中包含自定义数据。

      在模板中

      <li *ngFor = 'let opt of currentQuestion.options' 
                      [selectable] = 'opt'
                      [myOptions] ="{first: opt.val1, second: opt.val2}" // these are your multiple parameters
                      (selectedOption) = 'onOptionSelection($event)' >
           {{opt.option}}
      </li>
      

      在指令类中

      @Directive({
        selector: '[selectable]'
      })
      
      export class SelectableDirective{
        private el: HTMLElement;
        @Input('selectable') option:any;
        @Input('myOptions') data;
      
        //do something with data.first
        ...
        // do something with data.second
      }
      

      【讨论】:

      • 这就是我要找的。这样我就可以只使用一个指令绑定 pr。 html元素。非常感谢@Dag!
      • @MartinJH 值得一提的是,该解决方案在使用更改检测策略OnPush 时效果不佳。如果您想使用该策略,最好避免将对象用作@Input()。
      • @enf0rcer 当然你仍然可以在 OnPush 中使用这个方法,你只需要将一个新对象推送到指令中。所以,在模板中嵌入对象字面量是不行的——你需要通过组件上的一个 observable 来推动它。
      猜你喜欢
      • 2017-12-23
      • 1970-01-01
      • 2019-02-03
      • 1970-01-01
      • 2017-04-21
      • 2020-11-07
      • 1970-01-01
      • 2018-08-01
      • 1970-01-01
      相关资源
      最近更新 更多