【问题标题】:How do you generate dynamic <style> tag content in Angular template at runtime?如何在运行时在 Angular 模板中生成动态 <style> 标签内容?
【发布时间】:2021-04-09 14:59:44
【问题描述】:

我有一个 Angular 组件,它在运行时动态生成 mat-checkbox,我需要用不同的颜色以不同的方式更改每个复选框的各个背景,而且我没有(不会)事先有信息,只能在运行时。

我有以下ng-template 复选框:

<ng-template #renderCheckbox let-id="id" let-attr="attr">
  <mat-checkbox 
    [checked]="attr.show"
    [color]="'custom-' + id"
    (change)="onChange($event.checked, attr)">
    {{attr.name}}
  </mat-checkbox>
</ng-template>

其中,模板中的attr 具有以下接口类型,这些信息是从Highcharts' 系列中提取的,我不想硬编码color

interface LinkedSeriesAttributes {
  id: string;
  name: string;
  index: number;
  color: string;
  checked: boolean;
}

由于无法预先创建 css 类,也无法直接将颜色应用于 mat-checkbox,因此我只能在模板开头生成 &lt;style&gt;...&lt;/style&gt;

在我的组件中,我的代码会生成这样的样式:

  .mat-checkbox.mat-custom-hello.mat-checkbox-checked .mat-checkbox-background::before {
    color: #6E8BC3 !important;
  }

  .mat-checkbox.mat-custom-world.mat-checkbox-checked .mat-checkbox-background::before {
    color: #9ED6F2 !important;
  }
  ...

但是,我尝试了各种方法将其转储到 &lt;style&gt; 中,但均未成功。我试过了:

<style>{{ dynamicCSSStyles }}</style>

其中,我的 IDE 显示花括号有错误,虽然它编译正常并且运行没有错误,但我什么也没得到,甚至看不到 &lt;style&gt; 标记。

我还尝试将&lt;style&gt; 包含在我的dynamicCSSStyles 变量中,而angular 只是将整个内容作为文本转储...

在 Angular 中生成&lt;style&gt; 的正确方法是什么。

【问题讨论】:

    标签: html css angular highcharts angular-material


    【解决方案1】:

    我发现了一种 REALLY 肮脏的“使这项工作”的方式,但它会导致 Angular 不断将 &lt;style&gt; 添加回 DOM。

    首先,将encapsulation 设置为ViewEncapsulation.None

    其次,创建一个函数来生成&lt;style&gt;标签的老式方式带有id

      updateDynsmicStyleNode() {
        const id = 'dynamic-css-styles';
        const nativeElm = this.elmRef.nativeElement;
        const existing = nativeElm.querySelector(`style#${id}`);
        if (!existing) {
          const styleTag = document.createElement('style');
          styleTag.setAttribute('id', id);
          styleTag.innerHTML = this.dynamicCSSStyles;
          nativeElm.prepend(styleTag);
        } else {
          existing.innerHTML = this.dynamicCSSStyles;
        }
      }
    

    第三,在ngAfterViewChecked中调用我们的函数:

      ngAfterViewChecked() {
        this.updateDynsmicStyleNode();
      }
    

    我的意思是,虽然这行得通,真的很糟糕,因为在屏幕上移动鼠标会导致 Angular 不断地重新插入 &lt;style&gt; 标签。

    有没有人知道其他更合法的存档方式?哈哈

    【讨论】:

    • 最快的解决方法是创建一个变量_dynamicCSSStyles: string,并且只有在值发生变化时才更新innerHtml。因此,如果this.dynamicCSSStyles != _dynamicCSSStyles,您只会更新innerHTML。但更大的问题是您在ngAfterViewChecked 期间这样做(这种情况经常发生),而不是仅在它实际发生变化时才这样做。另一件可能有帮助的事情是组件上的ChangeDetectionStrategy.OnPush(但这是避免不必要的变更检测活动的更广泛策略的一部分)。
    【解决方案2】:

    您可以使用ngClass[class] 属性。因为您可以从 component.ts 文件中准备好样式。

    你可以这样做:

    Way 1: If you already know what the dynamic ids might be, (like if it always will be 'hello' and 'world')
    
    let dynamicClasses = {};
    
    // Once you get some classes from your logic, you can add them to the object above
    
    dynamicClasses['hello'] = 'custom-hello';
    dynamicClasses['world'] = 'custom-world';
    
    // Then in HTML
    <mat-checkbox [ngClass]="dynamicClasses"></mat-checkbox>
    
    
    
    Way 2: If you dont know what the classes also might be, like if its not always be hello or world, then create a method and call it where required, you might need to do something similar to @codenamezero said. 
    
    

    【讨论】:

    • 颜色和值不是预先确定的。所以即使我在某个地方有一个 CSS 类,我也不知道颜色。
    • 您能否给出您从中获取动态信息的代码示例以及如何获取它?我的意思是价值。这样我就可以看一下代码,也许会给你一些建议
    • 我在第一篇文章中添加了一些内容,但本质上,我试图从多个 Highcharts 动态读取系列,解析其系列以获取 idname、@ 987654327@、color 等,然后动态地动态生成一组复选框来切换它们。我已经让它工作了,除了我希望 mat-checkbox 背景颜色与系列颜色相匹配。
    • 如果没有真正简单易用的方法来归档我正在尝试做的事情,我想我别无选择,只能提前强制/限制颜色,而不是抓取和设置它们像那样动态地。如果我不使用mat-checkbox,它会起作用,但是因为我使用的是mat-checkbox,并且我没有直接设置/更改它的属性,所以操纵颜色要困难得多。
    猜你喜欢
    • 1970-01-01
    • 2016-08-27
    • 2011-05-02
    • 2012-12-13
    • 2019-07-10
    • 2023-03-03
    • 2011-02-15
    • 1970-01-01
    • 2016-02-01
    相关资源
    最近更新 更多