Dynamically changing CSS value in Ionic 3 - html

In my app, I have movies' details that can be opened, and I want the buttons of the detail to match the movie.
For instance, with the movie "Back to the Future", I have in my data colors = ["#000000","#123123"].
If I do <div [ngStyle]="{'background-color': movie?.colors[0]}"> the div will be of the color I wanted.
My question is, in Ionic, how can I change variables.scss to have these colors (updated when we open a new movie) ?
Because we can't modify tabs with custom css, so I have to add it to variables.scss...

if you want to update any css color or value like font-size like the sass variable at run time use css variables in this way you can update any css property value at run time if it base on css variable like the color in my example but it 's can be any css value
consider this example
style.css
:root {
--color : red;
}
* {
color:var(--color)
}
AppComponent
colorList = ['green', 'blue'];
updateColor(color) {
document.documentElement.style.setProperty(`--color`, color);
}
Template
<button *ngFor="let c of colorList" (click)="updateColor(c)">{{c}}</button>
stackblitz demo 🚀🚀
sass variable are going to compile at build time to there values so they are not reusable at run time

For most use cases, it is convenient to programmatically change the CSS value of an element by mapping it with a variable. We want the CSS value to change every time we update the variable, not only through this.ngZone.run().
<div class="progress" [style.height]=currentLevelPercentage>
This example has shown how we can map the height CSS property of the div element (class progress) to the variable currentLevelPercentage and change its value dynamically. currentLevelPercentage is the variable that must be compulsorily present in the TypeScript file.

For those here to know how to change color of each tab background in super-tabs (ionic) here's my 4 tabs code (I can now change height and width with code too ^^).
in tabs-page.scss :
:root {
--color1: white;
--color2: white;
--color3: white;
--color4: white;
}
super-tab-button:nth-of-type(1) {
background-color: var(--color1)
}
super-tab-button:nth-of-type(2) {
background-color: var(--color2)
}
super-tab-button:nth-of-type(3) {
background-color: var(--color3)
}
super-tab-button:nth-of-type(4) {
background-color: var(--color4)
}
in tabs-page.html : do nothing particular
in tabs-page.ts :
constructor(public navCtrl: NavController, public navParams: NavParams) {
document.documentElement.style.setProperty('--color1', this.movie.colors[0]);
document.documentElement.style.setProperty('--color2', this.movie.colors[1]);
document.documentElement.style.setProperty('--color3', this.movie.colors[2]);
document.documentElement.style.setProperty('--color4', this.movie.colors[3]);
}
Thank you #malbarmawi !

Just an idea about changing style dynamically. here is what i am using
<span [style.width]=foo></span>
Change the value of ‘foo’ in your .ts file
https://angular.io/docs/ts/latest/guide/template-syntax.html#!#style-binding

Simply try this
[ngStyle]="{'background-color': item.color}"

Related

Dynamically change font, background colors in Angular

We have a web application built using Angular 9. It has colors for headers, borders and some menu backgrounds stored in multiple places in css files.
The ask is to change those as per client branding. So if ClientA logs in, they should start seeing those colors as #FF0000 and if ClientB logs in, they need to see those colors as #00FF00.
Other than inline styling every html with style="color:{{clientColor}} can you help suggest the best way to do this?
Thank you!
You can try to use :root selector and variables in it, and for body tag just overwrite these root variables, working example here: stackblitz
styles.scss:
:root {
--fontColor: #000;
}
.theme-dark {
--fontColor: red;
}
app.component.ts
export class AppComponent {
theme = 'theme-dark';
toggle(): void {
const body = document.body;
if (body.classList.contains(this.theme)) {
body.classList.remove(this.theme);
} else {
body.classList.add(this.theme);
}
}
}
app.component.html
<p>
Start editing to see some magic happen :)
</p>
<button (click)="toggle()">Toggle color font</button>
app.component.scss
p {
font-family: Lato;
color: var(--fontColor);
}
You can use this:
[style.color]="clientColor"

How to change color of mat-slide-toggle via html (Angular)

For a project I have used the mat-slide-toggle of the Materials library. Now I want to change the color of the slider and the circle, which are the classes mat-slide-toggle-bar and mat-slide-toggle-thumb. I can set the background-color of both via the css-file, but here's the catch. I have several slide-toggles which all need different colors. The colors are defined in a dataset available in the component. I can access this dataset in the html, but not in the css. I can't use style="background-color: ..." on the mat-slide-toggle because it is not on the right class. The two classes I need are not directly visible in the html.
Html looks like this:
<span *ngFor="let data of dataSets">
<mat-slide-toggle (change)="toggleDataSet($event)">{{data.label}}</mat-slide-toggle>
</span>
So I need to either access the dataset in the css or somehow be able to set the background-color on nested classes not visible in the html. Is there a way to do this?
For changing the color of the sliders dynamically, you can create a Directive that receives the color for the circle and the one for the slider as inputs. The directive add attributes on the element and adds the styling needed to change the colors:
There is a similar answer given for changing the color for a progress bar here: Change angular material progress bar color from code.
The directive you need looks like this:
#Directive({
selector: '[sliderColor]'
})
export class SliderColorDirective implements OnChanges {
static sliderNumberCounter = 0;
#Input() circleColor: number;
#Input() sliderColor: number;
styleElement: HTMLStyleElement = document.createElement('style');
attributeName: string;
constructor(private el: ElementRef) {
this.attributeName = `slider-color-${SliderColorDirective.sliderNumberCounter}`;
SliderColorDirective.sliderNumberCounter++;
const nativeEl: HTMLElement = this.el.nativeElement;
nativeEl.setAttribute(this.attributeName, '');
nativeEl.appendChild(this.styleElement);
}
ngOnChanges(): void {
this.setColors();
}
setColors(): void {
this.styleElement.innerText = `
[${this.attributeName}] .mat-slide-toggle-bar {
background-color: ${this.sliderColor};
}
[${this.attributeName}] .mat-slide-toggle-thumb {
background-color: ${this.circleColor};
}
`;
}
}
The directive can be used like this:
<mat-slide-toggle sliderColor [sliderColor]="'red'" [circleColor]="'black'">{{data.label}}</mat-slide-toggle>

Angular components how to use stylesheet defined be the user?

Assumed I have created an Angular component called button and I want the user, who implements it in their app to set the color of the button. Is there a other way than using Input() decorators?
The only alternative way that I'm were of is using ng::deep. But remember, this feature will become deprecated soon!
Follows an example of how to use it.
app.component.html:
<my-component>
<another-component>
<div class="buton"></div>
</another-component>
</my-component>
my-component.component.scss:
.someclasse ::ng-deep {
.button {
background-color: white;
}
}
#Input decorator is the best in this situation, for ex. :
button.component.html:
<button class="your-custom-buttom" [ngStyle]="{backgroundColor: color}">Button</button>
button.component.ts:
#Input() color = 'red'
app.component.html:
<app-button color="green"></app-button>
Other way, you could add some specific class to button component, and tell user to change it in styles.scss:
styles.scss:
.your-custom-buttom {
background-color: red;
}
button.component.html:
<button class="your-custom-buttom">button</button>
https://stackblitz.com/edit/angular-dyrn4f?file=src%2Fapp%2Fbutton%2Fbutton%2Fbutton.component.html

CSS set background image regarding class selector

I would like to set the background image of a div regarding its class. The web I am developing should show a set of game cards. Each card is contained in a div and have a class like this:
<div class="card value suit>
</div>
Being the suit and value for instance clubs and five respectively. So for instance, for a div container like this:
<div class="card seven clubs>
</div>
I wonder if there is a way via CSS to set its background-image to this attribute without writing this for each card:
.card.seven.clubs {
background-image: url("../../images/seven_clubs.png");
}
you can't really have dinamy classes with css only, you need some form or precompiler such as SASS to to convert from thing like
for every number do {
generate number properties
}
for every suite do {
generate suite css properties
}
to actual css code in the form of
.suite1{
property: value;
}
.suite2{
property:value
}
.number1{
property:value
}
or you can use Javascript and dynamically set styles on it
var cards = document.getElementsByClassName('card');
for (var i = 0; i++; i < cards.length){
var thisElementClasses = cards[i].classList;
let imageUrl = '../../images/'+thisElementClasses[0]+'_'+'thisElementClasses[1]'+'.png';
card[i].style.backgroundImage = imageUrl;
}

knockoutjs css binding value when boolean computed property is false/true

I am binding my currently selected item like this:
The selected item gets visible, but how can I give the unselected items an unselected/default background color? When I set a background color to the template class I do not see anymore the background color set from the selection via mouse click.
Is the problem maybe that I have 2 backgrounds set but none is removed?
<div data-bind="foreach: items">
<div class="cellContainer" >
<div class="template" data-bind="click: $parent.selectItem, css: { selected: isSelected }">
<div data-bind="text: number"></div>
</div>
</div>
</div>
.selected {
background-color: #0094ff;
}
Sounds like a cascade issue. Make sure your ".template" style is defined before your ".selected" style in your css file.
Make sure your selectItem method resets isSelected on all elements before setting it to true on the argument. A naive implementation could be:
var ViewModel = function() {
// Skipped the rest for brevity...
self.selectItem = function(item) {
// Deselect all items first
for (var i = 0; i < self.items().length; i++) {
self.items()[i].isSelected(false);
}
// Select the argument
item.isSelected(true);
};
};
See this jsfiddle for a demo.
However, it is often easier to keep a reference on the parent view model to the currently selected item, and change the css binding to something like:
css: { selected: $parent.TheOneSelectedItem().number() == number() }
See this fiddle for the alternate demo.
Something like this might work.
.template {
background-color: #fff;
}
.template.selected {
background-color: #0094ff;
}
It does not look like a knockout issue.