60

I'm 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}};
        }
      `],
})

How to we reference property values inside the styles declaration?

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.

1
  • 2
    I think this would make an excellent feature request. Commented Jul 23, 2019 at 9:47

6 Answers 6

56

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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, an issue has been already filed for this https://github.com/angular/angular/issues/7108 there are some suggestion as well, this might be helpful to you
38

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

10 Comments

you should post the code solution here. can you please show how you use the variable values inside css style properties ?
can you post some code example of this solution? This looks to be a really good solution.
I just tried this with Angular 4 and Angular CLI ~1.6.0 and didn't work, but this worked: github.com/angular/angular/issues/9343#issuecomment-312035896
this answer is incomplete.
@NinjaCoding And in what terms its incomplete ?
|
17

You can bind only style.color:

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

Comments

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>

Comments

2

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

2 Comments

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.
Can you or someone else explain: "The JSON method is used for color"
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.