Angular2 Dynamic Change CSS-Eigenschaft

72

Wir erstellen eine Angular2-Anwendung und möchten in der Lage sein, eine globale CSS-Variable zu erstellen (und die Werte der Eigenschaften zu aktualisieren, wenn sie geändert werden, wenn die Variable zugewiesen wird).

Wir hatten Polymer für eine Weile verwendet (jetzt wechseln wir zu Angular2-Komponenten) und wir hatten CSS-Eigenschaften verwendet (Polymer hat einige Polyfills) und wir hatten nur Stile mit aktualisiert Polymer.updateStyles().

Gibt es eine Möglichkeit, eine ähnliche Funktion zu erreichen?

BEARBEITEN:

Wir möchten etwas Ähnliches wie Sass color: $g-main-coloroder benutzerdefinierte CSS-Eigenschaften color: var(--g-main-color)und wann immer wir uns entscheiden, den Wert der Eigenschaft zu ändern, z. B. etwas Ähnliches updateVariable('g-main-color', '#112a4f'), das den Wert überall dynamisch aktualisiert. All das, während eine App läuft.

EDIT 2:

Ich möchte einige globale CSS-Variablen in verschiedenen Teilen (Host, untergeordnetes Element ...) meines CSS verwenden und den Wert sofort ändern können. Wenn ich also meine Farbvariable ändere, ändert sich dies überall in der App.

Ich werde zum Beispiel die Sass-Syntax verwenden:

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

Ist es möglich, so etwas wie Winkelrohre zu verwenden? (Aber es funktioniert angeblich nur in HTML)

:host { border: 2px solid {{ 'my-color' | cssvariable }} }
:host .some-label { color: {{ 'my-color' | cssvariable }} }
Tenhobi
quelle
2
Ich bin interessiert zu wissen, welchen Ansatz Sie gewählt haben. Wir haben ähnliche Anforderungen.
Yousuf
Ich habe noch keine Lösung dafür. Der einzige vernünftige heutige Ansatz ist wahrscheinlich die Verwendung von CSS-Variablen mit einer Art Polyfill ...
Tenhobi,
Kennen Sie eine Polyfüllung, die in angle2 zum Ersetzen von Variablen verwendet werden kann?
Yousuf
Gibt es einen Grund, warum das Binden an Objekte mit ngStyle nicht funktioniert? Diese Objekte können von überall her kommen und Sie können sie zur Laufzeit nach Belieben ändern. Auf diese Weise müssen Sie die Eigenschaft oder den Wert nicht im Voraus kennen. Sie strukturieren lediglich ein Objekt, weisen es dem Wert zu, an den das Element gebunden ist, und die Änderung erfolgt. Dies bedeutet, dass Sie jede Art von vorgefertigtem, statischem oder kompiliertem CSS aus der Gleichung herausnehmen können. Wenn dies nicht gut ist, können Sie jederzeit alle Ihre Elemente an innerHTML binden und das innerHTML ändern, indem Sie einen gestalteten Bereich anwenden, den Sie dynamisch erstellen.
Tim Consolazio

Antworten:

21

Verwenden Sie einfach Standard-CSS-Variablen:

Ihr globales CSS (zB: styles.css)

body {
  --my-var: #000
}

In der CSS Ihrer Komponente oder was auch immer es ist:

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

Anschließend können Sie den Wert der Variablen direkt mit TS / JS ändern, indem Sie den Inline-Stil auf das HTML-Element setzen:

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

Andernfalls können Sie jQuery dafür verwenden:

$("body").css("--my-var", "#fff");
monkeythedev
quelle
2
Dies ist genau das, was ich wollte, danke für das Teilen
Noopur Dabhi
Ist die Verwendung von direkter DOM-Manipulation und jQuery nicht der letzte Ausweg bei Verwendung von Angular 2.0+?
Riesen Elk
Überprüfen Sie dies heraus, Renderer2 von Angular docs: angular.io/api/core/Renderer2
Giant Elk
@GiantElk Richtig, aber ich ändere nur einen CSS-Variablenwert. Da das Binden von CSS-Variablen in ngStyle nicht unterstützt wird , ist dies meiner Meinung nach die einfachste Lösung. Persönlich würde ich niemals eine schwierige API wie Renderer verwenden, nur um einen Wert einer Variablen zu ändern.
Monkeythedev
69

