How to provide dynamic styling to riotjs tag - riot.js

I want to create a riotjs tag to whom some style or css class can be added directly in HTML page. And I also can set some style attributes dynamically from tag script;
For Example;
<my-tag class="some class" attr1="" attr2="" />
<my-tag>
<script>
if(opts.attr1) //set some style to my-tag
</script>
</my-tag>
I can achieve it by creating a HTML tag string with dynamic properties and insert as HTML to root. But I don't want to add additional child tag just for styling.

What about something like this. You pass some options to the tag, and then change the style classes dynamically. Check the example http://plnkr.co/edit/ZuPMFFBIuDPSeawsEkPX?p=preview
<my-tag color="green"></my-tag>
<my-tag color="red"></my-tag>
<my-tag>
<h1 class="{opts.color}">{ message }</h1>
<script>
this.message = 'hello there'
</script>
<style>
.red {
color: red;
}
.green {
color: green;
}
</style>
</my-tag>

You can optionally include classes onto your elements by using the syntax below.
<my-tag>
<div class="some-class another-class { my-class: attr1 }"></div>
<script>
this.attr1 = this.opts.attr1;
</script>
</my-tag>
And then in the HTML where you use the tag.
<my-tag attr1="whatever"></my-tag>
So if this.opts.attr1 is set, this will add the class my-class to the <div> element.

Related

How do I add a class to a slotted element?

In my my-dropdown component in Stencil, I have this:
<slot name="filter" />
In my HTML, I have this:
<my-dropdown label="dropdown" size="m" filter="true">
<select slot="filter" class="inf__dropdown-select">
<option>One</option>
<option>Two</option>
<option>Three</option>
</select>
</my-dropdown>
The class inf__dropdown-select is defined in the stylesheet of the component, and it used to be applied to the select element inside the component.tsx, but since I need to slot it now, I replaced the select element with a single <slot name="filter" /> slot, but now I don't know how do I apply the class? If I add the class to the slot inside the component, it's not being
applied. I thought adding it to the element that you are slotting would work, but it doesn't. How do I make sure the class is applied to the slotted select element?
You have implemented the inf__dropdown-select style class inside shadow DOM (the style for my-dropdown), but the class is being set on the select element which is in light DOM, so the style can never be applied to the element.
To style elements inside a slot of a web component from inside the component, you use the ::slotted() pseudo-element selector inside the component's stylesheet.
For example - the stylesheet for my-dropdown:
:host {
::slotted(select) {
...
}
...
}
You can also use other selectors inside the ::slotted() function such as ::slotted(.inf__dropdown-select), ::slotted(select.inf__dropdown-select) or ::slotted([slot="filter"]) depending on how specific you need to be according to the design of your component.
Important to note: Slotted content is reflected, NOT moved!
<slot> content is styled by CSS in the container
in the SO snippet below global CSS myClass
Below <style> can be inside the component (in lightDOM !!) or outside the component.
and inside the component,
the "skin" (only the first! element select) can be styled with ::slotted
For really deep dive, see: ::slotted CSS selector for nested children in shadowDOM slot
customElements.define("my-dropdown",class extends HTMLElement{
constructor(){
super()
.attachShadow({mode:"open"})
.innerHTML = `
<style>
::slotted(select) {
margin:3em;
}
div {
background:pink;
}
</style>
<div>
<slot name="filter">NO slot named: filter</slot>
</div>
`
}
})
<style>
select {
font:20px arial;
}
</style>
<my-dropdown label="dropdown" size="m" filter="true">
<style>
.myClass {
border: 5px dashed green;
}
</style>
<select slot="filter" class="myClass">
<option>One</option>
<option>Two</option>
<option>Three</option>
</select>
</my-dropdown>

how to render loaded html text with classname inside vuejs

I try to render some html text loaded in a json file.
the textstring holds an class="" css style
"example": word 1<br><span class=\"main-color\">word 2</span> word 3"
the vuejs part looks like this:
<p v-html="example"> </p>
the scoped css:
.main-color {
color: #ff00ff;
}
the html code looks as expected in debugger, but the text was not rendered! why?
You are missing a " at the start of the variable
This works
<script setup>
import { ref } from 'vue'
const example = ref("word 1<br><span class=\"main-color\">word 2</span> word 3")
</script>
<template>
<p v-html="example"> </p>
</template>
<style>
.main-color {
color: #ff00ff;
}
</style>

Unable to disable click event of a span

