Define a variable used in js and css - vue.js

For example, I want to define a global color a = '#FFF', and reference it in js and css to make sure that there is only one color named a in the project. then when the value of a changed, a in js and css also changed. is that possible in vue?

Hmm... I was thinking about watchers watch in combination with CSS variables.
Maybe something like this?
Whenever a changes, the CSS variable --a changes aswell.
You can actually type in any color format you want. Hex, rgb, rgba...
let v = new Vue({
el: "#app",
data: {
a: "red"
},
watch: {
a(val){
document.documentElement.style.setProperty("--a", val);
}
}
})
:root {
--a: red;
}
#app {
height: 100px;
width:100%;
background: var(--a);
transition: background 500ms;
}
p {
background: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<p>Color: {{a}}</p>
<input v-model="a">
</div>

Related

Super small Vue button

I'm learning Vue, and even with the simplest examples there is something wrong. For example, buttons. I have a defined component, myButton, responds to clicks, but it doesn't look like it should, is super small and dont have any label. What am I doing wrong?
Part of index.js:
Vue.component('mybutton', {
props: {
buttonLabel: String,
},
template: '<button #click="onClick()" class="btn">{{ buttonLabel }}</button>',
methods: {
onClick(){
console.log('Click');
}
},
})
Part of index.html:
<div id="app">
<mybutton text="From Vue"></mybutton>
<button class="btn">Test</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="index.js"></script>
And CSS:
.btn {
display: inline-block;
background: #000;
color: #fff;
border: none;
padding: 10px,20px;
border-radius: 5px;
text-decoration: none;
font-size: 15px;
font-family: inherit;
}
Your prop is called buttonLabel, while you pass a property called text inside your index.html. Therefore, the button doesn't get any text and then it's rendered without any inner content (and therefore slim, since you didn't give it fixed width and height).
You need to change the part of index.html and replace text with button-label (Vue automatically maps buttonLabel to it, and it is the better option. Using buttonLabel might not work in this case, since you are not using single file components.
Call it like
<mybutton mylabel="hI"></mybutton>
Vue.component('mybutton', {
props: ['mylabel'],
template: '<button>{{ mylabel }}</button>'
})
https://codepen.io/flakerimi/pen/wvgGqVb
https://v2.vuejs.org/v2/guide/components.html

Initialize components in for loop from array data

Trying initialize custom elements (3 buttons) in for loop but first element missing text.
LeftMenu.vue
<template>
<div id="left-menu">
<MenuButton v-for="mytext in buttonList" v-bind:key="mytext" v-bind:mytext="mytext"/>
</div>
</template>
<script>
import MenuButton from './components/MenuButton.vue'
export default {
name: 'left-menu',
components: {
MenuButton
},
computed: {
buttonList() {
return ["Test1", "Test2", "Test3"];
}
}
}
</script>
<style>
#left-menu {
width: 200px;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
</style>
MenuButton.vue
<template>
<div id="left-menu-button">
{{mytext}}
</div>
</template>
<script>
export default {
name: 'left-menu-button',
props: {
mytext: String
}
}
</script>
<style>
#left-menu-button {
width: 180px;
height: 50px;
margin-left: 10px;
margin-bottom: 5px;
}
</style>
main.js
import Vue from 'vue'
import LeftMenu from './LeftMenu.vue'
import MenuButton from './components/MenuButton.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(LeftMenu)
}).$mount('#left-menu')
new Vue({
render: h => h(MenuButton)
}).$mount('#left-menu-button');
I am new to vue and still trying to figure out how all part are connected and working together. It just seems very strange that I got 3 buttons but only last two of them have text and first one does not...may be someone can point me to my mistake.
You've assigned an id of left-menu-button to each of your buttons. You've then told Vue to mount something into that id. The first element (i.e. first button) with that id will be treated as the mounting element, which blows away the text.
You should remove the ids from all elements within your templates. The only id should be the one within your HTML file. For styling purposes use classes instead of ids. Then create a single Vue instance (just one call to new Vue, not two) targeting the id of the element inside your HTML file.
It is possible to create multiple Vue instance directly using new Vue but that is rarely necessary. To do that you would need to have multiple target elements within your HTML file.

