Angular2 dynamic change CSS property

2019-01-13 06:44发布

问题:

We are making an Angular2 application and we want to be able to somehow create a global CSS variable (and update the properties' values whenever changed when the variable is assigned).

We had used Polymer for a while (now we are switching to Angular2 components) and we had used CSS properties (Polymer has some polyfill) and we had just update styles using Polymer.updateStyles().

Is there any way how we can achieve a similar function?

EDIT:

We want something similar to Sass color: $g-main-color or to CSS custom properties color: var(--g-main-color) and whenever we decide to change the value of the property, e.g. something like updateVariable('g-main-color', '#112a4f') it dynamicly update the value everywhere. All that while an app is running.

EDIT 2:

I want to use some global CSS variables in different parts (host, child element...) of my CSS and be able to change the value immediately - so if I change my-color variable, it changes everywhere in app.

I will use Sass syntax for example:

:host { border: 2px solid $my-color }
:host .some-label { color: $my-color }

Is possible to use something like Angular pipes? (But it supposedly only works in HTML)

:host { border: 2px solid {{ 'my-color' | cssvariable }} }
:host .some-label { color: {{ 'my-color' | cssvariable }} }

回答1:

Just use standard CSS variables:

Your global css (eg: styles.css)

body {
  --my-var: #000
}

In your component's css o whatever it is:

span {
  color: var(--my-var)
}

Then you can change the value of the variable directly with TS/JS by setting inline style to html element:

document.querySelector("body").style.cssText = "--my-var: #000";

Otherwise you can use jQuery for it:

$("body").css("--my-var", "#fff");


回答2:

1) Using inline styles

<div [style.color]="myDynamicColor">

2) Use multiple CSS classes mapping to what you want and switch classes like:

 /* CSS */
 .theme { /* any shared styles */ }
 .theme.blue { color: blue; }
 .theme.red { color: red; }

 /* Template */
 <div class="theme" [ngClass]="{blue: isBlue, red: isRed}">
 <div class="theme" [class.blue]="isBlue">

Code samples from: https://angular.io/cheatsheet

More info on ngClass directive : https://angular.io/docs/ts/latest/api/common/index/NgClass-directive.html



回答3:

You don't have any example code but I assume you want to do something like this?

@View({
directives: [NgClass],
styles: [`
    .${TodoModel.COMPLETED}  {
        text-decoration: line-through;
    }
    .${TodoModel.STARTED} {
        color: green;
    }
`],
template: `<div>
                <span [ng-class]="todo.status" >{{todo.title}}</span>
                <button (click)="todo.toggle()" >Toggle status</button>
            </div>`
})

You assign ng-class to a variable which is dynamic (a property of a model called TodoModel as you can guess).

todo.toggle() is changing the value of todo.status and there for the class of the input is changing.

This is an example for class name but actually you could do the same think for css properties.

I hope this is what you meant.

This example is taken for the great egghead tutorial here.



回答4:

I did this plunker to explore one way to do what you want.

Here I get mystyle from the parent component but you can get it from a service.

import {Component, View} from 'angular2/angular2'

@Component({
  selector: '[my-person]',
  inputs: [
    'name',
    'mystyle: customstyle'
  ],
  host: {
    '[style.backgroundColor]': 'mystyle.backgroundColor'
  }
})
@View({
  template: `My Person Component: {{ name }}`
})
export class Person {}


回答5:

Angular 6 + Alyle UI

With Alyle UI you can change the styles dynamically

Here a demo stackblitz

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    CommonModule,
    FormsModule,
    HttpClientModule,
    BrowserAnimationsModule,
    AlyleUIModule.forRoot(
      {
        name: 'myTheme',
        primary: {
          default: '#00bcd4'
        },
        accent: {
          default: '#ff4081'
        },
        scheme: 'myCustomScheme', // myCustomScheme from colorSchemes
        lightGreen: '#8bc34a',
        colorSchemes: {
          light: {
            myColor: 'teal',
          },
          dark: {
            myColor: '#FF923D'
          },
          myCustomScheme: {
            background: {
              primary: '#dde4e6',
            },
            text: {
              default: '#fff'
            },
            myColor: '#C362FF'
          }
        }
      }
    ),
    LyCommonModule, // for bg, color, raised and others
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Html

<div [className]="classes.card">dynamic style</div>
<p color="myColor">myColor</p>
<p bg="myColor">myColor</p>

For change Style

import { Component } from '@angular/core';
import { LyTheme } from '@alyle/ui';

@Component({ ... })
export class AppComponent  {
  classes = {
    card: this.theme.setStyle(
      'card', // key
      () => (
        // style
        `background-color: ${this.theme.palette.myColor};` +
        `position: relative;` +
        `margin: 1em;` +
        `text-align: center;`
         ...
      )
    )
  }
  constructor(
    public theme: LyTheme
  ) { }

  changeScheme() {
    const scheme = this.theme.palette.scheme === 'light' ?
    'dark' : this.theme.palette.scheme === 'dark' ?
    'myCustomScheme' : 'light';
    this.theme.setScheme(scheme);
  }
}

Github Repository