1) Verwenden von Inline-Stilen

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

2) Verwenden Sie mehrere CSS-Klassen, die Ihren Wünschen zugeordnet sind, und wechseln Sie die Klassen wie folgt:

 /* 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">

Codebeispiele von: https://angular.io/cheatsheet

Weitere Informationen zur ngClass-Direktive: https://angular.io/docs/ts/latest/api/common/index/NgClass-directive.html

Gerard Sans
quelle
2
Dies mag funktionieren, aber es gibt ein Problem: Sie müssen dynamische Stile von der CSS-Datei trennen, was niemals der beste Weg ist. :( Ich möchte lieber etwas in CSS haben, aber ich werde mich wahrscheinlich
darum kümmern müssen
Ich verstehe nicht. Verwenden Sie SASS / LESS. Für dynamische Stile aus JavaScript kann ich nur diese sehen. Auf jeden Fall können Sie statische und dynamische Stile nur mischen, wenn Sie es falsch machen. Statisch: CSS. Dynamisch: JavaScript.
Gerard Sans
Ich habe gesagt, dass es schön wäre, so etwas wie Angular2-Pipes zu haben - die Möglichkeit, es in die CSS-Datei oder den CSS-Bereich zu schreiben. Aber es ist wahrscheinlich nicht möglich, also muss ich es so machen, wie Sie es in 1) geschrieben haben, und vielleicht einfach einen Kommentar in die Sass-Datei einfügen, dass eine globale Variable von außen verwendet wird (oder sein sollte).
Tenhobi
Wenn Sie sich abenteuerlustig fühlen, können Sie einen Schritt erstellen, um SASS zu übernehmen und ein JS-Modul auszugeben, das Sie importieren können ^ _ ^
Gerard Sans
Nicht nützlich für Variablen, die Zahlen enthalten. Sie möchten keine 10000 Klassen erstellen
Milad
5

Sie haben keinen Beispielcode, aber ich nehme an, Sie möchten so etwas tun?

@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>`
})

Sie weisen ng-classeine Variable zu, die dynamisch ist (eine Eigenschaft eines Modells, die, TodoModelwie Sie sich vorstellen können, aufgerufen wird ).

todo.toggle()ändert den Wert von todo.statusund dort ändert sich für die Klasse der Eingabe.

Dies ist ein Beispiel für den Klassennamen, aber Sie können das gleiche für CSS-Eigenschaften tun.

Ich hoffe das hast du gemeint.

Dieses Beispiel ist für das großartige Egghead-Tutorial hier genommen .

Shikloshi
quelle
5
Das wollen wir nicht. Wir möchten etwas wie in Sass color: $g-main-coloroder in benutzerdefinierten CSS-Eigenschaften color: var(--g-main-color)und wann immer wir uns entscheiden, den Wert der Eigenschaft zu ändern, z. B. etwas wie JS updateVariable('g-main-color', '#112a4f'), wird der Wert überall dynamisch aktualisiert. All das, während eine App läuft.
Tenhobi
2

Ich habe diesen Plunker gemacht , um einen Weg zu finden, um das zu tun, was Sie wollen.

Hier bekomme ich mystylevon der übergeordneten Komponente, aber Sie können es von einem Dienst bekommen.

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 {}
bertrandg
quelle
Ich muss in der Lage sein, Stile von Host- und untergeordneten Elementen zu ändern, was ich mit Ihrer Lösung nicht kann, und es ist eine Art chaotischer Schreibstile von außerhalb des "CSS-Bereichs". Schauen Sie sich EDIT 2 an. Übrigens. Anstatt Farbe von der Eingabe über ein Attribut zu übernehmen, ist es besser, einfach eine Klasse zu importieren und eine Variable daraus zu verwenden, da ich globale Variablen für die gesamte App möchte. ;)
Tenhobi
-2

Angular 6 + Alyle UI

Mit der Alyle-Benutzeroberfläche können Sie die Stile dynamisch ändern

Hier ein 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>

Zum Ändern des Stils

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

Enm
quelle
Die Frage ist über Dart. Ich denke, das wird nicht funktionieren.
Günter Zöchbauer