Angular 4 中如何从 Controller 访问已排序的管道数组(使用 *ngFor 和管道生成)
How to Access Sorted Pipe Array (generated with *ngFor and pipes) from Controller in Angular 4
如何访问在控制器内的 *ngFor 中声明的变量?
我有这样的代码:
<song *ngFor="let track of music | async | sortMusic: [sortBy] as sortedTracks" [trackInfo]="track" (click)="toggleTrack(track)"></song>
我想访问 "sortedTracks" 变量。我有兴趣从具有上述代码的组件访问它,而不是从歌曲组件控制器访问它。
更新
确实应该很容易:
@ViewChild(NgForOf) ngForDir: NgForOf<any>;
this.ngForDir.ngForOf
旧版本
1) 特别指示
我们可以编写帮助我获得它的指令:
ngfor-as.directive.ts
import { Directive, EmbeddedViewRef, NgIterable, ViewContainerRef } from '@angular/core';
import { NgForOfContext } from '@angular/common';
@Directive({
selector: '[ngForOf]'
})
export class NgForOfAsDirective<T> {
constructor(private vcRef: ViewContainerRef) {}
public get asValue(): NgIterable<T> {
const viewRef = this.vcRef.get(0) as EmbeddedViewRef<NgForOfContext<T>>;
return viewRef ? viewRef.context.ngForOf : null;
}
}
一旦我们在上面创建了指令,我们就可以使用 @ViewChild
来获取该指令的实例:
@Component({
selector: 'my-app',
template: `
<song *ngFor="let track of music | async | sortMusic: sortBy as sortedTracks" ...></song>
`
})
export class AppComponent {
...
@ViewChild(NgForOfAsDirective) ngForAs: NgForOfAsDirective<any[]>;
ngAfterViewInit() {
console.log(this.ngForAs.asValue);
}
}
2) 直接从 ViewContainerRef 获取值
如果您不想创建一个指令,您可以只获取 ngForOf
指令使用的 ViewContainer
:
@Component({
selector: 'my-app',
template: `
<song *ngFor="let track of music | async | sortMusic: sortBy as sortedTracks" ...></song>
`
})
export class AppComponent {
@ViewChild(TemplateRef, { read: ViewContainerRef }) vcRef: ViewContainerRef;
get asMusicValue(): NgIterable<any> {
const viewRef = this.vcRef.get(0) as EmbeddedViewRef<NgForOfContext<any>>;
return viewRef ? viewRef.context.ngForOf : null;
}
...
ngAfterViewInit() {
console.log(this.asMusicValue);
}
}
当然,如果您的模板中有多个 ngForOf
指令,那么您在查询 ViewContainerRef
时应该更加精确。
为此,您可以使用以下选项之一:
@ViewChildren
如果知道确切的顺序 (example)
@ViewChildren(TemplateRef, { read: ViewContainerRef }) vcRefs: QueryList<ViewContainerRef>;
...
this.vcRefs.first.get(0)
^^^^^
ngForOf
(example) 的扩展形式:
<ng-template #someId
let-track
ngFor
[ngForOf]="music | async | sortMusic: sortBy"
let-sortedTracks="ngFor">
<song [trackInfo]="track"></song>
</ng-template>
- 带有特殊选择器的指令(example)
@Directive({
selector: '[ngForOf=music | async | sortMusic: sortBy ]'
})
export class NgForOfMusic {}
...
@ViewChild(NgForOfMusic, { read: ViewContainerRef }) vcRef: ViewContainerRef;
它将匹配
*ngFor="let track of music | async | sortMusic: sortBy as sortedTracks"
| |
\ /
attrValue
但不要使用方括号,例如:
*ngFor="let track of music | async | sortMusic: [sortBy] as sortedTracks"
因为选择器
@Directive({
selector: '[ngForOf=music | async | sortMusic: [sortBy] ]'
})
行不通。
如何访问在控制器内的 *ngFor 中声明的变量?
我有这样的代码:
<song *ngFor="let track of music | async | sortMusic: [sortBy] as sortedTracks" [trackInfo]="track" (click)="toggleTrack(track)"></song>
我想访问 "sortedTracks" 变量。我有兴趣从具有上述代码的组件访问它,而不是从歌曲组件控制器访问它。
更新
确实应该很容易:
@ViewChild(NgForOf) ngForDir: NgForOf<any>;
this.ngForDir.ngForOf
旧版本
1) 特别指示
我们可以编写帮助我获得它的指令:
ngfor-as.directive.ts
import { Directive, EmbeddedViewRef, NgIterable, ViewContainerRef } from '@angular/core';
import { NgForOfContext } from '@angular/common';
@Directive({
selector: '[ngForOf]'
})
export class NgForOfAsDirective<T> {
constructor(private vcRef: ViewContainerRef) {}
public get asValue(): NgIterable<T> {
const viewRef = this.vcRef.get(0) as EmbeddedViewRef<NgForOfContext<T>>;
return viewRef ? viewRef.context.ngForOf : null;
}
}
一旦我们在上面创建了指令,我们就可以使用 @ViewChild
来获取该指令的实例:
@Component({
selector: 'my-app',
template: `
<song *ngFor="let track of music | async | sortMusic: sortBy as sortedTracks" ...></song>
`
})
export class AppComponent {
...
@ViewChild(NgForOfAsDirective) ngForAs: NgForOfAsDirective<any[]>;
ngAfterViewInit() {
console.log(this.ngForAs.asValue);
}
}
2) 直接从 ViewContainerRef 获取值
如果您不想创建一个指令,您可以只获取 ngForOf
指令使用的 ViewContainer
:
@Component({
selector: 'my-app',
template: `
<song *ngFor="let track of music | async | sortMusic: sortBy as sortedTracks" ...></song>
`
})
export class AppComponent {
@ViewChild(TemplateRef, { read: ViewContainerRef }) vcRef: ViewContainerRef;
get asMusicValue(): NgIterable<any> {
const viewRef = this.vcRef.get(0) as EmbeddedViewRef<NgForOfContext<any>>;
return viewRef ? viewRef.context.ngForOf : null;
}
...
ngAfterViewInit() {
console.log(this.asMusicValue);
}
}
当然,如果您的模板中有多个 ngForOf
指令,那么您在查询 ViewContainerRef
时应该更加精确。
为此,您可以使用以下选项之一:
@ViewChildren
如果知道确切的顺序 (example)
@ViewChildren(TemplateRef, { read: ViewContainerRef }) vcRefs: QueryList<ViewContainerRef>;
...
this.vcRefs.first.get(0)
^^^^^
ngForOf
(example) 的扩展形式:
<ng-template #someId
let-track
ngFor
[ngForOf]="music | async | sortMusic: sortBy"
let-sortedTracks="ngFor">
<song [trackInfo]="track"></song>
</ng-template>
- 带有特殊选择器的指令(example)
@Directive({
selector: '[ngForOf=music | async | sortMusic: sortBy ]'
})
export class NgForOfMusic {}
...
@ViewChild(NgForOfMusic, { read: ViewContainerRef }) vcRef: ViewContainerRef;
它将匹配
*ngFor="let track of music | async | sortMusic: sortBy as sortedTracks"
| |
\ /
attrValue
但不要使用方括号,例如:
*ngFor="let track of music | async | sortMusic: [sortBy] as sortedTracks"
因为选择器
@Directive({
selector: '[ngForOf=music | async | sortMusic: [sortBy] ]'
})
行不通。