【问题标题】:Styled HTML content dynamically switched with tabs using Angular 2使用 Angular 2 使用选项卡动态切换样式化的 HTML 内容
【发布时间】:2017-03-19 21:44:22
【问题描述】:

我正在尝试创建一个可重用的 angular2 组件,该组件接受我服务器上 html 文件的 URL 数组,并创建一个带有选项卡的内容窗口,以在“章节”之间切换,有效地交换内容窗口内的 html 和 css。我尝试了各种各样的东西,包括 iframe,但那些都不起作用,我可以在 StackOverflow 上找到的 angular 1 ng-include 变通办法,但它们都已被弃用,而我最接近的是构建一个组件您可以@Input html 并插入内容,但样式不会应用,并且角度会删除任何样式或脚本标签。这是我尝试过的。

在我的父组件类中:

htmlInput: string = "<h1>Why Does Angular make this so hard?</h1>";
cssInput: string = "h1 { color:red; }"

父组件 HTML:

<app-html [html]='htmlInput' [css]='cssInput'></app-html>

我的 HTML 组件:

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

@Component({
    selector: 'app-html',
    template: '<div [innerHtml]=html></div>', //This works but no style
    //template: '{{html}}', //This displays the actual markup on page
    styles: ['{{css}}'] //This does nothing
    //styles: ['h1 { color: red; }']//Also nothing
})
export class HtmlComponent implements OnInit {
    @Input() html: string = "";
    @Input() css: string = "";
    ngOnInit() {

    }
}

这段代码的结果是

为什么 Angular 让这件事变得如此困难?

但没有红色。也许在将 innerHtml 添加到 DOM 之前应用样式?我不知道,但只是放置 {{html}} 结果会显示带有可见 h1 标签的实际标记。

我想这样做的原因是,在我对网站进行角度化之前,我已经在服务器上的一个文件夹中创建了一堆 HTML 页面,它们都共享一个样式表。我希望能够像书中的页面一样翻阅它们,而无需重新加载页面,并且由于页面太多而且我可能会一直添加更多,我真的不想为每个页面创建路由一。 (我已经有基本站点导航的路由。)

关于如何在最新版本的 Angular 2 中将样式化的 HTML 动态嵌入到页面中,是否有人有更好的建议?在发布这篇文章时,我们处于 2.0.0-beta.17 中。

或者...我已经认为我可能从完全错误的角度来处理这个问题。 Angular 让这件事变得如此困难并且不赞成人们提出的所有解决方案肯定是有原因的,所以如果有人对我如何以更友好的角度实现相同的结果提出建议,我也很乐意听到。

谢谢。

编辑:

我能够通过创建一个管道来解决我的问题,该管道在将 html 添加到 iframe 之前对其进行清理。

import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Pipe({ name: 'safe' })
export class SafePipe implements PipeTransform {
  constructor(private sanitizer: DomSanitizer) {}
  transform(url: string) {
    return this.sanitizer.bypassSecurityTrustResourceUrl(url);
  }
}

然后你可以将你的 html 传递到 iframe 中。

<iframe width="100%" height="1000" frameBorder="0" [src]="url | safe"></iframe>

这对我很有用,因为我有一些使用各种 jquery 和样式等的旧页面。这是让它们显示出来的快速修复。

【问题讨论】:

标签: html css angular typescript angular2-template


【解决方案1】:

Angular2 通过将动态添加的属性(如 _ngcontent-yle-18)包含到 CSS 选择器中来重写添加到组件的样式。

Angular2 使用它来模拟阴影 DOM 样式封装。这些属性不会添加到动态添加的 HTML 中(例如 innerHTML)。

解决方法

  • 将样式添加到index.html,因为Angular2不会重写这些样式

  • 设置ViewEncapsulation.None,因为这样Angular就不会添加封装仿真属性

  • 使用/deep/ 让Angular2忽略封装仿真属性

另见Angular 2 - innerHTML styling

【讨论】:

  • 我能够通过将其放入索引来应用该样式。我不喜欢该解决方案,但我正在阅读有关您发布的其他解决方案和您提供的其他 SO 帖子的更多信息。你知道我在使用漂亮的打印或突出显示 js 时会遇到什么问题吗?有一些 html 页面有代码 sn-ps,我想应用语法着色。
  • 不确定你的意思。你指的是什么问题?我不希望出现问题。
  • 这些库会在页面加载后动态地将类添加到您的 或 <pre> 标记中,以便于语法着色。它似乎不想在 innerHtml 上工作。我想我真的在寻找一种方法,让我的页面的内部部分忽略所有角度规则,我可以在其中使用带有 jQ​​uery 和自定义样式的脚本标签等等。这样,我只需将旧的非角度网站的片段粘贴在我想要的地方。我只是梦想太大了吗?</pre>
  • 你只需要考虑一些事情。您不能将脚本标记添加到组件模板,因为它将被删除。还有其他方法可用(不知道这是否适用于您的用例)如果您使用默认视图封装,则无法将样式添加到组件中,因为它们会被重写。总有解决方法,这取决于您到底想做什么。
  • 好吧,我将为您提供一个有效的样式解决方案的答案。我将继续寻找解决我所有用例的另一种解决方法。如果我找到解决方案,我可能会回来编辑我的问题,这样它就不会与您发布的其他问题的信息相同。谢谢。
【解决方案2】:

您应该将您的 css 包装到一个对象中并使用 ngStyle 将其绑定到您的组件而不是 styles 属性,因为 styles 不支持数据绑定。

例子:

htmlInput: string = "<h1>Why Does Angular make this so hard?</h1>";
cssInput: string = "{h1 { color:red; }}"

父组件 HTML:

<app-html [html]='htmlInput' [css]='cssInput'></app-html>

您的 HTML 组件:

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

@Component({
    selector: 'app-html',
    template: '<div [innerHtml]="html" [ngStyle]="css"></div>',
    styles: []
})
export class HtmlComponent implements OnInit {
    @Input() html: string = "";
    @Input() css: string = "";
    ngOnInit() {

    }
}

【讨论】:

  • 异常:未捕获(承诺中):错误:./HtmlComponent 类 HtmlComponent 中的错误 - 内联模板:0:24 原因:找不到不同的支持对象 '{h1 { color:red; }}'
  • 检查上述响应,但似乎您需要禁用视图封装并将其设置为无。
猜你喜欢
  • 2016-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-13
  • 1970-01-01
相关资源
最近更新 更多