将组件用作自定义元素和角度组件

时间:2018-06-11 15:57:38

标签: angular web-component angular6 custom-element

我正在尝试使用Angular组件作为自定义元素,因此我可以将其添加到DOM中,并自动引导,但我还需要将此组件作为另一个组件模板的一部分。

我已将 Description 组件注册为自定义元素,并且只要我将以下内容添加到dom中,它就会正确引导:

<app-description text="Some description text..."></app-description>

但是,如果我想将该组件用作 Header 组件模板的一部分(其属性descriptionText已正确设置),则不会显示任何描述。我正在使用它:

<app-description text="{{descriptionText}}"></app-description>

我也试过了:

<app-description [text]="descriptionText"></app-description>

<app-description text="descriptionText"></app-description>

但在任何情况下我都没有得到预期的结果。

所以,我的问题是: 有没有办法将Angular组件定义为自定义元素,还能将它包含在任何Angular组件的模板中?

修改 我在控制台和描述组​​件中的ngOnInit方法中放置了一个console.log(),我将在控制台中打印出来:

enter image description here

似乎组件初始化了两次,而在第二个'text'中设置为undefined?

描述组件:

@Component({
  selector: 'app-description',
  templateUrl: './description.component.html',
  styleUrls: ['./description.component.css']
})
export class DescriptionComponent implements OnInit {
  @Input() text: String;

  constructor() {}

  ngOnInit() {
    console.log('text:', this.text)
  }
}

描述模板:

<div class="description">
    <h3>{{ text }}</h3>
</div>

标题组件:

  @Component({
    selector: 'app-header',
    templateUrl: './header.component.html',
    styleUrls: ['./header.component.less']
  })
  export class HeaderComponent implements OnInit {
    @Input() title: String;
    @Input() subtitle: String;
    @Input() descriptionText: String;

    constructor() {}

    ngOnInit() {
      console.log('descriptionText:', this.descriptionText)
    }
  }

标题模板:

<div class="header flex-container">
    <h1>{{ title }}</h1>
    <h2>{{ subtitle }}</h2>
    {{descriptionText}} <!-- shown correctly! -->
    <app-description text="{{descriptionText}}"></app-description>
</div>

模块:

@NgModule({
  declarations: [
    AppComponent,
    HeaderComponent,
    DescriptionComponent
  ],
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [],
  entryComponents: [
    AppComponent,
    HeaderComponent,
    DescriptionComponent
  ],
  schemas : [
    CUSTOM_ELEMENTS_SCHEMA
  ]
}) 

export class AppModule {
  constructor(private injector: Injector) {
    this.registerCustomElements();
  }

  ngDoBootstrap() {}

  registerCustomElements() {
    const HeaderElement = createCustomElement(HeaderComponent, {injector: this.injector});
    customElements.define('app-header', HeaderElement);

    const DescriptionElement = createCustomElement(DescriptionComponent, {injector: this.injector});
    customElements.define('app-description', DescriptionElement);
  }
}

我正在使用Angular 6中提供的角度自定义元素

谢谢!

2 个答案:

答案 0 :(得分:0)

好的我使用下面的代码解决了,问题是与嵌套的css代码相关的东西然后你需要在你的子自定义元素(在这种情况下;jQuery(document).ready(function($){ // browser window scroll (in pixels) after which the "back to top" link is shown var offset = 300, //browser window scroll (in pixels) after which the "back to top" link opacity is reduced offset_opacity = 1200, //duration of the top scrolling animation (in ms) scroll_top_duration = 700, //grab the "back to top" link $back_to_top = $('.cd-top'); //grab the "back to bottom" link $back_to_bottom = $('.cd-bottom'); //hide or show the "back to top" link $(window).scroll(function(){ ( $(this).scrollTop() > offset ) ? $back_to_top.addClass('cd-is-visible') : $back_to_top.removeClass('cd-is-visible cd-fade-out'); if( $(this).scrollTop() > offset_opacity ) { $back_to_top.addClass('cd-fade-out'); } }); //smooth scroll to top $back_to_top.on('click', function(event){ event.preventDefault(); $('body,html').animate({ scrollTop: 0 , }, scroll_top_duration ); }); //hide or show the "back to bottom" link $(window).scroll(function(){ ( $(this).scrollBottom() > offset ) ? $back_to_bottom.addClass('cd-is-visible') : $back_to_bottom.removeClass('cd-is-visible cd-fade-out'); if( $(this).scrollBottom() > offset_opacity ) { $back_to_bottom.addClass('cd-fade-out'); } }); //smooth scroll to bottom $back_to_bottom.on('click', function(event){ event.preventDefault(); $('body,html').animate({ scrollTop: 0 , }, scroll_top_duration ); }); }); )中放入以下行<app-description>我将var encapsulation: ViewEncapsulation.None更改为descriptionTest

<强> description.component.ts

description

<强> description.component.html

@Component({
  selector: 'app-description',
  templateUrl: './description.component.html',
  styleUrls: ['./description.component.css'],
  encapsulation: ViewEncapsulation.None
})

<强> header.component.ts

<div>
    {{text}}
</div>

<强> header.component.html

  @Input() title: String;
  @Input() subtitle: String;
  @Input() description: String;

<强>的index.html

    <div class="header flex-container">
      <h1>{{ title }}</h1>
      <h2>{{ subtitle }}</h2>
      {{description}} <!-- shown correctly! -->
      <app-description text="{{description}}"></app-description>
    </div>

**App.module.ts**

@NgModule({
  declarations: [
    AppComponent,      
    HeaderComponent,
    DescriptionComponent  
  ],
  imports: [
    BrowserModule,    
  ],  
  providers: [],
  entryComponents:[
    HeaderComponent,
    DescriptionComponent
  ],
  bootstrap: []
})
export class AppModule {
  constructor(private injector: Injector) {

  }

  ngDoBootstrap() {
    this.registerCustomElements();
  }

  registerCustomElements() {
    const DescriptionElement = createCustomElement(DescriptionComponent, {injector: this.injector});
    customElements.define('app-description', DescriptionElement);

    const HeaderElement = createCustomElement(HeaderComponent, {injector: this.injector});
    customElements.define('app-header', HeaderElement);       
  }

src

output

使用此示例

github repository

答案 1 :(得分:0)

我找到了解决方案!

如果我们看到我的description.component.ts,则此组件的HTML标记为 app-description

@Component({
  selector: 'app-description',
  ...

在我的app.module.ts中,我将DescriptionComponent注册为角色元素,如下所示:

const DescriptionElement = createCustomElement(DescriptionComponent, {injector: this.injector});
customElements.define('app-description', DescriptionElement);

请注意,我声明元素与组件具有相同的标记。 我改为:

const DescriptionElement = createCustomElement(DescriptionComponent, {injector: this.injector});
customElements.define('app-descriptions', DescriptionElement);

现在我可以在任何HTML文件中使用自定义元素,如下所示:

<body>
  <app-descriptions text="Probando 1"></app-descriptions>
</body>

并在我的Header模板中使用DescriptionComponent,如:

 <app-description text="{{descriptionText}}"></app-description>

我的结论是:使用与组件的HTML标记不同的HTML标记声明您的Angular元素。

感谢所有合作的人!