Angular 2/4/5/6-在其组件类方面转换自定义组件的innerHTML

时间:2018-08-06 16:19:07

标签: javascript angular typescript angular-material material-design

我想制作以下基本组件:card.component将用户在其innerHTML上定义的内容带入其组件类,以便可以对其进行转换并将其显示在其模板上。

这是用户将使用此组件的方式:

<app-card>hello world, this is a sample text</app-card>

您在StackBlitz.com上有一个基础项目,可以对其进行分叉以使其正常工作。

https://stackblitz.com/edit/angular-cmdpgh?file=src%2Fapp%2Fcomponents%2Fcard%2Fcard.component.ts

这是代码的预览:

import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'app-card',
    templateUrl: 'card.component.html',
    styleUrls: [ 'card.component.css' ],
})
export class CardComponent implements OnInit {

  private content: string;

  ngOnInit() {
    // please, override this to get the real innerHTML on: 'app.component.html'
    let innerHTML = 'testing';
    this.content = CardComponent.complexStrTransform(innerHTML);
  }
  private static complexStrTransform(str: string): string {
    // complex transformations here
    let result = '';
    for (let i = 0; i < str.length; i++) {
      let c = str[i];
      result += c;
      result += c.toUpperCase();
      result += '|';
    }
    result = '!!!' + result + '!!!';
    return result;
  }
}
<mat-card>
    <mat-card-content>
        {{content}}
    </mat-card-content>
    <mat-card-actions>
        <button mat-button>LIKE</button>
        <button mat-button>SHARE</button>
    </mat-card-actions>
</mat-card>

{{content}}的位置上,组件应显示以下结果:complexStrTransform(...)

我在某些地方可以使用:<ng-content></ng-content>在组件模板上指定要放置innerHTML的位置,但是我认为这不是最好的选择,因为我需要用非常复杂的更改来转换innerHTML,而这些更改只能在组件类上完成。

有什么建议吗?

感谢您的关注。

2 个答案:

答案 0 :(得分:0)

我不确定这正是您所需要的,但是我尝试编写一个小的解决方案来与您的示例进行常规的组件交互,

  1. 在卡片组件中,

添加一个输入,稍后我们可以从主应用程序组件中使用

 @Input('complexInput') complexInputContent: string;

然后将innerHTML初始化为添加的全局输入

 let innerHTML = this.complexInputContent;
  1. 如下更新您的应用程序组件,

<app-card  [complexInput]="contentDiv.innerText">


<div #contentDiv contenteditable="true" >

hello world, this is a sample text

</div>


</app-card>

这是有效的解决方案(预览):https://angular-k5wjbp.stackblitz.io/

可编辑的代码:https://stackblitz.com/edit/angular-k5wjbp

参考:https://angular.io/guide/component-interaction

答案 1 :(得分:0)

Dilusha的先前答案已完成部分工作。另一部分是将转换功能实现为管道,并使用一些DOM技巧。 Here is is on Stackblitz

首先,将您的转换函数作为Pipe重新处理(并重构组件):

import { Component, Pipe, PipeTransform } from '@angular/core';

@Component({
  selector: 'app-card',
  templateUrl: 'card.component.html',
  styleUrls: ['card.component.css'],
})
export class CardComponent { }

@Pipe({ name: 'complexStr' })
export class ComplexStrPipe implements PipeTransform {
  transform(str: string): string {
    // complex transformations here
    let result = '';
    for (let i = 0; i < str.length; i++) {
      let c = str[i];
      result += c;
      result += c.toUpperCase();
      result += '|';
    }
    result = '!!!' + result + '!!!';
    return result;
  }
}

接下来,将ng-content标记添加到您的组件中,以便用户可以简单地插入内容。同时,使用display: none使用样式将其隐藏,并为其分配模板引用变量,以便您的组件可以访问它并使用管道将其显示:

<mat-card>
    <mat-card-content>
        {{inner.innerText | complexStr}}
    </mat-card-content>
    <mat-card-actions>
        <button mat-button>LIKE</button>
        <button mat-button>SHARE</button>
    </mat-card-actions>
</mat-card>
<div #inner style="display: none">
    <ng-content></ng-content>
</div>

现在您的组件可以正常工作了:

<app-card>hello world, this is a sample text</app-card>

显然,这有点破解,因为原始用户内容仍然存在于DOM中。但这可以有效地完成工作。