I am trying to disable a span. My attempt is as below.
<span #click="confirm" disabled="true">click here</span>
But it will not disabled. Where I was wrong and how can I fix this?
You can use css class to disable the span. If you want to make it dynamic simply use Class Binding eg :class="your_variable"
For Class and Style Bindings you can use this reference
vuejs.org/v2/guide/class-and-style.html#Object-Syntax
Class and Style Bindings
const app = new Vue({
methods: {
confirm(){
alert('hello');
}
}
})
app.$mount("#app")
.disable-click{
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Enable click</h2>
<span v-on:click="confirm()">Click</span>
<h2>Disable click</h2>
<span v-on:click="confirm()" class="disable-click">Disable Click</span>
</div>

Vuetife overwrite components scoped styles

I create an application using Vuetify. One component should display a schedule that is created using dxhtmlScheduler. But global Vuetify styles overwrite local dxhtmlScheduler styles and therefore the schedule is not displayed correctly. How to make dxhtmlScheduler styles a particular component had a higher priority than the styles Vuetify?
<template >
<div id="scheduler_here" class="dhx_cal_container" style='width:100%; height:100%;'>
<div class="dhx_cal_navline">
<div class="dhx_cal_prev_button"> </div>
<div class="dhx_cal_next_button"> </div>
<div class="dhx_cal_today_button"></div>
<div class="dhx_cal_date"></div>
<div class="dhx_cal_tab" name="day_tab"></div>
<div class="dhx_cal_tab" name="week_tab"></div>
<div class="dhx_cal_tab" name="month_tab"></div>
</div>
<div class="dhx_cal_header"></div>
<div class="dhx_cal_data"></div>
</template>
<script>
import 'dhtmlx-scheduler'
export default {
name: "Scheduler",
mounted() {
scheduler.init("scheduler_here");
}
}
</script>
<style scoped>
#import "../../node_modules/dhtmlx-scheduler/codebase/dhtmlxscheduler_material.css";
</style>
The markup generated by dhtmlxScheduler lives outside vue component scope, so I don't think scoped styles would work with it.
Try removing scoped attribute from your style declaration
<style>
#import "../../node_modules/dhtmlx-scheduler/codebase/dhtmlxscheduler_material.css";
</style>
Here is a related github issue https://github.com/vuejs/vue-loader/issues/559
Explanation:
Vue adds a special data-v-xxxxxxx attribute to html elements created by your component.
Vue css-loader in its turn modifies selectors in scoped css in order to explicitly match elements inside your component and nothing outside.
So .dhx_cal_event_line { background: blue; } in dhtmlscheduler.css becomes .dhx_cal_event_line[data-v-xxxxxxx] { backtround: blue; } when loaded to the page. Such style is supposed to only affect a component with the matching value of data-v attribute.
The problem is, DOM elements of dhtmlxscheduler are created by the library code outside the vue component knowledge, they don't have vue data-v-xxxxxxx attributes, thus scoped css selectors no longer matches them.
Thus, you'll have to load scheduler css as a global style.
There is maybe a better solution, but unfortunately, I don't know it.

How to customize style of VueJS 2.0 using stylus?

I am using v-text-field without vuetify.min.css just use stylus.
Here is my code.
<template>
<v-text-field type="text" name="password"></v-text-field>
</template>
<style lang="stylus" scoped="scoped">
.input-group_details {
XXX
}
</style>
I am trying to hide some divs in v-text-field.
But I got nothing changed.
That is not possible using scoped styles (That's the point of scoping)
What you could do is either passing down a prop which indicates that the divs are hidden or handle it globally.
passing down a prop:
const textField = {
template: `
<div>
<div>Always shown</div>
<div v-if="shown">
Conditionally shown
</div>
</div>
`,
props: { shown: Boolean }
};
Vue.component('v-text-field', textField);
new Vue({}).$mount('#app');
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">
<b>shown = true:</b>
<v-text-field :shown="true"></v-text-field>
<br>
<b>shown = false:</b>
<v-text-field :shown="false"></v-text-field>
</div>
As per https://vue-loader.vuejs.org/en/features/scoped-css.html#notes
you need to use >>> operator for CSS
So this should work:
<style scoped>
>>> .input-group_details {
//your css
}
</style>
You can use lang="stylus" and it will work, but your IDE might throw some syntax errors.
I'm not sure what's correct stylus syntax for that.
Note that it was implemented in v12.2.0