styling error when added styles using ngClass - css

When I only use class name like error and info the css works
Example: https://stackblitz.com/edit/github-i4uqtt-zrz3jb (using Angular latest version)
but when I renamed the css class and add more styles like for the example below the css and [ngClass] no longer work. Any idea guys ?
#HTML
<div fxLayout="row" fxLayoutAlign="space-between">
<div fxLayout="column" fxFlex="0 0 7%">
<mat-icon
[ngClass]="password.hasError('mininum') ? 'error-check-outline' : 'info-check-outline'">
check_circle_outline </mat-icon>
</div>
<div fxLayout="column" fxFlex="0 0 100%">
<span
[ngClass]="password.hasError('mininum') ? 'text-info-error' : 'text-info'">
8 characters mininum</span>
</div>
</div>
#ts
validateMinimumPassword: ValidatorFn = (control: AbstractControl) => {
if (control.value.length < 8) {
return { minimum: true };
}
return null;
};
#CSS
.text-info {
font-family: Inter;
font-style: normal;
font-weight: normal;
font-size: 14px;
color: #4caf50;
font-family: Manrope;
margin-top: 2.5px;
}
.text-info-error {
font-family: Inter;
font-style: normal;
font-weight: normal;
font-size: 14px;
color: #DDD;
font-family: Manrope;
margin-top: 2.5px;
}
.error-check-outline {
transform: scale(.74);
color: #DDD;
}
.info-check-outline {
transform: scale(.74);
color: #4caf50;
}

You have to wrap your ngClass condition in {} also change syntax
For Example:
[ngClass]="{'error-check-outline': password.hasError('minimum'), 'info-check-outline' : !password.hasError('minimum'
)}"

Everything should work, if you correct your typo mininum. Its minimum.
Working example: https://stackblitz.com/edit/so-68358839
Update: Why its green
You have the expression "password.hasError('mininum') ? 'text-info-error' : 'text-info'"
The ternary(conditional) operator syntax is like,
condition ? exprIfTrue : exprIfFalse
You gave password.hasError('mininum') and as it has a typo it returns null, which is falsey. So now the expression on the left is false,
and the .text-info will get selected. As that style makes the color green, it will become green.

you can write a method to return class based on condition
setClass(type) {
if (type == 'minimum') {
return 'class-one';
} else if (type == 'maxmimum') {
return 'class-two';
}
}
and then use this method in HTML like below
<div [ngClass]="setClass('minimum')"><div>
using this way you can clean your HTML

Related

How to set an element's class in svelte

