Angular 2+ dynamically generate css - css

For a given js variable, which has style information in it:
menuBgColor = "red";
In AngularJS I was able to use dynamically embedded style:
<div>
<style>
.menuElement{
background-color:{{menuBgColor}}
}
</style>
<div class="menuElement">...</div>
</div>
In Angular2+ I cannot use the same as above. When the view is rendered in the browser variable menuBgColor is not populated and the element is rendered as coded.
like this -
<body>
...other markup...
<div><style>.menuElement{background-color:{{menuBgColor}}}</style>
...markup...
</body>
I want to know that what are the other ways in angular 2+ to add dynamic styles to the view?
I know of ngStyle but the given example is a very small one.
In my case, I have to apply dynamic styles to each element of the whole app like button, borders, background, colors, tree controls,
sidebars etc. So ngStyle is very exhaustive.
I also do not have predefined theme files because theme is managed by a feature in our app where user can define his/her own theme. Here
I understand that I can refresh page to get the updated theme BUT
consider that there can be 'n' number of users with their own themes.
So in my use case, the only solution I can think of is that somehow variable interpolate and create an embedded css.
Any help is greatly appreciated.

You can try this:
<div [style.background-color]="yourVar"></div>
In this case the binding should work

There's no pretty way to do this without building a huge structure like Angular Material does. But, if your theme system is not so complex, I'd simply go with a dynamically rendering of the <link> tag to your theme like so:
import { Component } from '#angular/core'
import { DomSanitizer } from '#angular/platform-browser'
#Component({
selector: 'my-app',
template: `
<link rel="stylesheet" [href]="getThemeUrl()">
<div class="main">
{{'themes/css/'+ theme +'.css' }}
<select [(ngModel)]="theme" (change)="onThemeChanged(theme)">
<option value="red">Red</option>
<option value="blue">Blue</option>
<option value="yellow">Yellow</option>
</select>
</div>
`
})
export class AppComponent {
theme = 'red';
constructor(public sanitizer: DomSanitizer){}
getThemeUrl(){
return this.sanitizer
.bypassSecurityTrustResourceUrl('themes/' + this.theme + '.css');
}
}
Plunkr

Related

Angular Material matTooltip break line elements

Im using Angular 7 and Angular material matTooltip.
I want that the tooltip displays every element in the next line, something like this:
But, instead I'm getting this:
I got 3 elements per line, and I don't want that. I want one element/line.
My code is as follows:
app.component.ts
items=['15-09-2020: 200','16-09-2020: 200','17-09-2020: 200', '18-09-2020: 200'];
newItems = this.items.join("\r\n");
app.component.html
<div class="col col-sm-2" matTooltipPosition="after" matTooltip="{{ items}}"></div>
Check this example that is not working for me:
Stackbliz
Source : https://www.angularjswiki.com/material/tooltip/
It's a bit late, to people who want to have breaklines in the tooltip,
you create a custom class in your global CSS and add this class with "matTooltipClass".
HTML
<button mat-raised-button
matTooltip="Multiline Tooltip 
 This is second line"
