Programmatically create forms in vue - javascript

I want to ask the user how many points he wants to create and then get each points coordinates.
I tried creating a initial text field to get how many points and then a loop to create each form. It works but I don't know how to get each form value.
How can I get each form values? Or is there a better way to do it?
<template>
<div>
<v-card class="mb-3">
<v-card-text>
<v-text-field label="How many nodes" :value="nodes" #input="onInput" type="number"></v-text-field>
</v-card-text>
</v-card>
<v-container fluid grid-list-md>
<v-layout row wrap>
<template v-for="i in nodes">
<v-flex :key="i" xs12 md3>
<div>
<v-card class="mb-3">
<v-card-text>
<div>Node {{i}}</div>
<v-text-field label="Coord X" value="x1" #input="getValues" type="number" v-model="no1"></v-text-field>
<v-text-field label="Coord Y" :value="y1" #input="getValues" type="number"></v-text-field>
</v-card-text>
</v-card>
</div>
</v-flex>
</template>
</v-layout>
</v-container>
</div>
</template>
<script>
export default {
data () {
return {
nodes: 2
}
},
methods: {
onInput (val) {
this.nodes = parseInt(val)
}
}
}
</script>

I think this would be a better way of doing it:
<template>
<div>
<v-card class="mb-3">
<v-card-text>
<v-text-field label="How many nodes" v-model="nodes" type="number"></v-text-field>
</v-card-text>
</v-card>
<v-container fluid grid-list-md>
<v-layout row wrap>
<template v-for="(node, index) in nodesArr">
<v-flex :key="i" xs12 md3>
<div>
<v-card class="mb-3">
<v-card-text>
<div>Node {{index + 1}}</div>
<v-text-field label="Coord X" v-model="node[index].coordX" type="number" v-model="no1"></v-text-field>
<v-text-field label="Coord Y" v-model="node[index].coordY" type="number"></v-text-field>
</v-card-text>
</v-card>
</div>
</v-flex>
</template>
</v-layout>
</v-container>
</div>
</template>
<script>
export default {
data () {
return {
nodes: 0,
nodesArr: []
}
},
watch: {
nodes(newVal) {
this.nodesArr = [];
for(var i=0; i<this.nodes; i++){
this.nodesArr.push({coordX: "", coordY: ""});
}
}
},
methods: {
}
}
</script>
Whats going on:
Set up a v-model on the input which takes the number of nodes and bind it to nodes property.
initialized a new property nodesArr : [] which will be used to loop through to display each Coord input
set up a watcher on nodes which loops through the number of nodes entered and pushes those many objects {coordX: "", coordY: ""} to nodesArr array
we loop through nodesArr using v-for="(node, index) in nodesArr" to display the inputs for x-coord and y-coord
The x-coord input is bound to the corresponding coordX property making use of the index we get in v-for
Similarly the y-coord input is bound to the corresponding coordY property making use of the index we get in v-for
since the inputs are two way bound using v-model you have all the input data in nodesArr property which can be used as you wish

Related

Vue.js: How can I put a Login Modal inside a dropdown Menu?

I have the following dropdown menu:
<template>
<v-menu close-on-click transition="slide-y-transition">
<template v-slot:activator="{ on, attrs }">
<v-btn color="primary" v-bind="attrs" v-on="on">
Menu
</v-btn>
</template>
<v-list>
<v-list-item v-for="(item, index) in menuItemsMisc" :key="index" v-model="item.model">
<v-list-item-title>
<v-btn block color="white" #click="item.fn">{{ item.title }}</v-btn>
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
<!-- Modal code here -->
</template>
<script>
export default {
name: 'MenuBar',
data: () => ({
loginModal: false,
purchaseModal: false,
menuItemsMisc: [
{ title: 'Login',
model: 'loginModal',
fn: () => { this.loginModal = true}
},
{ title: 'Purchase',
model: 'purchaseModal',
fn: () => { this.purchaseModal = true }
},
]
}),
}
</script>
And I am trying to display this Login Modal When the Login Button is clicked in the dropdown.
<v-dialog v-model="loginModal" persistent max-width="500px">
<v-card class="elevation-12">
<v-toolbar color="primary" dark flat>
<v-toolbar-title>Login form</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-card-text>
<v-form>
<v-text-field name="login" prepend-icon="mdi-account" type="text"></v-text-field>
<v-text-field id="password" name="password" prepend-icon="mdi-lock" type="password">
</v-text-field>
</v-form>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary">Login</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
But whenever I click the Login or Purchase Button, I have an error that says:
TypeError: Cannot set property 'loginModal' of undefined
What is the Problem here?
From the Vue docs on v-model:
You can use the v-model directive to create two-way data bindings on form input, textarea, and select elements. It automatically picks the correct way to update the element based on the input type.
The v-model property on your <v-dialog> component is expecting it to be an input of some type.
You should be able to simply change this to a v-if:
<v-dialog v-if="loginModal" persistent max-width="500px">
This will cause the <v-dialog> component to display when your button is clicked.
EDIT: Please also make sure your data property on the Vue instance is declared as a class-style function. If you use a lambda function you will lose the this scope when referring to this.loginModal:
export default {
...
data() {
return {
...
}
}
}

How to have the button span the whole width?