I have a svelte application and I wish to highlight a row when the user clicks on it; similar to this simple code:
<div id="A" class="car-even">A</div>
<div id="B" class="car-odd">B</div>
<style>
.car-even {
color: #008800;
cursor: pointer;
}
.car-odd {
color: red;
cursor: pointer;
}
.car-selected {
color: blue;
background-color: #ffffaa;
cursor: pointer;
}
</style>
<script>
row = document.getElementById('A')
row.className = 'car-selected '
</script>
But in svelte the className does not seem to be updated correctly. What is wrong?
App.svelte
<script>
import Car from './cars.svelte'
let car = ''
$: console.log('Car', car)
</script>
<Car bind:selected_car={car}/>
Cars.svelte
<script>
let cars = ['Audi', 'BMW', 'Hillman', 'Hyundai', 'Jaguar']
export let selected_car = ''
let car_class = ['car-even', 'car-odd']
function carClicked(car) {
selected_car = car
let car_row = document.getElementById(car)
car_row.className = 'car-selected'
}
</script>
{#each cars as car, index (car)}
<div id={car} class="{car_class[index % 2]}" on:click={() => carClicked(car)}>{car}</div>
{/each}
<style>
.car-even {
color: #008800;
cursor: pointer;
}
.car-odd {
color: #000088;
cursor: pointer;
}
.car-selected {
background-color: #ffffaa;
cursor: pointer;
}
</style>
Your example doesn't seem to work, because the .car-selected css class isn't compiled, because it's not used anywhere (the compiler knows of). If you have a look at the html, the class gets added on click (but this also overwrites/removes the other class)
If you add :global() modifier :global(.car-selected), you see the class is applied
To do it the Svelte way, use the class:directive instead and add this to the div inside the each loop
class:car-selected={car === selected_car}
You could then get rid of carClicked() if you wanted REPL
{#each cars as car, index (car)}
<div id={car}
class="{car_class[index % 2]}"
class:car-selected={car === selected_car}
on:click={() => selected_car = car}
>
{car}
</div>
{/each}
((+ why not reduce repetition and make use of Svelte's scoped styling and add
div {
cursor: pointer;
user-select: none;
}
))

Vue button toggling CSS using checkbox

I am working on VueJS below is my css
.button-css {
align-items: center;
background-color: var(--azure-radiance);
border-radius: 30px;
display: flex;
height: 50px;
min-width: 200px;
padding: 0 60px;
}
.opensans-bold-white-18px {
color: var(--white);
font-family: var(--font-family-open_sans);
font-size: var(--font-size-xxxl);
font-style: normal;
font-weight: 700;
align-self: center;
}
and followed by Vue script
new Vue({
el: "#app",
data: {
termsState: false,
validated: false
},
computed: {
termsError() {
return this.validated && !this.termsState
}
},
methods: {
handleTermsState() {
this.validated = false
},
handleSubmit() {
this.validated = true
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id='app'>
<label for="terms">
Terms and Privacy Policy
<input type="checkbox" id="terms" name="terms" v-model="termsState" #change="handleTermsState">
{{ termsState }}
</label>
<div><button class="button-css opensans-bold-white-18px" type="submit" :disabled="!termsState" #click="handleSubmit">Submit</button></div>
</div>
The button retains the CSS only when it is enabled i.e 'oval shape button' when checkbox is ticked, when it is disabled it takes a gray rectangular shape button. I want to retain the shape of button as gray oval shape button disabled mode how to achieve it?
Below is the before and after images
I want both before and after images to be the oval shape
Actually it has nothing to do with Vue. All you have to do is to modify your CSS like this:
First remove the color property:
.opensans-bold-white-18px {
/* color: var(--white); */
font-family: var(--font-family-open_sans);
font-size: var(--font-size-xxxl);
font-style: normal;
font-weight: 700;
align-self: center;
}
Second, change your button css class to bind a computed property like this:
<button :class="cssClass" type="submit" :disabled="!termsState" #click="handleSubmit">Submit</button>
And add your computed property:
computed: {
cssClass() {
return "overlap-group-23 opensans-bold-white-18px button-css " + (this.termsState ? "button-enabled" : "");
}
}
Tested on both Safari and Chrome.
Is this what you want?

How to change CSS classes according to time received by API

I'm building a weather app in React and so far so good. The problem is now I want to have a "lightmode" and "darkmode" which should be CSS classes that change according to sunrise/sunset times received by an API. When I did it in vanilla JS I used a function that converted the timestamps into hours and compared the current hour to sunrise/sunset and then decided which class to present, like so
function getMode(response) {
let today = response.data.dt;
let timezone = response.data.timezone;
let difference = today + timezone - 3600;
let hours = timeConverter(difference);
let mode = document.getElementById("app");
let sunrise = response.data.sys.sunrise;
let difference2 = sunrise + timezone - 3600;
let currentSunrise = timeConverter(difference2);
let sunset = response.data.sys.sunset;
let difference3 = sunset + timezone - 3600;
let currentSunset = timeConverter(difference3) - 1;
if (hours > currentSunset) {
mode.classList.add("darkmode").remove("lightmode");
}
else if (hours < currentSunrise) {
mode.classList.add("darkmode").remove("lightmode");
} else {
mode.classList.remove("darkmode").add("lightmode");
}
}
axios.get(apiUrl).then(getMode)
<body>
<div id="app" class="lightmode">
The CSS then looked like this
.lightmode h1 {
font-family: "Josefin Sans", sans-serif;
text-align: right;
color: #06384d;
font-size: 32px;
font-weight: 700;
}
.lightmode {
font-family: "Josefin Sans", sans-serif;
background-image: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
border-style: solid;
border-radius: 30px;
border-color: #096386;
}
#app {
margin: 10px 400px;
padding: 10px 10px;
}
(...)
.darkmode h1 {
font-family: "Josefin Sans", sans-serif;
text-align: right;
color: #fff;
font-size: 32px;
font-weight: 700;
}
.darkmode {
font-family: "Josefin Sans", sans-serif;
background-image: linear-gradient(to top, #30cfd0 0%, #330867 100%);
border-style: solid;
border-radius: 30px;
border-color: #096386;
}
And that worked fine. Now in React (novice here) I don't know how to approach the problem. I've been reading about dynamically changing CSS classes in React with state but I can't figure out how to incorporate that with the API response. Any suggestions?
You can store className in state and change it in your function.
class Demo extends Component {
constructor(props) {
super(props);
this.state = {
stClass: "lightmode"
}
}
state = {
stClass: "lightmode"
}
componentDidMount = () => {
[call your function here and change the state of stClass]
}
render() {
return (
<div className={`${this.state.stClass}`}>
[your code here]
</div>
)
}
}
The key part of dynamically changing CSS classes in React would be:
<div className={`App ${this.state.displayMode}`}>
The class name of the container will be updated anytime the state for displayMode is changed and in this example, appended to the class App, resulting in App darkmode and rendered as such.
<div class="App darkmode">
Sample code / use case:
class App extends Component {
state = {
displayMode: "lightmode"
};
getMode = response => {
let _displayMode;
// Logic for determining the mode
return _displayMode;
}
componentDidMount() {
// Make API call here and run your logic to determine the mode
axios.get(apiUrl).then(getMode).then(displayMode => {
// As a callback to your function, set the state for displayMode
this.setState({
displayMode: displayMode
})
});
}
render() {
return (
<div className={`App ${this.state.displayMode}`}>
</div>
);
}
}

Polymer paper-spinner change color through class with data-binding

I use a polymer paper-spinner inside my web-component:
<dom-module id="custom-spinner">
<style include = 'custom-spinner-styles'>
paper-spinner.yellow{
--paper-spinner-layer-1-color: yellow;
--paper-spinner-layer-2-color: yellow;
--paper-spinner-layer-3-color: yellow;
--paper-spinner-layer-4-color: yellow;
}
</style>
<template>
<div class = "loader">
<paper-spinner class$="{{color}}"></paper-spinner>
</div>
<content>
</content>
</template>
</dom-module>
<script>
etc....
</script>
I use it like this:
<custom-spinner color = "yellow" size = "200px" fade-in-sp = "500" fade-out-sp = "400"></custom-spinner>
Now the problem is, that the data-binding works and the paper-spinners class is set to yellow, but the styles are not applied.
If I set 'yellow' directly it works perfectly:
<paper-spinner class="yellow"></paper-spinner>
Any ideas where the problem is?
Help would be greatly appreciated.
I am using data-binding for Styling in my gold-password-input and it is working like this:
.None {
color: var(--gold-password-input-strength-meter-none-color, --paper-grey-700) !important;
}
.VeryWeak {
color: var(--gold-password-input-strength-meter-veryweak-color, --paper-red-700) !important;
}
.Weak {
color: var(--gold-password-input-strength-meter-weak-color, --paper-orange-700) !important;
}
.Medium {
color: var(--gold-password-input-strength-meter-medium-color, --paper-yellow-700) !important;
}
.Strong {
color: var(--gold-password-input-strength-meter-strong-color, --paper-blue-700) !important;
}
.VeryStrong {
color: var(--gold-password-input-strength-meter-verystrong-color, --paper-green-700) !important;
}
and
<span id="strengthLabel">
[[strengthMeterLabels.Label]]:
<span class$=[[_strengthMeterScore]]>[[_computeStrengthMeterLabel(_strengthMeterScore)]]</span>
<paper-icon-button icon="info" alt="info" disabled noink></paper-icon-button>
</span>

Advanced CSS Selector - Select based on styling

Performance issues aside, is it possible to use a style as a selector? For example, something like:
div[background-image="img/someimg.jpg"] {opacity:.5}
My fallback plan is to use javascript and iterate over divs (adding a class when found), but this might end up being even more expensive given that the page is highly dynamic, and I'm not in control of the divs being added.
Even if there are a lot of styles, you can do this by using the asterisk as seen here, so this code:
div[style*="box-sizing: border-box;"] {
background-color: #ffffe0;
}
easily matches this HTML:
<div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, " courier="" new",="" monospace;="" font-size:="" 12px;="" color:="" rgb(51,="" 51,="" 51);="" border-top-left-radius:="" 4px;="" border-top-right-radius:="" border-bottom-right-radius:="" border-bottom-left-radius:="" background-color:="" rgb(251,="" 250,="" 248);="" border:="" 1px="" solid="" rgba(0,="" 0,="" 0.14902);="" background-position:="" initial="" initial;="" background-repeat:="" initial;-en-codeblock:true;"=""><div><font style="font-size: 14px;"><span style="line-height: normal; font-family: Monaco; font-variant-ligatures: no-common-ligatures; color: rgb(54, 86, 138);">func</span><span style="line-height: normal; font-family: Monaco; font-variant-ligatures: no-common-ligatures; color: rgb(0, 0, 0);"> doThis(thing: </span><span style="line-height: normal; font-family: Monaco; font-variant-ligatures: no-common-ligatures; color: rgb(195, 89, 0);">AnyObject</span><span style="line-height: normal; font-family: Monaco; font-variant-ligatures: no-common-ligatures; color: rgb(0, 0, 0);">) {</span><span style="color: rgb(0, 0, 0); font-family: Monaco;">}</span></font></div>
<div><font style="font-size: 14px;"><br></font></div>
<div><font style="font-size: 14px;"><span style="font-variant-caps: normal; line-height: normal; font-family: Monaco; font-variant-ligatures: no-common-ligatures; color: rgb(54, 86, 138);">func</span><span style="font-variant-caps: normal; line-height: normal; font-family: Monaco; font-variant-ligatures: no-common-ligatures; color: rgb(0, 0, 0);"> doThisThing(thing thing: </span><span style="font-variant-caps: normal; line-height: normal; font-family: Monaco; font-variant-ligatures: no-common-ligatures; color: rgb(195, 89, 0);">AnyObject</span><span style="font-variant-caps: normal; line-height: normal; font-family: Monaco; font-variant-ligatures: no-common-ligatures; color: rgb(0, 0, 0);">) {</span><span style="color: rgb(0, 0, 0); font-family: Monaco;">}</span></font></div></div>
From the W3C page on Attributes:
CSS 2.1 allows authors to specify rules that match elements which have certain attributes defined in the source document.
Attributes are the things defined from the HTML code itself, like id, class, src, href, etc.:
<a id="foo" href="bar">Foo</a>
Unless you specifically defined the style from within a style attribute, like this:
<div style="background-image: url('img/someimg.jpg');">Foo</div>
You can't do anything with CSS.
If you did do it inline, you could try this selector:
div[style="background-image: url('img/someimg.jpg');"]
{
/* ... */
}
Now that you're worried about performance, you can try using pure-JS to do this (untested):
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++)
{
var current = divs[i];
if (current.style.backgroundImage == "url('img/someimg.jpg')")
{
current.style.opacity = 0.5; // You'll need more hacks for IE...
}
}
I'd suggest manipulating CSS classes rather than individual styles in this case. For example:
div.some-img
{
background-image: url('img/someimg.jpg');
}
div.some-img-fade
{
opacity: 5;
}
......
$('div.some-img').each(function() { $(this).addClass('some-img-fade'); });
There's something called DOMSubtreeModified which has now been turned into MutationObserver. This can help you watch the dom for when new elements are added:
// identify an element to observe
var elementToObserve = document.querySelector("#targetElementId");
// create a new instance of `MutationObserver` named `observer`,
// passing it a callback function
var observer = new MutationObserver(function() {
console.log('callback that runs when observer is triggered');
});
// call `observe` on that MutationObserver instance,
// passing it the element to observe, and the options object
observer.observe(elementToObserve, {subtree: true, childList: true});
This example is copy/pasted from mdn docs: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe

Resources