Angular Ivy(8-beta):如何将HttpClient注入组件?

Mar*_*sch 12 angular

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

main.ts:

import { ?renderComponent as renderComponent } from '@angular/core';
import { AppComponent } from './app/app.component';
renderComponent(AppComponent);
Run Code Online (Sandbox Code Playgroud)

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 }));
    }
}
Run Code Online (Sandbox Code Playgroud)

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

这导致以下异常:

错误:注入器: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() }) },
    // ...
  ]
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*sch 3

回答我自己的问题:可以在 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 });
Run Code Online (Sandbox Code Playgroud)

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

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

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

customElements.define('ng-ivy-custom-element', AppComponentCustomElement);
Run Code Online (Sandbox Code Playgroud)

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

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