首页 > 解决方案 > Angular Ivy (8-beta):如何将 HttpClient 注入到组件中?

问题描述

我正在尝试构建一个示例应用程序来测试 Angular Ivy 与 Angular Elements 的结合,但我找不到任何关于如何在该设置中配置 DI 的信息 - 因为 app.module 被绕过了。

main.ts:

import { ɵrenderComponent as renderComponent } from '@angular/core';
import { AppComponent } from './app/app.component';
renderComponent(AppComponent);

app.module.ts:main.ts不使用这个,那么应该在哪里加载 HttpClientModule 并定义自定义元素?

import { NgModule, Injector } from '@angular/core';
import { HttpClientModule } from '@angular/common/http/http';
import { createCustomElement } from '@angular/elements';

import { AppComponent } from 'src/app/app.component';

@NgModule({
    declarations: [ AppComponent ],
    imports: [ HttpClientModule ],
    entryComponents: [AppComponent]
})
export class AppModule {
    constructor(private injector: Injector) { }

    ngDoBootstrap() {
        customElements.define('app-component',
            createCustomElement(AppComponent, { injector: this.injector }));
    }
}

app.component.ts:

import { Component, ChangeDetectionStrategy, ViewEncapsulation, Input } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject } from 'rxjs';

@Component({
  selector: 'app-component',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.ShadowDom,
})
export class AppComponent {
    constructor(private http: HttpClient) {
        http.get<any>('someurl').subscribe(data => console.log(data));
    }
}

这会导致以下异常:

错误:注射器:NOT_FOUND [HttpClient]

我已经阅读了一些关于@Component 的“deps”属性的提示,但没有找到(~8.0.0-beta.8)。我尝试添加providers: [ { provide: HttpClient } ]到@Component,它抛出

错误:注射器:NOT_FOUND [HttpHandler]

providers: [ { provide: HttpClient, deps: [HttpHandler] } ]仍然抛出相同的异常。

使用 Ivy 时应该在哪里配置依赖项?在此期间,应该在哪里createCustomElement调用?

我添加了一个 github 存储库,其中包含一个最小、完整且可验证的示例:https ://github.com/markusdresch/ng-ivy-custom-element

编辑 好吧,我走得更远了。必须更明确地提供 HttpHandler(这在 @Component 中):

  providers: [
    { provide: HttpClient, deps: [ HttpHandler ] },
    { provide: HttpHandler, useValue: new HttpXhrBackend({ build: () => new XMLHttpRequest() }) },
    // ...
  ]

这样,上述错误就消失了,并且可以正常工作。但是,我仍然不确定如何注册自定义元素。

标签: angular

解决方案


回答我自己的问题:可以在 main.ts 中启动根注入器。这不像@NgModule 那样简单,因为还必须提供依赖项:

在 main.ts 中:

const injector: Injector = Injector.create({
  name: 'root',
  providers: [
    { provide: HttpClient, deps: [ HttpHandler ] },
    { provide: HttpHandler, useValue: new HttpXhrBackend({ build: () => new XMLHttpRequest() }) },
  ]
});

renderComponent(AppComponent, { injector: injector });

我还没有真正解决创建这样的自定义元素,除了这个黑客:

class AppComponentCustomElement extends HTMLElement {
  constructor() {
    super();

    renderComponent(AppComponent, { injector: injector });
  }
}

customElements.define('ng-ivy-custom-element', AppComponentCustomElement);

但是这种方式 @Inputs 等必须手动路由。如果我发现更有用的东西,我会继续修补和更新。

更新:根据https://juristr.com/blog/2019/05/Angular-8-and-the-Future-NGConf-2019-Roundup/#not-every-app-is-a-spa我的尝试不是被认为是一种黑客行为,但实现这一目标的正确方法。


推荐阅读