我执行异步服务调用来获取元素列表。
public elementList: Array<Element>;
...
this.service.getElementList().subscribe( list => {
this.elementList = list;
this.createFormGroup(list);
}
);
...
Run Code Online (Sandbox Code Playgroud)
当我收到元素列表(我订阅了服务调用)时,我根据元素列表构建表单组。在模板中,我有一个 *ngIf 仅当列表大于零时才绘制。
*ngIf="elementList?.length>0"
Run Code Online (Sandbox Code Playgroud)
由于elementList是异步获取的,所以这个ngIf不起作用。我读到可以将 ngIf 与 AsnycPipe 一起使用。所以在模板中我将有:
*ngIf="elementList$ && elementList$.length>0"
Run Code Online (Sandbox Code Playgroud)
其中 elementList$ 是从服务调用返回的 Observable。
public elementList$: Observable<Array<Element>>;
elementList$ =this.service.getElementList()
Run Code Online (Sandbox Code Playgroud)
我想知道收到 elementList 后如何创建 FormGroup。首先,我需要创建 FormGroup,然后模板应该调用 *ngIf 来绘制元素。
我花了大约三天的时间试图解决这个问题。
预期行为:材质表始终使用后端的最新数据进行渲染。当从单独的组件将新项目添加到表中时,路由器重定向到页面会显示更新的数据。
实际行为:第一次导航到页面时,表格为空。表格已呈现,列标题已呈现,但未填充任何行。导航离开然后返回可以正确填充表格。当向表中添加新项目时,服务会将该项目发送到后端,然后调用所有项目。然后该服务会更新商店(另一项服务)。重定向到表格组件时,表格似乎快速闪烁旧数据,然后再次显示为空白。一旦我离开并返回,表格就会正确加载。
我正在将下面的异步管道与服务一起使用。这对我来说似乎不对......此外,ngOnChanges 没有记录任何内容。
应用商店.service.ts
private _pets: ReplaySubject<Pet[]> = new ReplaySubject(1);
public readonly pets: Observable<Pet[]> = this._pets.asObservable();
getPets(): Observable<Pet[]> {
return this.pets;
}
Run Code Online (Sandbox Code Playgroud)
appDispatch.service.ts
public getPets(): Observable<Pet[]> {
return this.appStore.getPets();
}
private setPets(pets: Pet[]) {
this.appStore.setPets(pets);
}
Run Code Online (Sandbox Code Playgroud)
petTableComponent.component.ts
...
changeDetection: ChangeDetectionStrategy.OnPush
constructor(private appDispatch: AppDispatchService,
private router: Router) {
}
ngOnChanges(changes: SimpleChanges): void {
console.log(changes.value.currentValue);
}
Run Code Online (Sandbox Code Playgroud)
petTableComponent.component.html
<table
mat-table
[dataSource]="appDispatch.getPets() | async" multiTemplateDataRows
class="mat-elevation-z8">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef scope="col" [attr.role]="null"> <h4>Name</h4></th>
<td mat-cell *matCellDef="let element" scope="row" [attr.role]="null"> …Run Code Online (Sandbox Code Playgroud) 我有一个可观察量,我想在 ngIf 中创建一个变量,并且仅在值为 null 时返回 false (可观察量返回一个数字)
我需要显式检查 null,因为我的 observable 可以返回 0 作为触发 else 块的值。
我尝试过以下方法
*ngIf="(observable$ | async) as obs; obs !== null; esle #elseTemplate"
Run Code Online (Sandbox Code Playgroud)
*ngIf="((observable$ | async) as obs) !== null; esle #elseTemplate"
Run Code Online (Sandbox Code Playgroud)
*ngIf="(observable$ | async) !== null; $implicit = obs; else #elseTemplate"
// this returns the boolean
Run Code Online (Sandbox Code Playgroud)
我当前的解决方案看起来不太优雅是
*ngIf="(observable$ | async) !== null; esle #elseTemplate"
{{ observable$ | async }}
Run Code Online (Sandbox Code Playgroud)
我正在使用 Angular 10。
我想将一个值传递给子组件。这个值是一个 Observable,所以我使用异步管道。
<child [test]="test$ | async"></child>
Run Code Online (Sandbox Code Playgroud)
test$ 只是一个普通的可观察变量,它在一段时间(3000 毫秒)后发出值,模拟对服务器的 API 请求。
this.test$=timer(3000).pipe(
mapTo("value")
)
Run Code Online (Sandbox Code Playgroud)
在子组件中,我只想检查test值
@Input() test: any;
constructor(){
console.log("child/test", this.test); //null
setTimeout(()=>console.log("child/test (timeout)", this.test),4000) //value
if(this.test){
//maintain and check `this.test`
//this code will not run, because at this point `this.test` is null.
//we don't know the exact time that `this.test` will have a value
//this causes that `this.test` is wrong
this.checked=true
}
}
Run Code Online (Sandbox Code Playgroud)
<div *ngIf="checked">{{test}}</div>
Run Code Online (Sandbox Code Playgroud)
我不想更改测试类型Observable并订阅它。我想直接接收最终值。我根本不想修改编辑组件。
使用ChangeDetectorRef手动触发变化检测器是不
@Input() test$:Observable
constructor(){
this.test$.subscribe(v=>this.test=v)
}
Run Code Online (Sandbox Code Playgroud)
我还做了这个 …
当在 Angular 中使用异步管道时,不会立即触发事件(http 请求或任何有延迟的可观察值),第一个值null
是为什么会发生?如何避免这种情况?
<hello [data]="delayedData$|async"> </hello>
Run Code Online (Sandbox Code Playgroud)
第一个改变:
SimpleChange {
currentValue: null
firstChange: true
previousValue: undefined
}
Run Code Online (Sandbox Code Playgroud)
第二个变化:
SimpleChange {
currentValue: 'some real data'
firstChange: false
previousValue: null
}
Run Code Online (Sandbox Code Playgroud)
stackblitz 上的示例: https://stackblitz.com/edit/http-async-pipe-crxm32
我对 Angular 异步管道的理解是,它在 HTML 模板中为您订阅公开的 Observable。例如
成分
export class TestComponent {
let todos$: Observable<Array<Todo>>;
constructor(private http: HttpClient) {}
ngOnInit() {
this.todos$ = this.http.get<Array<Todos>>(...)
}
}
Run Code Online (Sandbox Code Playgroud)
模板
<div *ngFor="let todo of todos$ | async">
{{ todo }}
</div>
Run Code Online (Sandbox Code Playgroud)
我的理解是 HttpClient Observable 将发出以下成功事件:
next(value)
completed
Run Code Online (Sandbox Code Playgroud)
和错误时
error(error)
completed
Run Code Online (Sandbox Code Playgroud)
当可观察对象发出已完成事件时,订阅将关闭。
因此,如果您订阅了像 Angulars HttpClient Observable 这样的冷 observable,您如何重试该 HttpClient 请求?
异步操作符执行初始订阅,但一旦冷可观察完成就会关闭,如果你想再次执行它,如何让异步操作符重新订阅?例如,如果您想刷新数据。
我正在研究遗留的角度代码,原来的开发人员已经走了。我在模板中看到了很多异步管道。它会导致更多的变化检测吗?
模板:
<div>{{(cart$ | async)?.name}}</div>
<div>{{(cart$ | async)?.price}}</div>
<div>{{(cart$ | async)?.count}}</div>
Run Code Online (Sandbox Code Playgroud)
我应该重构代码,让父组件模板异步管道cart$并将其传递给子组件吗?我知道这样代码更干净,除此之外,还有其他优点吗?谢谢!
<child [cart]="cart$ | async"></child>
Run Code Online (Sandbox Code Playgroud)