bootstrap-vue - show button based on boolean - javascript

When I click Launch centered modal, I expect the modal hide the buttons x,cancel and ok because showButton is false.
After I click the show button, the button of the modal should be shown because now showButton is true.
How should I do it?
App.vue
<template>
<div id="app">
<b-button v-b-modal.modal-center>Launch centered modal</b-button>
<b-modal id="modal-center" centered title="BootstrapVue">
<p class="my-4">Vertically centered modal!</p>
<button #click="setShowButton">Show Button</button>
</b-modal>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
showButton: false,
};
},
methods: {
setShowButton() {
this.showButton = true;
},
},
};
</script>
<style>
#app {
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Codesandbox
https://codesandbox.io/s/flamboyant-herschel-62wpt?file=/src/App.vue:0-587

You can use the hide-header-close and hide-footer properties. Documented here. Modal docs
<template>
<div id="app">
<b-button v-b-modal.modal-center>Launch centered modal</b-button>
<b-modal
id="modal-center"
centered
title="BootstrapVue"
:hide-header-close="!this.showButton"
:hide-footer="!this.showButton"
>
<p class="my-4">Vertically centered modal!</p>
<button #click="setShowButton">Show Button</button>
</b-modal>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
showButton: false,
};
},
methods: {
setShowButton() {
this.showButton = true;
},
},
};
</script>
<style>
#app {
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Example
https://codesandbox.io/s/hungry-architecture-zrcqj?file=/src/App.vue

Related

How can I duplicate my component in vue.js?

