在动态组件中找不到角通用异步管道

如何解决在动态组件中找不到角通用异步管道

我有一个Angular 10应用程序,该应用程序将Angular Universal用于SSR。此应用程序还发出http请求以获取一些html并动态呈现它。当我使用ng serve运行应用程序时,一切正常,动态内容将通过http请求获取,并正确呈现到页面中。这些是我的主要模块和组件

app.module.ts

export function createCompiler(compilerFactory: CompilerFactory) {
  return compilerFactory.createCompiler();
}

@NgModule({
  declarations: [
    AppComponent,],imports: [
    browserModule.withServerTransition({ appId: 'serverApp' }),browserAnimationsModule,HttpClientModule,browserTransferStateModule,CoreModule
  ],providers: [
    HttpClientModule,{ provide: COMPILER_OPTIONS,useValue: {},multi: true },{ provide: CompilerFactory,useClass: JitCompilerFactory,deps: [COMPILER_OPTIONS] },{ provide: Compiler,useFactory: createCompiler,deps: [CompilerFactory] }
  ],bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts

@Component({
  selector: 'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.scss'],})
export class AppComponent implements OnInit {
  categories$: Observable<any[]>;
  categories: any[]
  store$: Observable<any>;
  constructor() {}

  ngOnInit() {
    const cats = [
      { id: 1,name: 'XMAS' },{ id: 2,name: 'KITCHEN' },{ id: 3,name: 'DINNING' },{ id: 4,name: 'BATHROOM' },{ id: 5,name: 'bedROOM' },];
    const store = {
      countryCode : 'US',}
    this.store$ = of(store);
    this.categories$ = of(cats);
    this.categories = [...cats];
  }
}

这是该组件的基本html

<p>TEST</p>
<div *ngIf="categories?.length">
  <h2>CATEGORIES</h2>
  <ul *ngFor="let cat of categories">
    <li>{{ cat.name }}</li>
  </ul>
</div>
<footer>
  <app-dynamic-content name="Footer_Sections" [parentContext]="this"></app-dynamic-content>
</footer>

app-dynamic内容组件通过http请求获取内容,创建一个新组件,将获取内容分配为模板,创建一个新模块,并将该组件添加到声明中以允许使用

dynamic-content.component.ts

@Component({
    selector: 'app-dynamic-content',templateUrl: './dynamic-content.component.html',styleUrls: ['./dynamic-content.component.scss'],changeDetection: ChangeDetectionStrategy.OnPush
  })
  export class DynamicContentComponent implements OnInit,OnDestroy,AfterViewInit {
    @input() name: string;
    @input() parentContext: any;
    @ViewChild('container',{ read: ViewContainerRef }) container: ViewContainerRef;  
    private componentRef: ComponentRef<any>;
    private unsubscribe = new Subject<void>();  
    parsedContent: DynamicContent;
    dynamicContent$: Observable<any>;
    template: string;
  
    constructor(
      private dynamicContentsService: DynamicContentsService,private compiler: Compiler,private changeDetectorRef: ChangeDetectorRef
    ) { }
  
    ngOnInit(): void {
      this.dynamicContent$ = this.dynamicContentsService.getDynamicContent(this.name).pipe(filter(res => !!res));
    }
  
    ngAfterViewInit() {
      this.dynamicContent$.pipe(take(1))
        .subscribe((response) => {
          if (response && response.dynamicContents.length) {
            this.parsedContent = this.dynamicContentsService.parseDinamycContent(response.dynamicContents as DynamicContent[]);
            this.template = this.parsedContent.value;
            this.createDynamicComponent();
          }
        });
    }
  
    createDynamicComponent() {
      const Metadata = new Component({
        selector: 'app-dynamic',template: this.template
      });
  
      const factory = this.createComponentFactory(Metadata);
      this.componentRef = this.container.createComponent(factory);
      this.changeDetectorRef.detectChanges();
    }
  

    createComponentFactory(Metadata: Component): ComponentFactory<any> {
      const self = this;
      const componentClass = class DynamicComponent { context: any = self.parentContext; };
      const moduleClass = class RuntimeComponentModule {};
      const decoratedComponent = Component(Metadata)(componentClass);
      const modules = this.getModulesNeeded();
      const decoratedngModule = NgModule({ imports: modules,declarations: [decoratedComponent] })(moduleClass);
      const module: ModuleWithComponentFactories<any> = this.compiler.compileModuleAndAllComponentsSync(decoratedngModule);
  
      return module.componentFactories.find(factory => factory.componentType === decoratedComponent);
    }
  
    getModulesNeeded() {
      return [browserModule,CommonModule];
    }
  
    ngOnDestroy() {
      this.unsubscribe.next();
      this.unsubscribe.complete();
  
      if (this.componentRef) {
        this.componentRef.destroy();
      }
    }
  }

dynamic-content.component.html

<ng-container>
  <ng-template #container></ng-template>
</ng-container>

这是通过http请求获取的html内容

<div class="social" *ngIf="context.store$ | async as store">
  <div class="networks">
    <h3>Follow US</h3>
  </div>
</div>

正如我所说,当应用程序与ng serve一起运行时,此组件可以正常工作,呈现动态内容。问题是当我使用ng run app-name:serve-ssr使用ssr运行应用程序时,所有内容均来自服务器,除了此动态内容组件。该内容实际上是在服务器中获取的,因为我可以看到模板存储在脚本html标签中的transferState键中,但是我在服务器控制台中遇到了此错误

ERROR Error: The pipe 'async' Could not be found!
at getPipeDef$1 (C:\app\dist\myapp\server\main.js:1:2321863)
at ɵɵpipe (C:\app\dist\myapp\server\main.js:1:2321915)
at template (ng:///.js:150:9)
at executeTemplate (C:\app\dist\myapp\server\main.js:1:2097798)
at renderView (C:\app\dist\myapp\server\main.js:1:2093138)
at renderComponent (C:\app\dist\myapp\server\main.js:1:2111597)
at renderChildComponents (C:\app\dist\myapp\server\main.js:1:2093514)
at renderView (C:\app\dist\myapp\server\main.js:1:2093555)
at ComponentFactory$1.create (C:\app\dist\myapp\server\main.js:1:2313775)
at R3ViewContainerRef.createComponent (C:\app\dist\myapp\server\main.js:1:2130074)

出现此错误后,浏览器似乎控制了控件从transferState键获取内容并呈现该内容,但ssr不适用于这种动态内容。我的通用服务器由ng add Universal命令组成,唯一的变化是代理中间件。

import 'zone.js/dist/zone-node';
import { createProxyMiddleware,Filter,Options,RequestHandler } from 'http-proxy-middleware';
import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';

import { AppServerModule } from './src/main.server';
import { APP_BASE_HREF } from '@angular/common';
import { existsSync } from 'fs';
import { environment } from 'src/environments/environment';

// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
  const server = express();
  const distFolder = join(process.cwd(),'dist/myApp/browser');
  const indexHtml = existsSync(join(distFolder,'index.original.html')) ? 'index.original.html' : 'index';

  // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
  server.engine(
    'html',ngExpressEngine({
      bootstrap: AppServerModule,})
  );

  server.set('view engine','html');
  server.set('views',distFolder);
  server.use('/api',createProxyMiddleware({ target: environment?.host,changeOrigin: true }));
  server.get(
    '*.*',express.static(distFolder,{
      maxAge: '1y',})
  );

  // All regular routes use the Universal engine
  server.get('*',(req,res) => {
    console.log(req.params);
    res.render(indexHtml,{ req,providers: [{ provide: APP_BASE_HREF,useValue: req.baseUrl }] });
  });

  return server;
}

function run(): void {
  const port = process.env.PORT || 4000;

  // Start up the Node server
  const server = app();
  server.listen(port,() => {
    console.log(`Node Express server listening on http://localhost:${port}`);
  });
}

// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const modulefilename = (mainModule && mainModule.filename) || '';
if (modulefilename === __filename || modulefilename.includes('iisnode')) {
  run();
}

export * from './src/main.server';

有什么办法可以使这两件事协同工作吗?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?