简体   繁体   English

如何正确配置此虚拟Angular项目

[英]How to properly configure this dummy Angular project

I have this very basic project: 我有一个非常基本的项目:

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

This is the code on: /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>

This is the code on: /app/select-reset-example.html 这是以下代码: /app/select-reset-example.html

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

When loading the component: mat-slide-toggle through: select-reset-example it works, but when loading it directly on the index.html it doesn't. 加载组件时: mat-slide-toggle through: select-reset-example起作用,但是直接加载到index.html则不起作用。

My question is, how to configure the following /main.ts file in order to render the mat-slide-toggle directly on the index.html ? 我的问题是,如何配置以下/main.ts文件以便直接在index.html上呈现mat-slide-toggle

In case the scope be a problem, maybe is it possible to create a custom component which inherits from that mat-slide-toggle or MatSlideToggleModule class? 如果范围有问题,是否有可能创建一个自定义组件,该组件继承自该mat-slide-toggleMatSlideToggleModule类?

If possible, could you fork the project on stackblitz.com and give me the link with a proper configuration? 如果可能的话,您可以在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);

This is the structure of the project: 这是项目的结构:

在此处输入图片说明

Thanks! 谢谢!

Indeed there are several options which could be applied here. 实际上,这里可以应用几种选择。

Attempt 1 尝试1

At first glance we can easily solve your problem by simply importing MatSlideToggle component and adding it to the bootstrap array: 乍一看,我们只需导入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 https://stackblitz.com/edit/angular-rktmgc-7h51hh?file=main.ts

Hmm, seems we've broken everything:). 嗯,看来我们已经破坏了一切:)。

Why? 为什么?

Angular bootstraps SelectResetExample component. 角引导程序SelectResetExample组件。 During this process it creates mat-slide-toggle that is part of select-reset-example.html template. 在此过程中,它将创建mat-slide-toggle ,它是select-reset-example.html模板的一部分。

So now our html has two mat-slide-toggle tags. 所以现在我们的html有两个mat-slide-toggle标签。

And then angular bootstraps second component ( MatSlideToggle ) that will be applied to the first mat-slide-toggle . 然后,角度引导程序将第二个组件( MatSlideToggle )应用于第一个mat-slide-toggle This way we can see that the first working slider lost text Slide me! 这样,我们可以看到第一个工作的滑块丢失了文本Slide me! .

Attempt 2 尝试2

Let's change order of our bootstrapping components: 让我们更改自举组件的顺序:

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

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

The second slider works now but wait... We again lost the text. 第二个滑块现在可以使用,但是请稍候...我们再次丢失了文本。

The main reason of this is that angular can't process projectable nodes on bootstrapping component. 这主要是因为angular无法处理自举组件上的可投影节点。

Attempt 3 尝试3

Angular gives the opportunity to override bootstrapping process by writing code within ngDoBootstrap method of @NgModule . 角度给出了机会,通过内编写代码重写引导过程ngDoBootstrap的方法@NgModule Let's try... 我们试试吧...

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 https://stackblitz.com/edit/angular-rktmgc-ncyebq?file=index.html

Here i am bootstrapping our components throught custom method ngDoBootstrap . 在这里,我通过自定义方法ngDoBootstrap引导我们的组件。 And it works but... 它可以工作,但是...

What is this? 这是什么? Do I really need to know this? 我真的需要知道吗?

I don't think so. 我不这么认为。 There must be some other way out. 肯定还有其他出路。

Attempt 4 尝试4

in order not to complicate our live we should follow the design of angular framework. 为了不使我们的生活复杂化,我们应该遵循有角度框架的设计。 For that it would be better to have one root component. 为此,最好有一个根组件。 Let's create it: 创建它:

app.component.ts app.component.ts

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

app.component.html 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>

module 模组

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

index.html index.html

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

i moved styles to external resouces 我将样式转移到外部资源

Stackblitz Example Stackblitz示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM