How to set an element's class in svelte - css

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;
}
))

Related

Apply CSS styles on html tags after create them dynamically (inside .ts file)

I'm trying to add DIV after the project run (add it dynamically) but the problem is it didn't take the CSS style that I've set to it.
import { Component, OnInit, AfterViewInit } from '#angular/core';
#Component({
selector: 'app-chat2',
templateUrl: './chat2.component.html',
styleUrls: ['./chat2.component.css']
})
export class Chat2Component implements OnInit,AfterViewInit {
messages = [];
totalOnline = 0;
user = 1;
constructor() { }
ngOnInit() {
}
ngAfterViewInit(){
const divMessages: HTMLDivElement = document.querySelector(".msg_history");
let m = document.createElement("div");
m.innerHTML =
`<div class="incoming_msg">
<div class="incoming_msg_img" > <img src="https://ptetutorials.com/images/user-profile.png" alt="sunil"> </div>
<div class="received_msg">
<div class="received_withd_msg">
<p>Abdulaziz Burghal , Hello from Chat</p>
<span class="time_date"> 4:53 AM | June 9</span></div>
</div>
</div>`;
divMessages.appendChild(m);
divMessages.scrollTop = divMessages.scrollHeight;
}
}
Note: div that I've created it inside HTML file took the CSS style without any problem .
So, how could apply the CSS style on div's that I'll create them by code
Update:
Added CSS
.incoming_msg_img {
display: inline-block;
width: 6%;
}
.received_msg {
display: inline-block;
padding: 0 0 0 10px;
vertical-align: top;
width: 92%;
}
.received_withd_msg p {
background: #ebebeb none repeat scroll 0 0;
border-radius: 3px;
color: #646464;
font-size: 14px;
margin: 0;
padding: 5px 10px 5px 12px;
width: 100%;
}
Update 2
when I add the CSS styles as inline style it's work but the problem is the Div that contains the image it's CSS doesn't work!
You can apply the css in a few ways.
Via css
It's not clear why the css style isn't working, if you post it we can probably help more. Are you targeting the div or class of your dynamicly created html in the css?
Dynamically in JS
You'll have to get the element in JavaScript, either by using the m element you have or attaching a unique id to one of your elements.
const el = document.getElementById("${unique id})
Then you can set the style
el.style.cssText = "${your style text}"
If you use angular way to fill your list the CSS will work:
HTML
<div class="inbox_chat">
<div class="chat_list active_chat" *ngFor="let userData of listOfUsers">
<div class="chat_people">
<div class="chat_ib">
<h5>{{userData.userName}} <span class="chat_date">{{userData.creationDate}}</span></h5>
<p>{{userData.messageText}}</p>
</div>
</div>
</div>
</div>
TypeScript part:
listOfUsers: Array<InboxChatBoxDto> = [];// define it gloably
fillInboxChat(){
this._messageService
.inboxChat()
.pipe(
finalize(() => {
//alert("finished")
//finishedCallback();
})
)
.subscribe((result) => {
this.listOfUsers=result;
// });
});
}
If you use javascript to build your HTML you need to use an inline CSS property:
HTML part
<div class="inbox_chat"></div>
TypeScript part (use javascript code within it):
fillInboxChat(){
this._messageService
.inboxChat()
.pipe(
finalize(() => {
//alert("finished")
//finishedCallback();
})
)
.subscribe((result) => {
const divMessages: HTMLDivElement = document.querySelector(".inbox_chat");
result.forEach((item,index)=>{
let m = document.createElement("div");
m.className="chat_list"
m.style.cssText=` border-bottom: 1px solid #c4c4c4;
margin: 0;
padding: 18px 16px 10px;`
m.innerHTML = `<div class="chat_people" style='overflow:hidden; clear:both;' >
<div class="chat_ib" (click)="fillMessageHistory(`+item.userId+`)">
<h5 style='font-size:15px; color:#464646; margin:0 0 8px 0;'>` + item.userName +`<span class="chat_date" style='font-size:13px; float:right;'>`+ moment(item.creationTime ).format('YYYY/MM/ddd') +`</span></h5>
<p style='font-size:14px; color:#989898; margin:auto'>`+ item.messageText+`</p>
</div>
</div>`;
divMessages.appendChild(m);
});
});
}

How to toggle div background color based on class name and contenteditable value

I want to change div background color based on class name 'cls-editable', which is used by javascript to find the element and then set editable attribute to be 'true' or 'false.
When editable, background is yellow. Otherwise, it's white.
HTML
<div class='cls-editable'>
Hello
</div>
CSS:
.cls-editable, [contenteditable="true"] {
background-color: yellow;
}
.cls-editable, [contenteditable="false"] {
background-color: white;
}
Javascript:
if (this.checkStatus) {
$('.dirs_row').children('.cls-editable').each(function () {
$(this).attr('contenteditable', 'true');
});
} else {
$('.dirs_row').children('.cls-editable').each(function () {
$(this).attr('contenteditable', 'false');
});
}
But, it does not work. What's wrong with css?
Try this
CSS
.cls-editable[contenteditable="true"] {
background-color: yellow;
}
.cls-editable[contenteditable="false"] {
background-color: white;
}
OUTPUT
You got it almost correct! Here is the correct solution:
.cls-editable[contenteditable="true"] {
background-color: yellow;
}
.cls-editable[contenteditable="false"] {
background-color: white;
}
<div class='cls-editable' contentEditable="true">
Hello
</div>
<div class='cls-editable' contentEditable="false">
Hello
</div>

How to pass parameter from Angular to CSS in HTML table

I have HTML table in Angular web app.
Get the data from the database via service and display it as text.
One of the columns is Status, so I need to present that variable not as text,
but as a circle of certain color, so if that cell value is "green",
it should show as green circle.
Here is what I have.
CSS (part of Component Styles):
:host ::ng-deep td.circle {
text-align: center;
font-size: 0;
background-color: RED; <--- need to pass param here
}
I define that column as:
.circle {
border-radius: 50%;
height: 24px;
width: 24px;
}
HTML:
<app-table [attrs]="serviceapi" [monthSelected]="monthSelected" ></app-table>
TS for that table:
In constructor:
this.data = {
headers: [],
rows: []
};
ngOnInit() {
this.tableMetricsService.getTableMetrics(
JSON.parse(this.attrs).api,
this.monthSelected
).subscribe(response => {
this.data = response;
}
);
}
Any idea how to "translate" cell value into the CSS background-color ?
TIA,
Oleg.
You could put a data attribute on the html and write a corresponding selector:
[data-status="green"] {
background: green;
}
[data-status="red"] {
background: red;
}
<div data-status="green">Green</div>
<div data-status="red">Red</div>
But I don't see any advantage to this approach over using a regular css class:
.green {
background: green;
}
.red {
background: red;
}
<div class="green">Green</div>
<div class="red">Red</div>
Here is what worked for me:
<div *ngIf="cell.styleClass == 'circle'" [ngStyle]="{'background-color': cell.value}" [ngClass]="cell.styleClass">
</div>

How to dynamically apply CSS in vue.js?

This is my situation:
I have a web app that allow users to change the UI size. (i.e. small, medium or large button)
Users can change how it looks like dynamically during runtime. All text and form input boxes will be resized.
My project is in Vue.js.
What is the best way to solve this? Loading different css when user click?
Load different CSS while user click the button similar to this . Codepen : https://codepen.io/anon/pen/NJEoVM
HTML
<div id="app" :class="size">
<div class="text">Text</div>
<input class="ipt"/><br/><br/>
<button class="btn" #click="change('small')">Small</button>
<button class="btn" #click="change('medium')">Medium</button>
<button class="btn" #click="change('large')">Large</button>
</div>
CSS
.small .ipt{
width: 100px;
height:30px;
}
.small .text{
font-size: 18px;
}
.medium .ipt{
width: 300px;
height:50px;
}
.medium .text{
font-size: 32px;
}
.large .ipt{
width: 600px;
height:100px;
}
.large .text{
font-size: 64px;
}
Javascript
new Vue({
el: '#app',
data:()=>({
size:'small'
}),
methods:{
change(val){
this.size = val
}
}
});
Actually, you can make use of Custom Properties aka CSS variables.
Firstly, define the button CSS styles
/* button.css */
#buttonRef {
--fontSize: 16px;
font-size: var(--fontSize)
}
The overall flow would be something like the following one e.g
methods: {
changeButtonSize: function(size, event) {
event.preventDefault();
/* size might be either of 's', 'm', 'l' */
/* let the button ref is stored in refs */
const buttonRef = this.$refs[“buttonRef”];
let fontSize = 16;
switch(size) {
case 's':
fontSize = 12;
case 'm':
fontSize = 18;
case 'l':
fontSize = 22;
}
/* dynamically change the value for custom property */
buttonRef.style.setProperty("--fontSize", fontSize);
}
}
you can set up 3 classes:
.small {font-size:12px}
.medium {font-size:18px}
.large {font-size:24px}
Then add or remove them to your main parent div onClick.
If you have discreetly set the font-size on the elements, you'll have to target those elements as such:
.small .description { font-size:12px }
.small .title{ font-size:16px }

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>

Resources