Angular 2 (ng2) 在 [class.whatever] 中使用异步管道

Posted

技术标签:

【中文标题】Angular 2 (ng2) 在 [class.whatever] 中使用异步管道【英文标题】:Angular 2 (ng2) using the async pipe in [class.whatever] 【发布时间】:2017-05-05 02:05:18 【问题描述】:

我正在开发一个 Angular 2 应用程序,在我的一个组件中我有这个:

<p class="newNode">
  <input [(ngModel)]="formNode.id" placeholder="id">
  <input [(ngModel)]="formNode.name" placeholder="name">
  <input [(ngModel)]="formNode.type" placeholder="image">
  <button (click)="addNode()">Add</button>
</p>

<app-node-info *ngFor="let node of ((nodesService.observable | async) | immutableMapOfMaps)"
  [node]="node"
  [removeNode]="removeNode.bind(this)"
  [class.active] = "(viewService.observable | async).get('currentNode') === node.id"
  (click) = "viewService.setCurrentNode(node.id)">
</app-node-info>

在浏览器中运行良好,但是当我尝试对匹配的 ts 文件进行 lint 处理时,出现以下 linting 错误:“您尝试访问的方法“异步”在类声明中不存在。(无访问权限) -失踪成员)' 在:'11,21"

我的组件代码如下:

import  ChangeDetectionStrategy, Component, OnInit  from '@angular/core';
import  clone  from 'ramda';
import  UUID  from 'angular2-uuid';

import  StateService  from '../state.service';

import  D3Node  from '../../non-angular/interfaces';
import  NodesService, ViewService  from '../../non-angular/services-helpers';

@Component(
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'app-list-of-nodes',
  styleUrls: ['./list-of-nodes.component.css'],
  templateUrl: './list-of-nodes.component.html',
)
export class ListOfNodesComponent implements OnInit 
  formNode: D3Node;
  /**
   * The injected service from ./state.service
   */
  private nodesService: NodesService;
  private viewService: ViewService;

  constructor(state: StateService) 
    this.nodesService = state.twiglet.nodes;
    this.viewService = state.view;
  

  ngOnInit () 
    this.formNode = 
      id: UUID.UUID(),
      name: (Math.random().toString(36) + '00000000000000000').slice(2, 6),
      type: (Math.random().toString(36) + '00000000000000000').slice(2, 3),
    ;
  

  addNode () 
    this.nodesService.addNode(clone(this.formNode));
    this.formNode = 
      id: UUID.UUID(),
      name: (Math.random().toString(36) + '00000000000000000').slice(2, 6),
      type: (Math.random().toString(36) + '00000000000000000').slice(2, 3),
    ;
  

  removeNode (node: D3Node) 
    this.nodesService.removeNode(node);
  


在 ngFor 以外的地方使用异步管道是不是某种反模式?

我知道我可以订阅 observable 并将 response = 设置为某个局部变量,然后比较它而不是使用 [class.active] 中的异步管道,但我宁愿不在我的 .ts 中做某事我可以在我的 html 文件中执行的文件。

有没有办法绕过这个错误,这样我的 linter 就不会对我大喊大叫了?我有检查 linting 的 github 预提交钩子,所以我需要一个永久的解决方案。我确实发现我可以将// tslint:disable-line 放在讨论更改检测的行(第 11 行)并修复它,但我不知道为什么。

【问题讨论】:

错误显示的是哪个文件? - 我不确定你是否应该在你的模板文件上运行 ts-linter,毕竟 angular-expression 不完全是打字稿 name.component.ts 上显示错误,我没有对模板文件进行 linting。但是,如果我从模板文件中删除行 [class.active] = "(viewService.observable | async).get('currentNode') === node.id",则 linting 会通过。这对我来说很奇怪,就像 tslint 以某种方式导入模板。 这确实很奇怪 - linting 是什么时候完成的?您是否使用 webpack 并且 linting 是在预加载器中完成的?或者在包装过程中的某个时候等?这也很有趣,它没有突出您对async的其他用途 我在 VS 代码中的 linter 以及当我在终端中运行 `tslint \"src/**/*.ts\ ` 时都会抛出相同的错误。 【参考方案1】:

我认为有一个未解决的问题需要在 codelyzer 中修复。 https://github.com/angular/angular-cli/issues/4351

但在此之前,作为一种解决方法,您可以在您的组件中执行此操作以解决 lint 问题:

// TODO: fix this later
async: any;

constructor(..) ..

【讨论】:

【参考方案2】:

我遇到了同样的问题,并且能够像这样使用 安全导航操作符 摆脱 linter 抱怨。对你来说,它可能看起来像这样。

(viewService.observable | async)?.get('currentNode') === node.id

编辑:在codelyzer version 2.0.0-beta.1 中发现了一个错误报告,其中no-access-missing-member 配置设置为true。这对我来说似乎是一个案例。似乎在以后的版本中修复了,虽然我还没有尝试。

【讨论】:

【参考方案3】:

不确定这是否能解决问题,但模板表达式很快就会变得混乱,您可以这样做:

<app-node-info ...
    [class.active]="(currentNode | async) == node.id">
</app-node-info>

控制器:

export class ListOfNodesComponent implements OnInit 
  formNode: D3Node;
  /**
   * The injected service from ./state.service
   */
  private nodesService: NodesService;
  private viewService: ViewService;

  private currentNode: Observable<any>;

  constructor(state: StateService) 
    this.nodesService = state.twiglet.nodes;
    this.viewService = state.view;

    currentNode = this.viewService.observable
      .map(val => val.get('currentNode'));
  

【讨论】:

欣赏它。我曾想过将其拉入控制器,但后来我失去了使用可观察对象和不可变对象的 OnPush 优势。我可能会将服务本身从组件中拉出,然后使用 @Input() 从订阅中下推一个变量,我只是不知道为什么它在 linting 时遇到问题。 所以将异步逻辑的部分移动到控制器并没有改变任何东西?我以前没有见过,如果您找到解决方案,请在此处发布。 - 也许作为最后一击:您在模板中使用“===”,“==”有什么不同吗? 不,当我将异步移动到控制器中作为订阅时,它工作正常。我只是好奇为什么我不能按照自己的方式去做。 在我的回答中,我没有将订阅移动到控制器中 - 我只是将流的某些部分移到那里,异步仍在模板中 - 不知道为什么它适用于 tslint 但它更干净

以上是关于Angular 2 (ng2) 在 [class.whatever] 中使用异步管道的主要内容,如果未能解决你的问题,请参考以下文章

ng2-dnd 与 Angular 4

“ng2-CKEditor”节点模块不适用于打字稿[Angular2]

Angular2 切换/打开 ng2-select 下拉菜单

Angular 2 Universal ng2-bootstrap 不工作 Safari

在Angular2中使用css向ng2-select2添加样式

如何在Angular中使用自定义比例绘制ng2-charts水平条形图?