I am working on an angular 2 app and in one of my components I have this:
<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>
Works great in the browser but when I try to lint my matching ts file, I get this linting error: "The method "async" that you're trying to access does not exist in the class declaration. (no-access-missing-member)' at: '11,21"
My component code is as follows:
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);
}
}
Is it some type of anti pattern to use the async pipe in something other than the ngFor?
I know that I can subscribe to the observable and set the response = to some local variable and then compare that instead of using the async pipe in the [class.active] but I'd rather not do something in my .ts file that I can just do in my html file.
Is there a way I can get around this error so that my linter doesn't yell at me? I have github pre-commit hooks that check linting so I need a permanent solution. I did figure out that I can put a // tslint:disable-line
on the line that talks about change detection (line 11) and that fixes it but I have no idea why.
Not sure if that fixes the issue, but template-expressions can get messy quickly, you could do something like this:
<app-node-info ...
[class.active]="(currentNode | async) == node.id">
</app-node-info>
The controller:
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'));
}
I had the same issue and have been able to get rid of linter complain using safe navigation operator like this. For you it might look like this.
(viewService.observable | async)?.get('currentNode') === node.id
Edit: Found a bug report in codelyzer version 2.0.0-beta.1 with no-access-missing-member
config set to true. This seems to be a case for me. Seems to be fixed in later versions, though I did not try yet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With