50

I am working on a admin panel developed with angular 4 and trying to integrate a sections to customize styling like change color, bg etc. I already have developed a sections to save settings in database got them on app load as json using API.

Now I am trying to generate a dynamic css using values from json, I tried with following code in main component but its not working

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

I am not sure how I should load the css values in component and use them in style tag. I didnt find any other solution for same.

Another way is to use angular animation concept but the css is going to be huge and its not possible to implements it whole with angular animation using triggers and all. I believe there is a solution for this as it seems a genuine requirements and should have done by lots of other developers.

Any help is appreciable.

Edit : can not use ngStyle as its going to be applied on almost all elements as its for whole application and not only for specific element.

Vikram
  • 3,171
  • 7
  • 37
  • 67

6 Answers6

49

You can use ngStyle to dynamically add the css to your page from json.

<div [ngStyle]="{'color': variable ? 'red' : 'blue'}"></div>

An another example:

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

here I have loaded background image from json-data.

Rafael
  • 1,281
  • 2
  • 10
  • 35
Ajinkya Dhote
  • 1,389
  • 3
  • 13
  • 26
  • 1
    Thats a good suggestion Ajinkya but as I mentioned its going to be a huge css and will be applied to almost every element. so can not use ngStyle – Vikram Sep 05 '17 at 05:38
  • 1
    @Vikram, an issue has been already filed for this [https://github.com/angular/angular/issues/7108](https://github.com/angular/angular/issues/7108) there are some suggestion as well, this might be helpful to you – Ajinkya Dhote Sep 05 '17 at 05:48
35

Direct approach available in angular is using ngstyle as follows

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

After going through different methods and approached to add dynamic css to all pages on angular app I ended up with following solutions.

Requirement : generate dynamic css based on values returned from and API to change design and styling.

Solution :

  1. create a new component and create a service to load dynamic css variables from API.
  2. Add style tag in template file and use variable values for properties.
  3. Load this template on all pages or on main template.
  4. On app build style will be moved to head tag.

Code sample

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

    }
}

Now apply css using jquery or javascript to append css with help of function like following

appendCss(customData)
{
     let text = '.custom-form-1 {
            background-image: url("`+customData.background_image+`");
         }';
     $(document).ready(function(){
         $("style").append(text);
      });
}

and call this function after loading custom data from service or other variable like I did it ngOnInit

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

Its using jquery but can be done with javascript/typescript as well if you dont want to use jquery in your angular app

Other useful resource https://github.com/angular/angular/issues/9343#issuecomment-312035896

Vikram
  • 3,171
  • 7
  • 37
  • 67
  • you should post the code solution here. can you please show how you use the variable values inside css style properties ? – Vignesh.N Nov 11 '17 at 19:37
  • can you post some code example of this solution? This looks to be a really good solution. – Neutrino Jan 16 '18 at 01:51
  • 1
    I just tried this with Angular 4 and Angular CLI ~1.6.0 and didn't work, but this worked: https://github.com/angular/angular/issues/9343#issuecomment-312035896 – Mateo Tibaquira Apr 03 '18 at 04:14
  • this answer is incomplete. – Ninja Coding Apr 18 '18 at 15:28
  • @NinjaCoding And in what terms its incomplete ? – Vikram Apr 19 '18 at 02:28
  • Answer is incomplete because of the lack of code refering to the most important of your answer, which is de css service – javier Cuervas May 27 '18 at 12:24
  • @VikramSingh Please remove the first half of this answer. According to this bug (https://github.com/angular/angular/issues/13802) and its linked duplicate, this feature is not implemented. I've tested {{interpolation}} in the – jcairney Oct 30 '18 at 15:07
  • @VikramSingh thanks! To be sure, I really wanted {{interpolation}} in the – jcairney Nov 09 '18 at 23:23
  • You should mark someone else's response as the answer since there was someone who suggested you use ngStyle – Eric Oct 28 '20 at 02:41
  • Is there nowadays a way how to create really dynamic css based on component variable? I need to override bootstrap variable (something like `$primary: {{myColor}}`), which is, as far as I know, not possible to achieve this way. – Frimlik May 20 '21 at 11:14
15

You can bind only style.color:

<div class="card" [style.color]="cardColor">lorem ipsum</div>
Eliseo
  • 50,109
  • 4
  • 29
  • 67
6

ngClass is used to set the dynamic class basis of your variable value as below

Ts File Component:

@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 Code:

<some-element [ngClass]="{'first': true, 'second': true, 'third': false}">
 ...
</some-element>
Prashant Pimpale
  • 10,349
  • 9
  • 44
  • 84
Rohan Fating
  • 2,135
  • 15
  • 24
0

I wanted to dynamically style an element nested within a component, (specifically http://tb.github.io/ng2-nouislider/), so similar to the OP, ngStyle was not suitable.

My approach was to use a reference variable in my template (https://angular.io/api/core/ViewChild) to access the native element of the component and find the target child node using querySelector (https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector).

The required style was then applied with Renderer 2. Example below and on 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>

For minor styling changes at least, I think this is a feasible solution.

Matt Saunders
  • 3,538
  • 2
  • 22
  • 30
0

For background use, the JSON method is used for color:

<ion-list-header class="background-size"
[ngStyle]="{'background-image': 'url(' + data.headerImage + ')'}"
*ngIf="data.headerImage != null">
Fahimeh Ahmadi
  • 813
  • 8
  • 13
  • 6
    While this code may resolve the OP's issue, it is best to include an explanation as to how your code addresses the OP's issue. In this way, future visitors can learn from your post, and apply it to their own code. SO is not a coding service, but a resource for knowledge. Also, high quality, complete answers are more likely to be upvoted. These features, along with the requirement that all posts are self-contained, are some of the strengths of SO as a platform, that differentiates it from forums. You can edit to add additional info &/or to supplement your explanations with source documentation. – ysf Jun 09 '20 at 21:39
  • Can you or someone else explain: "The JSON method is used for color" – Simon_Weaver Jul 16 '20 at 01:49