How can I duplicate my component in vue.js? - javascript

<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++
}

Related

bootstrap-vue - show button based on boolean

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

Set up a v-on:click directive inside v-for

I have displayed a list of images with some information. I want those images to be clickable. And when clicked it should show a div with saying "HI!!". I have been trying to add a variable as show:true in Vue data and tried to build some logic that show becomes false when clicked. But I have not been able to achieve it.
Below is the sample code:
template>
<div>
<h1>SpaceX</h1>
<div v-for="launch in launches" :key="launch.id" class="list" #click="iclickthis(launch)">
<div ><img :src="launch.links.patch.small" alt="No Image" title={{launch.name}} /></div>
<div>ROCKET NAME: {{launch.name}} </div>
<div>DATE: {{ launch.date_utc}} </div>
<div>SUCCESS: {{ launch.success}} </div>
<div>COMPLETENESS: {{ launch.landing_success}} </div>
</div>
<!-- <v-model :start="openModel" #close="closeModel" /> -->
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'SpaceXTimeline',
components: {
},
data: () => ({
launches : [],
openModel : false,
show : true,
}),
methods: {
iclickthis(launch) {
// this should load a model search v-model / bootstrap on vue npm install v-model
console.log(launch.name + " is launched");
console.log("DETAILS: "+ launch.details);
console.log("ROCKET INFO: "+ launch.links.wikipedia);
console.log("CREW DETAILS: "+ launch.crew);
console.log("Launchpad Name: "+ launch.launchpad);
this.openModel = true;
},
closeModel () {
this.openModel = false;
}
},
async created() {
const {data} = await axios.get('https://api.spacexdata.com/v4/launches');
data.forEach(launch => {
this.launches.push(launch);
});
}
};
</script>
<style scoped>
.list {
border: 1px solid black;
}
</style>
Thanks, and appreciate a lot.
v-model is a binding and not an element, unless you've named a component that? Is it a misspelling of "modal"?
Either way, sounds like you want a v-if:
<v-model v-if="openModel" #close="closeModel" />
Example:
new Vue({
el: '#app',
components: {},
data: () => ({
launches: [],
openModel: false,
show: true,
}),
methods: {
iclickthis(launch) {
// this should load a model search v-model / bootstrap on vue npm install v-model
console.log(launch.name + ' is launched');
console.log('DETAILS: ' + launch.details);
console.log('ROCKET INFO: ' + launch.links.wikipedia);
console.log('CREW DETAILS: ' + launch.crew);
console.log('Launchpad Name: ' + launch.launchpad);
this.openModel = true;
},
closeModel() {
this.openModel = false;
},
},
async created() {
const {
data
} = await axios.get('https://api.spacexdata.com/v4/launches');
data.forEach(launch => {
this.launches.push(launch);
});
},
})
Vue.config.productionTip = false;
Vue.config.devtools = false;
.modal {
cursor: pointer;
display: flex;
justify-content: center;
position: fixed;
top: 0;
width: 100%;
height: 100vh;
padding: 20px 0;
background: rgba(255, 255, 255, 0.5);
}
img {
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<div id="app">
<h1>SpaceX</h1>
<div v-for="launch in launches" :key="launch.id" class="list" #click="iclickthis(launch)">
<div>
<img :src="launch.links.patch.small" alt="No Image" :title="launch.name" />
</div>
<div>ROCKET NAME: {{ launch.name }}</div>
<div>DATE: {{ launch.date_utc }}</div>
<div>SUCCESS: {{ launch.success }}</div>
<div>COMPLETENESS: {{ launch.landing_success }}</div>
</div>
<div v-if="openModel" #click="closeModel" class="modal">
MODAL
</div>
</div>

How does :class="`level ${file.invalidMessage && 'has-text-danger'}`" break down?

I am following this tutorial to upload files using VueJS and Express server and I have encountered a line of code that I do not understand.
At 8:19 we are introduced to :class="`level ${file.invalidMessage && 'has-text-danger'}`". I couldn't find anything similar in the Vue documentation.
Video Example:
<div v-for="(file, index) in files" :key="index"
:class="`level ${file.invalidMessage && 'has-text-danger'}`"
>
</div>
Vue Docs:
<div v-bind:class="{ active: isActive }"></div>
<div
class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }"
></div>
<div v-bind:class="classObject"></div>
<div v-bind:class="[activeClass, errorClass]"></div>
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
There is nothing similar to that weird syntax in the Vue Documentation.
I understand what ${} inside back quotes marks is used for(template literals).
I understand what the code purpose is, I have tested it and works, but I do not understand how it works and what shortcuts were used.
Can somebody "translate" that line of code ?
The :class binding in Vue accepts strings:
new Vue({
el: "#app",
computed: {
classlist() {
return this.classes.join(' ')
}
},
data() {
return {
classes: [
'first-class',
'second-class'
],
domClassList: null
}
},
mounted() {
// getting and setting the classlist of the DOM element
this.domClassList = document.getElementById('classList').getAttribute('class')
}
})
.level {
background: green;
padding: 15px;
}
.first-class {
color: white;
}
.second-class {
font-weight: 700;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div id="classList" :class="`level ${ classlist }`">
CLASSES ADDED AS STRINGS
</div>
<div>Classes: {{ domClassList }}</div>
</div>
As you can see in the snippet above, the classes are made from one level and the join of a Vue data variable (the classes array) that is returned in a computed property (classlist).
The other part of the question is the conditional format:
new Vue({
el: "#app",
computed: {
classlist() {
return this.classes.join(' ')
}
},
data() {
return {
firstOperand: true,
classes: [
'first-class',
'second-class'
],
domClassList: null
}
},
methods: {
setDomClassList() {
// getting and setting the classlist of the DOM element
this.domClassList = document.getElementById('classList').getAttribute('class')
},
toggleOperand() {
this.firstOperand = !this.firstOperand
// this.$nextTick is required so Vue can set the data
// values before we read it from the DOM
const self = this
this.$nextTick(function() {
self.setDomClassList()
})
}
},
mounted() {
this.setDomClassList()
}
})
.level {
background: green;
padding: 15px;
}
.first-class {
color: white;
}
.second-class {
font-weight: 700;
}
/* this class is set so you can see the difference on
toggling the firstOperand variable
*/
.false {
font-style: italic
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div id="classList" :class="`level ${ firstOperand && classlist }`">
CLASSES ADDED AS STRINGS
</div>
<div>Classes: {{ domClassList }}</div>
<hr />
<div>
FIRSTOPERAND IS {{ firstOperand }}<br />
<button #click="toggleOperand">TOGGLE FIRSTOPERAND TO {{ !firstOperand }}</button>
</div>
</div>
The second snippet is almost the same as the first, except the && is introduced. I also created a .false CSS value so you can see the returned false.

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/

Categories