基于变量生成动态CSS的Angular方法

53

我正在处理一个使用Angular 4开发的管理面板,并尝试集成一个部分来自定义样式,例如更改颜色、背景等。

我已经开发了一个部分来将设置保存在数据库中,并使用API将它们作为JSON在应用程序加载时获取。

现在我正在尝试使用JSON值生成动态CSS,但是我在主组件中尝试以下代码却无法实现:

@Component({
      templateUrl: 'card.html',
      styles: [`
        .card {
          height: 70px;
          width: 100px;
          color: {{css.cardColor}};
        }
      `],
})

我不确定应该如何在组件中加载CSS值并在样式标签中使用它们。我没有找到其他解决方案。

另一种方法是使用Angular动画概念,但CSS将会非常庞大,并且不可能使用触发器和所有内容来实现它。我相信这个问题有解决方案,因为它似乎是一个真正的需求,许多其他开发人员也应该已经处理过了。

任何帮助都是可欣赏的。

编辑:不能使用ngStyle,因为它将应用于几乎所有元素,因为它是整个应用程序,而不仅仅是特定元素。


2
我认为这将是一个非常优秀的功能请求。 - bvdb
6个回答

52
你可以使用ngStyle从JSON中动态地添加css到你的页面中。
<div [ngStyle]="{'color': variable ? 'red' : 'blue'}"></div>

另一个例子:

 <div md-card-avatar [ngStyle]="{'background-image': 'url(' + post.avatar + ')', 'background-size': 'cover'  }"></div>

这里我从JSON数据中加载了背景图片。


1
那是一个很好的建议Ajinkya,但正如我所提到的,这将是一个巨大的CSS,并且将应用于几乎每个元素。因此不能使用ngStyle。 - Vikram
1
@Vikram,此问题已经在https://github.com/angular/angular/issues/7108上进行了记录。同时还有一些建议,这可能对你有所帮助。 - Ajinkya Dhote

36

在 Angular 中可用的直接方法是使用 ngStyle,示例如下:

<div [ngStyle]="{'color': style.colorVal ? style.colorVal : '#000', 'font-size' : style.fontSize ? style.fontSize : '16px' }"></div>

在尝试了不同的方法和途径来将动态CSS添加到 Angular 应用程序的所有页面之后,我得出了以下解决方案。

要求:根据从 API 返回的值生成动态 CSS 以更改设计和样式。

解决方案:

  1. 创建一个新组件并创建一个服务来从 API 加载动态 CSS 变量。
  2. 在模板文件中添加样式标签,并使用变量值设置属性。
  3. 在所有页面或主模板上加载此模板。
  4. 在应用程序构建时,样式将被移动到头部标记。

代码示例

import { CssService} from './Css.service';

@Component({
  selector: 'DynamicCss',
  templateUrl: './DynamicCss.component.html',
  styleUrls: ['./DynamicCss.component.scss']
})
export class ServiceProviderComponent implements OnInit {
    cssVariables: any;
    constructor(private cssService:CssService){
        /* call the service/api to get the css variable values in cssVariables */

    }
}

现在使用 jQuery 或 JavaScript 应用 CSS,通过以下函数追加 CSS。
appendCss(customData)
{
     let text = '.custom-form-1 {
            background-image: url("`+customData.background_image+`");
         }';
     $(document).ready(function(){
         $("style").append(text);
      });
}

加载自定义数据后,可以像我在ngOnInit中所做的那样调用此函数。

ngOnInit(){
 this.appendCss(this.customizeFormData);
}

如果您不想在Angular应用中使用jQuery,也可以使用JavaScript / TypeScript来完成此操作。

其他有用的资源:https://github.com/angular/angular/issues/9343#issuecomment-312035896


你应该在这里发布代码解决方案。你能展示一下如何在CSS样式属性中使用变量值吗? - Vignesh.N
1
我刚刚尝试了使用Angular 4和Angular CLI ~1.6.0,但是没有成功,但是这个方法有效:https://github.com/angular/angular/issues/9343#issuecomment-312035896 - Mateo Tibaquira
这个答案不完整。 - Ninja Coding
@NinjaCoding 这个项目还有哪些方面是不完整的? - Vikram
现在有没有一种方法可以根据组件变量创建真正动态的基于CSS的样式?我需要覆盖Bootstrap变量(类似于$primary: {{myColor}}),据我所知,这种方式是不可能实现的。 - Frimlik
显示剩余5条评论

16

您只能绑定style.color属性:

<div class="card" [style.color]="cardColor">lorem ipsum</div>

6

ngClass 用于根据变量值设置动态类基础,如下所示:

Ts文件组件:

@Component ({
    selector:'simple-comp',
    template:`   <ol class="breadcrumb">
        <li *ngClass="{'active': step==='step1'}" (click)="step='step1; '">Step1</li>
        <li *ngClass="{'active': step==='step2'}"  (click)="step='step2'">Step2</li>
        <li *ngClass="{'active': step==='step3'}" (click)="step='step3'">Step3</li>
       </ol>`
})

export class SimpleComponent {
    public step: string = 'step1'; // change value like step1, step2, step3
}

HTML代码:

<some-element [ngClass]="{'first': true, 'second': true, 'third': false}">
 ...
</some-element>

0

在背景使用中,JSON方法用于颜色:

<ion-list-header class="background-size"
[ngStyle]="{'background-image': 'url(' + data.headerImage + ')'}"
*ngIf="data.headerImage != null">

6
虽然此代码可能解决了提问者的问题,但最好还是解释一下你的代码如何解决了这个问题。这样,未来的访问者就可以从你的帖子中学习并应用到自己的代码中。SO不是一个编码服务,而是一个知识资源。同时,高质量、完整的答案更容易获得点赞。这些特点以及所有帖子都必须是自包含的要求,是SO作为平台的一些优势,使其与论坛有所区别。你可以编辑以添加附加信息和/或使用源文件文档来补充你的解释。 - ysf
你或者其他人能否解释一下:“JSON方法用于颜色”? - Simon_Weaver

0

我想要动态地为组件中嵌套的元素(具体来说是http://tb.github.io/ng2-nouislider/)设置样式,所以像楼上所说,ngStyle并不适用。

我的方法是在模板中使用引用变量(https://angular.io/api/core/ViewChild)来访问组件的本地元素,并使用querySelector(https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)查找目标子节点。

然后使用Renderer 2应用所需的样式。以下是示例,也可以在https://stackblitz.com/edit/angular-r3bs1d上查看。

import { Component, Renderer2, ViewChild, AfterViewInit } from '@angular/core';

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

export class AppComponent implements AfterViewInit  {
    backgroundColour = '#ff0000';
    constructor(private renderer: Renderer2) { }
    @ViewChild('parent', { static: false }) parent;
    ngAfterViewInit(){
        this.renderer.setStyle(this.parent.nativeElement.querySelector('.child'), 'background', this.backgroundColour);
    }
}

HTML:

<div #parent>
    <div class="child">Child Element</div>
</div>

至少对于小的样式更改,我认为这是一个可行的解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接