matTooltipClass="multiline-tooltip">
Multiline tooltip
</button>
Global CSS
.multiline-tooltip{
white-space: pre-line;
}
You can also add in your specific component, you should add
encapsulation: ViewEncapsulation.None
to your component.ts
#Component({
selector: 'app-tooltip',
templateUrl: './tooltip.component.html',
styleUrls: ['./tooltip.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class TooltipComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
https://siderite.dev/blog/styling-angular-material-tooltips.html/
Hope this can help others
The answer from Asaf is working perfectly for me.
Angular 14
matTooltip="Component: Test
Last updated date: 2023-01-17T09:17:02.753Z"
Mattooltip
I have fixed this in my project using
So, what you'll need to do is:
newItems = this.items.join("
");
Another thing, you need to change this:
matTooltip="{{ items}}"
To this:
[matTooltip]="items"

How to load different .css files on different components of a react application?

I have two .jsx files that represent their respective components.
The first one is, Blog.jsx
import React from "react";
import '../assets/css/blog.css';
export const Blog = () => (
<div>
<h1>Hello Blog</h1>
</div>
)
With its respective CSS file, blog.css
div { background: #ff481f; }
and the second one is, Landing.jsx
import React from "react";
import '../assets/css/landing.css'
export const Landing = () => (
<div>
<h1>Hello Landing</h1>
</div>
)
With its respective CSS file, landing.css
div { background: #86ff2b; }
I have added routing and called instances of those two components on the App.js file which is the default file of a React application. After running the application, when navigated to components, I faced a problem that the background color is the same for both of the components (It loads landing.css only and never changes).
How can I fix that problem that each component only uses its respective .css file and loads it?
By default webpack and other build tools will compile all CSS files into one, even if css was imported in separate JSX files. So you can't use different CSS files and expect you don't affect on another part of page.
You have some options:
Use BEM for naming class names.
Use cssModules. In this case elements will have their own css class name and styles will not affect any other elements except if you use :global selector.
css-module
Using html tags as css selectors is a bad practice (because there is the behaviour you describe).
You should use only css classes or inline styles (using id's is another bad practise, id's have high priority).
div {
width: 20px;
height: 20px;
}
#id {
background: red;
}
.class {
background: green;
}
<div id="id" class="class"></div>
In case using css classes there is the same problem (when you have two similar classes). And this case is decided using css modules (set of rules of building) or you can use css-in-js (external library) which has its pros and cons. Also you can use BEM (methodology) and if your application is not big you can avoid this trouble.
css modules will add to your classes random hash and instead .my-awesome-class-name you will get .my-awesome-class-name-dew3sadf32s.
So, if you have two classes .class in the first file and .class in the second file in the end you will get two classes .class-dew23s2 and .class-dg22sf and you styles will resolve as expected.
css-in-js is a similar way except you should write your styles using javascript with some profits like including only those styles that are needed at the moment (what you are looking for right now) and several others.
You can code using pure css / scss / postcss / etc but many companies already choose between css modules and css-in-js.
BEM is just naming conventions for your class names.
And lastly - if you use inline-styles using react you should remember:
{} is constructor of object and {} returns new object on every call, it's mean if you write something like:
class MyAwesomeComponent extends Component {
render() {
return <div style={{color: "red"}}></div>;
}
}
or
class MyAwesomeComponent extends Component {
render() {
const divStyles = {color: "red"};
return <div style={divStyles}></div>;
}
}
div will re-render every time your render will call because div takes new prop.
Instead, you should define your styles (for example) in outside of your class:
const divStyles = {color: "red"};
class MyAwesomeComponent extends Component {
render() {
return <div style={divStyles}></div>;
}
}
Don't define your css using HTML tags because it will affect your entire application.
use className,id or inline styling.
like- App.css
.myApp{ color: red;}
#myApp2{ color: blue;}
App.js
import './App.css'
<div className="myApp">color changed by className</div>
<div id="myApp2">color changed by id</div>
<div style={{color:'red'}}>color changed by inline object styling</div> // inline styling
This is not the best solution if you are looking forward to improve yours css imports/loads.
However could be the best solution if you dont want to go in deep in css, resolve the problem fast and keep working with HTML tag.
You can add a div for each component, define an Id for the div and wrap the component. Afterwards in the component's css fies you are going to define all the styles starting with the #id so all the css classe or HTML tag will affect just the corresponding component.
//App render in root
ReactDOM.render(
<App />,
document.getElementById('root')
);
//App
function App(props){
return [
<Blog />, <OtherComponent />
]
}
//Blog component
function Blog(props){
return <div id="blog">
<h1>I am Blog</h1>
</div>
}
//Other component
function OtherComponent(props){
return <div id="otherComponent">
<h1>Im am other component</h1>
</div>
}
/* blog.css*/
#blog h1{
color:yellow;
}
/* otherComponent.css*/
#otherComponent h1{
color:green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

increase decrease the font size of whole app in angular 6

I want to change the font size of whole app in one click. like in this article
Right now am trying to archive this by document.getElementsByTagName() and get element current font size and increase it. Unfortunately I cannot get the current font size. When I call document.getElementsByTagName('body').[index].style.fontSize, returns an empty string. Is there are any packages available to do this..? any suggestions?
you can use [ngClass] on your wrapper div. I have created a stack blitz for it
the idea is to change the class when you click on a button and define your classes with font sizes
getElementsByTagName() will retrieve an array of all element objects
with the specified tag name.
Now you have only one body tag and using this function to retrieve it is an overkill and not of much use. It's better to wrap your app with a tag having id like <div id="myAppView">....app....</div>
Then selecting the id and applying the modification.
I've created a Stackblitz: https://stackblitz.com/edit/angular-k2szyy which has a slight modification of your code using .getElementById()
TS:
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
change() {
document.getElementById('myAppView').style.fontSize = '50%';
}
}
HTML:
<div id="myAppView">
<hello name="{{ name }}"></hello>
<p>
Start editing to see some magic happen :)
</p>
<button
(click) = "change()"
>Update</button>
</div>

Use of '<style scoped>' in Nuxt.js (SPA)

I start the project with nuxt.js / express.
We have developed style scoped for each component (.vue) in nuxt.js. So, when routing , the property is overlaid on the same class name (style), so the page does not display properly.
1. What is the correct use of 'style scoped'?
2. Or should the routing process be <a> rather than <nuxt-link>?
What is the correct use of 'style scoped'?
The <style scoped></style> notation is not ambiguous, as the scoped attribute suggests, all the CSS elements defined within this scope apply only to the current component. If the CSS element exists globally, the scoped one -having the same name and type- takes precedence, that is, it overrides the globally defined CSS element.
For example, let us define in /components folder 3 components Component1.vue, Component2.vue, Component3.vue:
Component1.vue:
<template>
<div class="yellow-text">Component 1</div>
</template>
<script>
export default {
name: 'Component1'
}
</script>
<style>
.yellow-text {
color: yellow;
}
</style>
Component2.vue:
<template>
<div class="yellow-text">Component 2</div>
</template>
<script>
export default {
name: 'Component2'
}
</script>
<style scoped>
.yellow-text {
color: red;
}
</style>
Component3.vue:
<template>
<div class="yellow-text">Component 3</div>
</template>
<script>
export default {
name: 'Component3'
}
</script>
In Component1.vue, the text will be displayed in yellow.
In Component2.vue, the text will be displayed in red because the scoped CSS class takes precedence over the globally defined one in Component1.vue.
In Component3.vue, the text will be displayed in yellow.
So to respond to your question: there is no correct way because there is only one way to do that, and the meaning is not subject to any form of interpretation.
Or should the routing process be rather than ?
Even if <nuxt-link /> is rendered as <a href>, the documentation clearly states the former must be used to navigated through the Nuxt.js application and In the future, we will add features to the component, like pre-fetching on the background for improving the responsiveness of Nuxt.js Applications.

Using ngStyle on the body tag on the main index.html in angular 2

I couldn't find a way to use ngStyle on the index.html in the body tag using angular 2.
like on index.html:
<body ngStyle="bodyStyle">
Demo text
</body>
The only way I found is using "encapsulation: ViewEncapsulation.None" in the component, however, only works using standard css class but not using a variable or function as ngStyle,
Like, on the component styles:
body {
background: red;
}
I also found something similar on angularjs as the link below.
http://plnkr.co/edit/7cwAeGMsCYA8HIrWbl7d?p=preview
Is possible to have the same result in angular 2 as the link above ?
There is no way to do that. ngStyle only works in the template of an Angular component. <body> can't be inside a components template.
You can use https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style instead.
Another way would be to use 'body' as selector of your AppComponent and apply styles using #HostBinding()
#Component({
selector: 'body',
...
})
export class AppComponent {
#HostBinding('style.background-color')
backgroundColor:string = 'red';
}

Resources