I am using Vuetify card with a layout and rendering some dynamic vuetify components inside of the card on checkbox selection which renders either a divider, a spacer, toolbar or button but i am not able to figure out how can i make the buttons span the entire width?
Basically the dynamic button should look like the button at the end rendering the entire width.
Please check this codepen.
Please check this working example:-
new Vue({
el: "#app",
data() {
return {
pricing: [{
text: "Actual price:",
value: "$17,000",
},
{
text: " Discount",
value: "$12,345",
}
],
elements: [{
title: "Divider",
value: "v-divider"
},
{
title: "Toolbar",
value: "v-toolbar"
},
{
title: "Button",
value: "v-btn"
}
],
selected: []
};
}
});
<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>
<link rel="stylesheet" href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons'>
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.css" rel="stylesheet" />
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout row>
<v-flex xs6>
<v-card>
<v-card-text>
<v-layout row justify-space-between v-for="option in pricing" :key="option.value" class="my-3">
<span :class="option.class">{{option.text}}</span>
<component v-for="(el, i) in selected" :key="i" :is="el.value"></component>
<span>{{option.value}}</span>
</v-layout>
<v-layout row justify-center>
<v-flex xs11>
<v-btn block>
Request
</v-btn>
</v-flex>
</v-layout>
</v-card-text>
</v-card>
<v-flex v-for="el in elements" :key="el.value">
<v-checkbox :value="el" v-model="selected" :label="el.title">
</v-checkbox>
</v-flex>
</v-flex>
</v-layout>
</v-container>
</v-app>
</div>
Any help will be appreciated. Thank you so much.
Use .flex.xs12 (12 = flex-basis: 100%;)
-or-
remove xs12 (And add button block attribute = flex: 1 0 auto;).
<!-- block buttons extend the full available width -->
<template>
<v-btn block>
Block Button
</v-btn>
</template>
https://vuetifyjs.com/en/components/buttons/#block

Show mutiple v-dialog boxes with different content in vue.js

Hii I am working on the Vue.js template and I stuck at a point where I need to show dynamic v-dialog using looping statement but now it shows all.
Dom:
<template v-for="item of faq">
<div :key="item.category">
<h4>{{ item.heading }}</h4>
<div v-for="subitems of item.content" :key="subitems.qus">
<v-dialog
v-model="dialog"
width="500"
>
<template v-slot:activator="{on}">
{{subitems.qus}}
</template>
<v-card>
<v-card-title
class="headline grey lighten-2"
primary-title
>
Privacy Policy
</v-card-title>
<v-card-text>
{{ subitems.ans }}
</v-card-text>
<v-divider></v-divider>
</v-card>
</v-dialog>
</div>
</div>
</template>
Script:
export default {
data: () => ({
faq,
dialog:false,
}),
}
I do not understand how I can do this. If I click on one button then it shows all.
There must a design a pattern for this one but a quick solution would be to create array of booleans for v-models of dialogs. something like below
export default {
data: () => ({
faq,
dialog: [] // Array instead of Boolean.
}),
}
and
<template v-for="item of faq">
<div :key="item.category">
<h4>{{ item.heading }}</h4>
<div v-for="(subitems, index) of item.content" :key="subitems.qus">
<v-dialog
v-model="dialog[index]"
width="500"
>
<template v-slot:activator="{on}">
{{subitems.qus}}
</template>
<v-card>
<v-card-title
class="headline grey lighten-2"
primary-title
>
Privacy Policy
</v-card-title>
<v-card-text>
{{ subitems.ans }}
</v-card-text>
<v-divider></v-divider>
</v-card>
</v-dialog>
</div>
</div>
</template>
Brother, you are doing a very small mistake, you should not keep your v-dialog component inside your loop, take this out from loop block and don't take dialog as empty array keep it false.

How can I clear data from multiple v-text-fields on button click?

I have a side panel with searching mechanism and I want to delete, or empty the existing data from each text fields and v-model on button click.
<search-panel :rightDrawer="rightDrawer" #cancelSearch="cancelSearch" #searchData="searchCustomers" #clearData="clearData">
<v-layout row>
<v-flex xs11 offset-xs1>
<v-text-field name="input-1-3" label="Frist Name" light v-model="searchVm.contains.firstName"></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs11 offset-xs1>
<v-text-field name="input-1-3" label="Last Name" light v-model="searchVm.contains.lastName"></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs11 offset-xs1>
<v-text-field name="input-1-3" label="Application Name" light v-model="searchVm.contains.applicationName"></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs11 offset-xs1>
<v-select v-model="searchVm.contains.status"
:items="statuses"
label="Status"
item-text= "name"
item-value= "id"
:return-object="false"></v-select>
</v-flex>
</v-layout>
</search-panel>
clearData() {
for (var e in this.searchVm.contains) {
e.Value=""; //just for demonstartion
}
}
Try this by looping through the keys of your object and use that keys to access the object properties in order to set them to empty strings
Object.keys(this.searchVm.contains).forEach(key=>{
this.searchVm.contains[key]="";
});

v-for key as a v-model in VueJS not working

I am using Vuetify framework for VueJS and I am trying to recreate the Data table edit dialog but instead of static values, I want the edit dialog to be dynamic (User can specify editable fields).
The problem is that I can't use the key I get from v-for for v-model like this.
<v-dialog v-model="dialog" max-width="500px">
<v-card>
<v-card-title>
<span class="headline">Edit Item</span>
</v-card-title>
<v-card-text>
<v-container grid-list-md>
<v-layout wrap>
<v-flex xs12 sm6 md4 v-for="(item, key, index) in editable_fields">
{{key}}
<h1>{{editedItem}}</h1>
<v-text-field v-model="editedItem.key" :label="key"></v-text-field>
</v-flex>
</v-layout>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" flat #click.native="close">Cancel</v-btn>
<v-btn color="blue darken-1" flat #click.native="save_edit">Save</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
And these are my props and data:
props: {
editable_fields: {
type: Object
default: ()=> {name: '', email: ''}
}
}
data: ->
editedItem = #editable_fields
return {editedItem: editedItem}
So the question is how should I approach to this?

Categories

Resources