How to change Vuetify Text fields text input color

How to change Vuetify v-text-fields input text color. I tried many ways but none of them is worked.
enter image description here
I tried to change the "Hello" text to red. It is not working.
if you want to change color to white just add props dark to v-text-input
There are few ways to do this.
One convenient way is to set a class on the v-text-field, then using specificity set the color of the input.
Note that you need to use the !important flag when not editing the Vuetify theme directly.
In the template,
<v-text-field class="text-green"></v-text-field>
In the CSS (e.g. style tag),
.text-green input {
color: green !important;
}
Live Snippet:
new Vue({
el: '#app',
data: () => ({
name: 'John'
})
})
.text-green input{
color: green !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.js"></script>
<div id="app">
<v-app>
<v-text-field class="text-green" v-model="name"></v-text-field>
</v-app>
</div>
What worked for me is exporting the themes colors as css variables (custom properties). Code below
// src/plugins/vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
export default new Vuetify({
theme: {
options: {
customProperties: true,
},
},
})
and then in the scss using the following code:
.v-text-field {
input {
color: var(--v-primary-base);
}
}
This works:
<v-text-field class="text-input-blue"/>
In combination with CSS:
.text-input-blue .v-text-field__slot input {
color: #00f !important;
}
One of the downsides of Javascript frameworks is that the CSS is often hard to customize.
In case you are using v-custom the below scss override will work for you:
<div class="input-text-wrapper">
<v-text-field class="input-text"/>
</div>
Style:
<style scoped lang="scss">
.input-text {
::v-deep {
.v-text-field {
input {
color: blue;
}
}
}
}
</style>
You need to create a file related to CSS styles in the Styles section and name it Override. In that file, you can make any desired changes you need. Put the following code in that file, you can change the color of the border:
.v-text-field {
input {
color: rgba(169, 169, 169, 0.33);
}
}

Combine several CSS classes into one

In a Vue project I want to combine a few css classes that I use on two elements in order to declutter my html. I was told I can do something like this with the cli, however i have no idea how.
.common-class {
#apply .class1 .class2 ...;
}
You can use LESS in you Vue files and use the extend pseudo-class to merge the styles
<style lang="less">
.class1{
}
.class2{
}
.common-class {
&:extend(.class1);
&:extend(.class2);
}
</style>
You can always create a computed property that returns those two classes combined:
new Vue({
el: "#app",
computed: {
combineStyles() {
return 'foo bar'
}
}
})
.foo {
color: red;
}
.bar {
font-size: 2rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<p :class="combineStyles">foo bar</p>
</div>
No CSS preprocessor needed. However if you want to use some CSS preprocessor then follow the docs.

Why should I use v-bind for style

I just started learning Vue and I was wondering, why should I use v-bind for style and not write it regularly in html/css file
Let's say you need to create a progress bar that is not static. You will then need to update the style attribute width for-example.
To accomplish this, we need to programatically edit the width of the element. We 'cannot' to this in plain css, therefore the :style attribute comes in handy.
Let's create an example:
Codepen
HTML
<div id="vue">
<div class="progress-bar">
<div :style="{'width':progress + '%'}" class="progress" />
</div>
<button #click="fakeProgress">Init fake progress</button>
</div>
Css;
.progress-bar, .progress {
border-radius: 20px;
height: 20px;
}
.progress-bar {
width: 250px;
background-color: gray;
}
.progress {
background-color: blue;
width: 0;
transition: all 1s ease;
}
Javascript
new Vue({
el: '#vue',
data: {
progress: 0
},
methods: {
fakeProgress() {
let progress = setInterval(() => {
if(this.progress == 100) {
clearInterval(progress)
} else {
this.progress += 1;
}
}, 50)
}
}
})
As you see here, we bind the progress data attribute to the width value on the fake progress bar. This is just a simple example, but I hope this makes you see its potential. (You could achieve this same effect using the <progress> tag, but that would ruin the explanation.
EDIT; Also want to point out that you are supposed to write all your css as normal as you point out in your question. However, :style is used in cases that you cannot normally use css for. Like the example above where we need css to change from a variable.