如何正确配置这个虚拟Angular项目

时间:2018-01-11 23:33:20

标签: javascript jquery angular typescript

我有这个非常基本的项目:

https://stackblitz.com/edit/angular-rktmgc-ktjk3n?file=index.html

这是代码:/index.html

<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<div class="mat-app-background basic-container">
    <br />
    <a href="https://material.angular.io/components/slide-toggle/api">API reference for Angular Material slide-toggle</a><br /><br />
    <select-reset-example>loading</select-reset-example>
    <div style="margin-top:30px;">
    <div style="color:#f00;margin-bottom:20px;">
          Below is what I need to get it work like above (but it doesn't):
    </div>
        <mat-slide-toggle>Slide me!</mat-slide-toggle>
    </div>
</div>

这是代码:/app/select-reset-example.html

<mat-slide-toggle>Slide me!</mat-slide-toggle>

加载组件时:mat-slide-toggle到:select-reset-example它可以正常工作,但直接在index.html上加载时它不会。

我的问题是,如何配置以下/main.ts文件,以便直接在mat-slide-toggle上呈现index.html

如果范围有问题,也许可以创建一个继承自mat-slide-toggleMatSlideToggleModule类的自定义组件?

如果可能,您可以在stackblitz.com上分叉项目并给我链接 配置正确吗?

import './polyfills';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatSlideToggleModule } from '@angular/material';
import { SelectResetExample } from './app/select-reset-example';
import { HttpModule } from '@angular/http';
import { CdkTableModule } from '@angular/cdk/table';

@NgModule({
  exports: [
    MatSlideToggleModule,
  ]
})
export class DemoMaterialModule { }

@NgModule({
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    FormsModule,
    HttpModule,
    DemoMaterialModule,
    ReactiveFormsModule,
  ],
  entryComponents: [SelectResetExample],
  declarations: [SelectResetExample],
  bootstrap: [SelectResetExample],
  providers: []
})
export class AppModule { }

platformBrowserDynamic().bootstrapModule(AppModule);

这是项目的结构:

enter image description here

谢谢!

1 个答案:

答案 0 :(得分:0)

确实有几种选择可以在这里应用。

尝试1

乍一看,我们只需导入MatSlideToggle组件并将其添加到bootstrap数组即可轻松解决您的问题:

import { MatSlideToggle } from '@angular/material';

@NgModule({
  ...
  bootstrap: [SelectResetExample, MatSlideToggle ]
                                  ^^^^^^^^^^^^^^
                               cool, it was very easy!!!
})
export class AppModule { }

https://stackblitz.com/edit/angular-rktmgc-7h51hh?file=main.ts

嗯,好像我们已经破坏了一切:)。

<强>为什么吗

Angular bootstraps SelectResetExample组件。在此过程中,它会创建属于mat-slide-toggle模板的select-reset-example.html

所以现在我们的html有两个mat-slide-toggle标签。

然后使用角度bootstraps第二个组件(MatSlideToggle)将应用于第一个mat-slide-toggle。通过这种方式,我们可以看到第一个工作滑块丢失了文本Slide me!

尝试2

让我们改变引导组件的顺序:

@NgModule({
  ...
  bootstrap: [ MatSlideToggle, SelectResetExample ]
})
export class AppModule { }

https://stackblitz.com/edit/angular-rktmgc-mkm7ry?file=main.ts

第二个滑块现在可以工作但等待......我们再次丢失了文本。

这样做的主要原因是 angular无法处理自举组件上的可投影节点。

尝试3

Angular通过在ngDoBootstrap @NgModule方法中编写代码,提供了覆盖引导过程的机会。我们试试......

import { ApplicationRef, ComponentFactoryResolver, Injector, NgModuleRef } from '@angular/core';

@NgModule({
  // we replaced bootstrap option with entryComponents
  entryComponents: [SelectResetExample, MatSlideToggle],
})
export class AppModule { 
  constructor(
    private resolver: ComponentFactoryResolver,
    private ngModule: NgModuleRef<any>) {}

  ngDoBootstrap(appRef: ApplicationRef) {

    const factory = this.resolver.resolveComponentFactory(MatSlideToggle);
    const target = document.querySelector('mat-slide-toggle');
    const compRef = factory.create(
       Injector.NULL,
       [Array.from(target.childNodes)], // passing projectable nodes
       target, 
       this.ngModule);

    appRef.attachView(compRef.hostView);


    appRef.bootstrap(SelectResetExample);
  }
}

https://stackblitz.com/edit/angular-rktmgc-ncyebq?file=index.html

在这里,我通过自定义方法ngDoBootstrap引导我们的组件。它有效但......

这是什么?我真的需要知道吗?

我不这么认为。必须有其他出路。

尝试4

为了不使我们的生活变得复杂,我们应该遵循角度框架的设计。为此,最好有一个根组件。让我们创建它:

<强> app.component.ts

@Component({
  selector: '.mat-app-background.basic-container',
  templateUrl: './app.component.html',
})
export class AppComponent {
}

<强> app.component.html

<br />
<a href="https://material.angular.io/components/slide-toggle/api">API reference for Angular Material slide-toggle</a><br /><br />
<select-reset-example>loading</select-reset-example>
<div style="margin-top:30px;">
  <div style="color:#f00;margin-bottom:20px;">
    Below is what I need to get it work like above (but it doesn't):
  </div>
  <mat-slide-toggle>Slide me!</mat-slide-toggle>
</div>

<强>模块

declarations: [SelectResetExample, AppComponent],
bootstrap: [AppComponent],

<强>的index.html

<div class="mat-app-background basic-container"></div>

我将样式移到外部资源

<强> Stackblitz Example