I want to pass a variable to a component which should be added as a class to a div. However, Vue adds the name of the variable instead of the content.
So I pass the prop color which contains red.
What I want: <div class="red">2</div>
What I get: <div class="color">2</div>
I think this is a noob question, so sorry for that. Maybe there is a better way to do this.
Thanks for helping me out.
Here are my components:
<template>
<div class="btn btn-outline-primary cell"
:class="{color}"
:id="id">
{{ number }}
</div>
</template>
<script>
export default {
name: "TileElement",
props: ["id", "number", "color"]
}
</script>
<style scoped>
.green {
color: green;
}
.red {
color: red;
}
.yellow {
color: yellow;
}
.cell {
display: inline-block;
float: left;
margin: 0.1em;
text-align: center;
background-color: lightgray;
width: 2.7em;
height: 2.7em;
}
</style>
Parent Component:
<template>
<div class="row">
<TileElement
v-for="tile in tiles"
v-bind:key="tile.id"
v-bind:number="tile.number"
v-bind:color="tile.color"
></TileElement>
</div>
</template>
<script>
import TileElement from './TileElement.vue';
export default {
name: "TileRow",
components: {
TileElement
},
data: function () {
return {
tiles: [
{id: 1, number: 1, color: "green"},
{id: 2, number: 2, color: "red"},
{id: 3, number: 3, color: "yellos"}
]
}
}
}
</script>
If you just need to pass a class, without any conditions or other such stuff, then you can simple use array for one and any other number of classes:
<div :class="[color]"></div>
But that's not only you can do.
https://v2.vuejs.org/v2/guide/class-and-style.html
:class="color" will also work:
var vm = new Vue({
el: '#app',
data() {
return {
color: 'red'
};
}
});
.cell { width: 50px; height: 50px; }
.red { background: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.21/vue.min.js"></script>
<div id="app">
<div class="cell" :class="color"></div>
</div>
Try dynamically importing the class name
:class="{[color]: true}"
Related
Let's assume that I receive a response from the API that contains a summary of the last matches of a given team.
Example response: LLWWWWLWDWDWLW
I want it to be in my div in specific style.
L should be stylized, its background should be red (square shape) and W should have a green background. The entire statement should be minimally separated from each other.
User has the option to change the team to check its recent matches.
I'm using Vue.js
One quick solution with v-for:
const mapColors = new Map([['W', 'green'], ['L', 'red'], ['D', 'yellow']])
const app = Vue.createApp({
data() {
return {
matches: [{team: 'team 1', games: 'LLWWWWLWDWDWLW'}, {team: 'team 2', games: 'WWWWLWDLLWWWDW'}]
};
},
methods: {
setColor(c) {
return mapColors.get(c)
}
}
})
app.mount('#demo')
.green {
background: limegreen;
}
.red {
background: lightcoral;
}
.yellow {
background: gold;
}
.games {
width: 1.2em;
display: inline-block;
text-align: center;
margin: .1em;
}
.match {
margin-right: .5em;
font-weight: 600;
}
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<div v-for="(match, idx) in matches" :key="idx">
<span class="match">{{ match.team }}</span>
<span v-for="(game, i) in match.games" :key="i">
<span class="games" :class="setColor(game)">
{{ game }}
</span>
</span>
</div>
</div>
can you help me with this, i dont know how to open element of tree by vue js.i mean open definite element. if future every element of tree will be wraped by rouer-link, but right now i dont know how to trigger mechanism to open element.
tree example here
enter link description here
or here
[enter link description here][2]
let tree = {
label: 'root',
nodes: [
{
label: 'item1',
nodes: [
{
label: 'item1.1'
},
{
label: 'item1.2',
nodes: [
{
label: 'item1.2.1'
}
]
}
]
},
{
label: 'item2'
}
]
}
Vue.component('tree-menu', {
template: '#tree-menu',
props: [ 'nodes', 'label', 'depth' ],
data() {
return {
showChildren: false
}
},
computed: {
iconClasses() {
return {
'fa-plus-square-o': !this.showChildren,
'fa-minus-square-o': this.showChildren
}
},
labelClasses() {
return { 'has-children': this.nodes }
},
indent() {
return { transform: `translate(${this.depth * 50}px)` }
}
},
methods: {
toggleChildren() {
this.showChildren = !this.showChildren;
}
}
});
new Vue({
el: '#app',
data: {
tree
}
})
body {
font-family: "Open Sans", sans-serif;
font-size: 18px;
font-weight: 300;
line-height: 1em;
}
.container {
width: 300px;
margin: 0 auto;
}
.tree-menu {
.label-wrapper {
padding-bottom: 10px;
margin-bottom: 10px;
border-bottom: 1px solid #ccc;
.has-children {
cursor: pointer;
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.3/vue.js"></script>
<div class="container">
<h4>Vue.js Expandable Tree Menu<br/><small>(Recursive Components)</small></h4>
<div id="app">
<tree-menu
:nodes="tree.nodes"
:depth="0"
:label="tree.label"
></tree-menu>
</div>
</div>
<script type="text/x-template" id="tree-menu">
<div class="tree-menu">
<div class="label-wrapper" #click="toggleChildren">
<div :style="indent" :class="labelClasses">
<i v-if="nodes" class="fa" :class="iconClasses"></i>
{{ label }}
</div>
</div>
<tree-menu
v-if="showChildren"
v-for="node in nodes"
:nodes="node.nodes"
:label="node.label"
:depth="depth + 1"
>
</tree-menu>
</div>
</script>
I have a simple BootstrapVue table.
The css is defined in App.vue. Here's the code for App.vue.
<template>
<div id="app">
<!-- <img alt="Vue logo" src="./assets/logo.png"> -->
<TestTable msg="testing"/>
</div>
</template>
<script>
import TestTable from './components/TestTable.vue'
export default {
name: 'App',
components: {
TestTable
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Here's the code for TestTable.vue.
<template>
<div>
<b-table striped hover :items="items"></b-table>
</div>
</template>
<script>
export default {
data() {
return {
items: [
{ age: 40, first_name: 'Dickerson', last_name: 'Macdonald' },
{ age: 21, first_name: 'Larsen', last_name: 'Shaw' },
{ age: 89, first_name: 'Geneva', last_name: 'Wilson' },
{ age: 38, first_name: 'Jami', last_name: 'Carney' }
]
}
}
}
</script>
The margin-top: 60px is defined in App.vue. I want to modify TableTest.vue such that it overrides the margin top in the CSS in App.vue. I want margin-top: 0px for TableTest.vue.
I am using Vue v2.6 and Bootstrap-vue.
I want to modify TableTest.vue such that it overrides the margin top in the CSS in App.vue
I earlier commented on your question that you applied margin-top: 60px in your parent component and child component is having its own box model.
Adding a code snippet to show how your component structured:
Vue.component('item', {
template:'#list-template',
props:['item'],
});
var vm = new Vue({
el:"#app",
computed: {
limitedItems() {
return ['item1'];
}
}
});
#app {
border: 2px solid black;
margin-top: 60px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<item v-for="item in limitedItems" :item="item" style="border: 2px solid green"></item>
</div>
<template id="list-template">
<p>{{ item }}</p>
</template>
you can try margin-top: -60px;
Simply use
<style>
#app {
margin-top: 0;
}
</style>
In Your TestTable.vue file and it will overwrite the previous css rule given that both <style> tags are not scoped.
How apply multiple event on single button in Vue.js?
I have a single button component
When a button is clicked in parent, several events are
must be applied
tytle should change from "Buy" to "In a basket"
icon shold apply done
style should change to button_1
my button component
<template>
<div class="btn"
#click="click"
:class="className">
<i class="material-icons"> {{ icon }} </i>
<span> {{ title }} </span>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: 'Buy'
},
disabled: {
type: Boolean,
default: false
},
button_1: {
type: Boolean,
default: false
},
icon: {
type: String,
default: ''
},
},
data() {
return {}
},
computed: {
className() {
return {
'btn__disabled': this.disabled,
'btn__button_1': this.button_1,
}
}
},
methods: {
click() {
this.$emit('click')
}
},
name: "BaseButton"
}
</script>
<style lang="scss" scoped>
.material-icons {
font-size: 16px;
}
.btn {
position: relative;
font-family: 'Merriweather', sans-serif;
color: var(--color-primary-light);
left: 45%;
bottom: 18%;
height: 48px;
width: 122px;
cursor: pointer;
background-color: var(--color-grey-light-4);
display: flex;
justify-content: space-evenly;
align-items: center;
&:hover,
&:active {
background-color: var(--color-grey-light-2);
border: none;
}
&__button_1 {
color: var(--color-primary-light);
background-color: var(--color-grey-light-3);
border: none;
}
&__disabled {
background-color: var(--color-grey-light-1);
border: none;
pointer-events: none;
}
}
</style>
my parent component
<template>
<base-button #click="clickBtn"></base-button>
</template>
<script>
import BaseButton from '../components/ui/BaseButton'
export default {
name: "GalleryOverview",
components: {BaseButton},
methods: {
clickBtn() {
console.log('BTN clicked')
}
}
}
}
</script>
How can I apply multiple event on single button?
You are almost done, as you are sending emit to parent component, you can use that to change.
So, first you will need to pass the required props to the child component, as:
<template>
<base-button #click="clickBtn" :title="title" :icon="icon" :button_1="button_1"></base-button>
</template>
<script>
import BaseButton from '../components/ui/BaseButton'
export default {
name: "GalleryOverview",
data() {
return {
title: 'My Title',
icon: '',
button_1: false
}
}
methods: {
// This is where you can change.
clickBtn() {
this.icon = 'change icon';
this.title = 'change title';
this.button_1 = true;
}
}
}
</script>
Now when you click the button it will change the title, icon and button_1.
I have a regular block I want to do so that when you click on an empty space, this block closes here is a link to codesandbox
<template>
<div>
<div class="wrapper"></div>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
},
};
</script>
<style scoped>
.wrapper {
width: 300px;
height: 150px;
background: green;
margin: auto;
}
</style>
Using an event bus to communicate between window click event listener and the component should be one way to go.
You can work on top of this codesandbox
You could do something like this. Using a backdrop and detects when it got clicked. Is this what you want?
App.vue
<template>
<div id="app" class="backdrop" #click.self="showBox = !showBox">
<img alt="Vue logo" src="./assets/logo.png" width="25%" />
<HelloWorld :showBox="showBox" msg="Hello Vue in CodeSandbox!" />
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
name: "App",
components: {
HelloWorld,
},
data: function () {
return {
showBox: true,
};
},
};
</script>
<style>
#app {
text-align: center;
margin-top: 40px;
}
.backdrop {
z-index: 0;
position: fixed;
width: 100%;
height: 100%;
}
</style>
HelloWorld.vue
<template>
<div>
<div v-if="showBox" class="wrapper"></div>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
showBox: Boolean,
},
};
</script>
<style scoped>
.wrapper {
width: 300px;
height: 150px;
background: green;
margin: auto;
}
</style>