<template>
<!--This is my main file -->
<div id="inputs">
<h1>언어 관리</h1>
<v-btn color="primary" elevation="10" large #click="duplicateEl"
>Add row</v-btn
>
<Contents />
</div>
</template>
<script>
import Contents from "./Contents.vue";
export default {
name: "LanguageMainMenu",
components: { Contents },
methods: {
duplicateEl() {
alert("You can duplicate buttons");
},
},
};
</script>
<style>
h1 {
text-align: center;
font-size: 38px;
padding-top: 20px;
margin: auto;
}
</style>
The best apprach is to use the component inside v-for.
Increment the index when the button is clicked.
Dont forget to use key inside the v-for
Working Fiddle
var example1 = new Vue({
el: '#app',
name: "LanguageMainMenu",
components: {
Contents: {
template: `<div>Contents Component</div>`,
}
},
data() {
return {
totalCount: 1,
}
},
methods: {
duplicateEl() {
this.totalCount++;
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.js"></script>
<div id="app">
<!--This is my main file -->
<div id="inputs">
<h1>언어 관리</h1>
<button #click="duplicateEl">Add row</button>
<Contents v-for="count in totalCount" :key="`component-${count}`" />
</div>
</div>
You can add a property in data object and use v-for for render buttons.
Let method duplicateEl to change the property value.
<v-btn v-for="item in btnNumber" ....>
duplicateEl(){
this.btnNumber++
}

How to pass a style property to a child component as a computed property in Vue.js?

I have the following problem:
I have too much logic in my inline style and would to place it inside a computed property. I know, that this is the way, that I should go, but do not know, how to achieve it.
Below I a simple example that I made for better understanding. In it, on button press, the child's component background-color is changing.
My code can be found here: Codesandbox
My parent component:
<template> <div id="app">
<MyChild :colorChange="active ? 'blue' : 'grey'" />
<p>Parent:</p>
<button #click="active = !active">Click Me!</button> </div> </template>
<script> import MyChild from "./components/MyChild";
export default { name: "App", components: {
MyChild, }, data() {
return {
active: false,
}; }, }; </script>
and my child component:
<template> <div class="hello">
<p>Hello from the child component</p>
<div class="myDiv" :style="{ background: colorChange }">
here is my color, that I change
</div> </div> </template>
<script> export default { name: "HelloWorld", props: {
colorChange: {
type: String,
default: "green",
}, }, }; </script>
<!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> .myDiv { color: white; padding: 1rem 0; } </style>
I also have a second question. Let's say, that I have more than one child component and also would like to change to colors on button click, but those colors differ. How can I achieve it without repeating myself (within the computed properties?)
Code example for my parent component:
<MyChild :colorChange="active ? 'blue' : 'grey'" />
<MyChild :colorChange="active ? 'grey' : 'blue'" />
<MyChild :colorChange="active ? 'blue' : 'red'" />
<MyChild :colorChange="active ? 'yellow' : 'blue'" />
Thanks in advance!
Maybe You can bind class and use different css classes:
Vue.component('MyChild',{
template: `
<div class="hello">
<p>Hello from the child component</p>
<div class="myDiv" :class="collorCurrent">
here is my color, that I change
</div>
</div>
`,
props: {
colorChange: {
type: String,
default: "green",
},
colorDef: {
type: String,
default: "green",
},
isActive: {
type: Boolean,
default: false,
},
},
computed: {
collorCurrent() {
return this.isActive ? this.colorChange : this.colorDef
}
}
})
new Vue({
el: "#demo",
data() {
return {
active: false,
}
},
})
.myDiv { color: white; padding: 1rem; }
.blue {
background: blue;
font-size: 22px;
}
.red {
background: red;
font-variant: small-caps;
}
.yellow {
background: yellow;
color: black;
}
.grey {
background: grey;
text-decoration: underline;
}
.green {
background: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<p>Parent:</p>
<button #click="active = !active">Click Me!</button>
<my-child :is-active="active" :color-def="'grey'" :color-change="'blue'"></my-child>
<my-child :is-active="active" :color-def="'blue'" :color-change="'grey'"></my-child>
<my-child :is-active="active" :color-def="'red'" :color-change="'blue'"></my-child>
<my-child :is-active="active" :color-def="'blue'" :color-change="'yellow'"></my-child>
</div>

VUE: How to use prop with CSS modules?

row.vue
<script>
export default {
name: "Row",
data() {
return {
app: [
"row",
"row-test",
"flex-center"
]
}
},
template: `
<div :class="$module[app]"><slot></slot></div>
`
}
</script>
row.scss
.row {
color: red;
}
.row-test {
color: green;
}
.flex-center {
align-items: center;
justify-content: center;
}
App.vue
<template>
<div id="app">
<row app="row-test flex-center">my row</row>
<router-view />
</div>
</template>
vue.config.js
css: {
requireModuleExtension: true,
loaderOptions: {
css: {
modules: {
localIdentName: 'hex-[HASH:HEX:3]'
}
}
},
modules: true
}
I want to declare my attributes using the app attribute, where they will be written similarly to an ordinary class. Then I want there to be an Array in row.vue, which will add only the values that I define in and convert them to CSS using CSS modules (class is randomly generated)
I'm getting this
<div app="row-test flex-center">my row</div>
Expected result
<div class="hex-g3D hex-f41">my row</div>
If you're passing app as prop to Row component, define a computed property to return the modules with the different classes:
<script>
export default {
name: "Row",
props:['app'],
computed:{
modules(){
return this.app.length? this.app.map(_class=>{
return this.$module[_class];
}):[];
}
},
template: `
<div :class="modules"><slot></slot></div>
`
}
</script>
and pass it like :
<template>
<div id="app">
<row :app="['row-test', 'flex-center']">my row</row>
<router-view />
</div>
</template>

How to pass v-model value between components

I have a parent form component and a child. How do I pass data from one to another using v-model? They are in different files. I'm using the components of the Quasar Framework.
Parent Component
<template>
<q-input
label="Nome *"
lazy-rules
:rules="[val => (val && val.length > 0) || 'Por favor, digite o seu nome']"
v-model="nome"
/>
</template>
<script>
export default {
name: "Nome",
data() {
return {
nome: "Max"
};
}
};
</script>
Child Component
<template>
<div class="q-pa-md" style="max-width: 500px">
<q-form #reset="onReset" class="q-gutter-md">
<Nome> </Nome>
<div>
<q-btn label="Reset" type="reset" color="red" flat class="q-ml-sm" />
</div>
</q-form>
</div>
</template>
<script>
import Nome from "components/Nome.vue";
export default {
components: { Nome },
onReset() {
this.name = null;
}
};
</script>
How do I onReset() work?
Automatically translated.
I think you have some confusion about your child component and parent component. On your code Nome is the child component and the form that using Nome is the parent component.
You can use ref to call the reset method on Nome from the parent form component.
Here is a Working example -
Vue.component("nome-input", {
data(){
return {
input: ""
}
},
template: `
<input #input="onInput" type="text" v-model="input">
`,
methods: {
reset(){
this.input = ""
},
onInput(){
this.$emit('onInput', this.input);
}
}
});
Vue.component("user-form", {
data(){
return {
name: '',
}
},
components: {
},
template: `
<div>
{{name}}
<nome-input ref="nome" #onInput="updateName"></nome-input>
<button #click.prevent="save">Save</button>
<button #click.prevent="reset">reset</button>
</div>
`,
methods: {
save(){
console.log(this.name);
},
reset(){
this.name = "";
this.$refs.nome.reset();
},
updateName(value){
this.name = value;
}
}
});
new Vue({
el: "#app",
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<user-form></user-form>
</div>
</body>
</html>
Here is a jsfiddle link for the above codes https://jsfiddle.net/azs06/u4x9jw62/34/

Vue.js: Collapse/expand all elements from parent

I need to add "expand/collapse all" functionality for my Vue component(some collapsible panel).
If user clicks collapse button then clicks on some panel and expand it then clicking on collapse button will do nothing because watched parameter will not change.
So how to implement this functionality properly (buttons must collapse and expand components always)?
I prepared simple example(sorry for bad formatting, it looks nice in editor :( ):
var collapsible = {
template: "#collapsible",
props: ["collapseAll"],
data: function () {
return {
collapsed: true
}
},
watch: {
collapseAll: function(value) {
this.collapsed = value
}
}
}
var app = new Vue({
template: "#app",
el: "#foo",
data: {
collapseAll: true
},
components: {
collapsible: collapsible
}
});
.wrapper {
width: 100%;
}
.wrapper + .wrapper {
margin-top: 10px;
}
.header {
height: 20px;
width: 100%;
background: #ccc;
}
.collapsible {
height: 100px;
width: 100%;
background: #aaa;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
<div id="foo"></div>
<script type="text/x-template" id="collapsible">
<div class="wrapper">
<div class="header" v-on:click="collapsed = !collapsed"></div>
<div class="collapsible" v-show="!collapsed"></div>
</div>
</script>
<script type="text/x-template" id="app">
<div>
<button v-on:click="collapseAll = true">Collapse All</button>
<button v-on:click="collapseAll = false">Expand All</button>
<collapsible v-for="a in 10" v-bind:collapseAll="collapseAll" v-bind:key="a"></collapsible>
</div>
</script>
Thanks!
This is a case where I might use a ref.
<button v-on:click="collapseAll">Collapse All</button>
<button v-on:click="expandAll">Expand All</button>
<collapsible ref="collapsible" v-for="a in 10" v-bind:key="a"></collapsible>
And add methods to your Vue.
var app = new Vue({
template: "#app",
el: "#foo",
methods:{
collapseAll(){
this.$refs.collapsible.map(c => c.collapsed = true)
},
expandAll(){
this.$refs.collapsible.map(c => c.collapsed = false)
}
},
components: {
collapsible: collapsible
}
});
Example.

Categories