Angular 使用数据转换创建指令

Angular 使用数据转换创建指令,angular,typescript,rxjs,angular-directive,Angular,Typescript,Rxjs,Angular Directive,我想创建一个LoaderDirective,它获取并可观察到加载数据,同时显示一个微调器,加载时将微调器更改为原始数据,同时使用“as”关键字公开加载的数据 我想这样使用它: 这就是我到目前为止所做的: @Directive({ // tslint:disable-next-line:directive-selector selector: '[load]', }) export class LoadDirective<T> { private data: T; @

我想创建一个LoaderDirective,它获取并可观察到加载数据,同时显示一个微调器,加载时将微调器更改为原始数据,同时使用“as”关键字公开加载的数据

我想这样使用它:

这就是我到目前为止所做的:

@Directive({
  // tslint:disable-next-line:directive-selector
  selector: '[load]',
})
export class LoadDirective<T> {
  private data: T;

  @Input()
  set load(observable: Observable<T>) {
    observable.subscribe({
      next: value => this.loaded(value),
      error: error => this.showError(error)
    });
  }

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef,
    private componentFactoryResolver: ComponentFactoryResolver
  ) {
    this.viewContainer.clear();
    this.viewContainer.createComponent(this.componentFactoryResolver.resolveComponentFactory(SpinnerComponent));
  }

  private loaded(value: T) {
    this.data = value;
    this.viewContainer.clear();
    this.viewContainer.createEmbeddedView(this.templateRef, {load: this.data});
  }

  private showError(e: string) {
    this.viewContainer.clear();
    const errorComponent = this.viewContainer.createComponent(this.componentFactoryResolver.resolveComponentFactory(ErrorComponent));
    errorComponent.instance.error = e;
  }
}
@指令({
//tslint:禁用下一行:指令选择器
选择器:“[load]”,
})
导出类装入指令{
私人资料:T;
@输入()
设定负荷(可观察:可观察){
可观察的({
下一步:value=>this.loaded(value),
error:error=>this.淋浴错误(error)
});
}
建造师(
私有templateRef:templateRef,
私有viewContainer:ViewContainerRef,
专用componentFactoryResolver:componentFactoryResolver
) {
this.viewContainer.clear();
this.viewContainer.createComponent(this.componentFactoryResolver.resolveComponentFactory(SpinnerComponent));
}
私有加载(值:T){
这个数据=值;
this.viewContainer.clear();
this.viewContainer.createEmbeddedView(this.templateRef,{load:this.data});
}
私人淋浴ROR(e:字符串){
this.viewContainer.clear();
const errorComponent=this.viewContainer.createComponent(this.componentFactoryResolver.resolveComponentFactory(errorComponent));
errorComponent.instance.error=e;
}
}

问题是输入数据是可观察的,因此它期望输出是可观察的。是否有类似的方法来改变这一点,例如管道处的
TransformPipe
?如何解决此问题?

以下是我尝试过的方法,请告诉我是否有效

范例

只需对代码进行一点小修改

更改自

this.viewContainer.createEmbeddedView(this.templateRef, {load: this.data});

const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
viewRef.context.data = this.data;
<div *appLoader="data$; data as result">
    {{result | json}}
</div>
模板更改为

const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
viewRef.context.data = this.data;
<div *appLoader="data$; data as result">
    {{result | json}}
</div>

{{result}json}

我可以使用异步pip来实现这一点,但我发现如果我可以在指令内实现这一点,那么我可以通过将
load()
重命名为
loadFor()
然后像这样调用它来创建一个解决方法:
。我只是好奇:为什么你想创建一个指令而不是一个组件?我想做的是使用加载的可观察项(或可观察项),而不用手动订阅组件并编写所有样板文件。我认为如果我只使用异步管道和ngIf:
会更好。但是,如果我可以编写自己的指令来完成所有这些,跳过实现自己的异步管道,那么这是多余的:
。这让我可以在div中的任何地方使用
,这是我想要的,没有用于订阅可观察项和存储结果的样板文件,没有额外的组件,非常漂亮和干净的代码,只订阅一次,结果就在范围内。第一个更改是多余的-更新的模板可以以任何方式工作。我正在考虑用
data$之类的东西来解决问题;数据作为结果
,但不确定这是否符合问题的要求。