【问题标题】:Declare variable in structural directive在结构指令中声明变量
【发布时间】:2019-08-19 00:33:12
【问题描述】:

我的 Angular 应用程序中有一个自定义结构指令,如下所示:

@Directive({
  selector: '[appIfData]'
})
export class IfDataDirective {

  private hasView = false;

  @Input()
  set appIfData(condition: boolean) {
    if (condition && !this.hasView) {
      this.viewContainerRef.clear();
      this.viewContainerRef.createEmbeddedView(this.templateRef);
      this.hasView = true;
    } else if (!condition) {
      this.viewContainerRef.clear();
      const factory = this.componentFactoryResolver.resolveComponentFactory(ContentMessageComponent);
      const messageComponentRef = this.viewContainerRef.createComponent(factory);
      messageComponentRef.instance.message = 'No data is available yet';
      messageComponentRef.instance.icon = 'fas fa-info';
      this.hasView = false;
    }
  }
}

在 html 模板中使用它:

<ng-container *appIfData="(referenceService.documentUserTypes$ | async) as userDocTypes">

但我不能像使用 ngIf 时那样访问模板其余部分中声明的变量“userDocTypes”。

我想这是一种正常的行为,但我找不到这样做的好方法。

任何帮助将不胜感激。

编辑:

这就是我使用它的方式,它位于子元素中。 如前所述,如果我将其更改为 *ngIf ,它就可以正常工作:

编辑 2:

更新指令

@Directive({
  selector: '[appIfData]'
})
export class IfDataDirective {

  private hasView = false;

  @Input()
  set appIfData(data: any) {
    if (data && !this.hasView) {
      this.viewContainerRef.clear();
      this.viewContainerRef.createEmbeddedView(this.templateRef, { appIfData: data });
      this.hasView = true;
    } else if (!data) {
      this.viewContainerRef.clear();
      const factory = this.componentFactoryResolver.resolveComponentFactory(ContentMessageComponent);
      const messageComponentRef = this.viewContainerRef.createComponent(factory);
      messageComponentRef.instance.message = 'No data is available yet';
      messageComponentRef.instance.icon = 'fas fa-info';
      this.hasView = false;
    }
  }

【问题讨论】:

  • 您能否提供一个示例,说明您想在哪里使用userDocTypes
  • 我已经编辑了问题

标签: angular angular2-directives


【解决方案1】:

在他的回答中查看了安德烈的评论后,我正在使用这个:

 /**
     * Cache for document user types
     */
    public documentUserTypesCache$: BehaviorSubject<DocumentUserType[]>;

    /**
     * Get document user types
     */
    public get documentUserTypes$(): BehaviorSubject<DocumentUserType[]> {
        if (!this.documentUserTypesCache$) {
            this.documentUserTypesCache$ = new BehaviorSubject<DocumentUserType[]>([]);
            this.getDocumentUserTypes().pipe(tap(r => this.documentUserTypesCache$.next(r))).subscribe();
        }
        return this.documentUserTypesCache$;
    }

并将其更改为:

/**
 * Cache for document user types
 */
public documentUserTypesCache$: BehaviorSubject<DocumentUserType[]>;

/**
 * Get document user types
 */
public get documentUserTypes(): DocumentUserType[] {
    if (!this.documentUserTypesCache$) {
        this.documentUserTypesCache$ = new BehaviorSubject<DocumentUserType[]>(null);
        this.getDocumentUserTypes().pipe(
            filter(r => r && r != null),
            tap(r => this.documentUserTypesCache$.next(r))).subscribe();
    }
    return this.documentUserTypesCache$.getValue();
}

不是最好的,但解决方法有效

【讨论】:

    【解决方案2】:

    你可以像这样向createEmbeddedView 添加上下文

    this.viewContainerRef.createEmbeddedView(this.templateRef, {appIfData: condition});
    

    还请注意,condition 在您的示例中不是布尔值,它可能会在 aot 编译期间崩溃。将条件类型更改为其他内容

    【讨论】:

    • 我已经更新了我的代码。它不起作用。在帖子中查看我的编辑 2
    • 能否请您检查通过documentUserTypes$ 发生的事件。您的指令中存在一些问题,导致它仅采用第一个真实值并跳过其他值
    • 你是对的,问题来自于使用行为主体。我将其更改为可观察的,并且知道它的工作原理。谢谢
    • 问题来自设置为 false 的 hasview 属性,并且我的行为主题是使用数组启动的。上下文解决方案就像一个魅力。谢谢
    【解决方案3】:

    as 中声明的变量只能在其子元素内访问,如

    <ng-container *appIfData="(referenceService.documentUserTypes$ | async) as userDocTypes">
         <div>{{ userDocTypes }}</div>  // you can access here
    </ng-container>
    
    <div>{{ userDocTypes }}</div> // you cannot access here
    

    我认为你对 template reference 感到困惑,它可以在其模板中访问

    <div>
        <input type="text" #myInput value="123">
    </div>
    
    <div>{{ myInput.value }}</div> // you can access template variable outside of it
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-17
      • 1970-01-01
      • 1970-01-01
      • 2017-09-20
      • 2016-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多