How to bind "v-model" property in vue? - vue.js

I want to show list of inputs dynamically.
I am not asking about using v-bind OR v-model, I want to bind v-model property itself (like v-bind:v-model).
Here is the code but it does not work.
<template>
<div class="form-outside">
<form>
<div v-for="(input, index) in inputs" :key="index">
<div class="caption">{{input.caption}}</div>
<input :type="input.type" :v-model="input.model" />
</div>
<div v-if="error" class="error-message">{{error}}</div>
<div v-if="kind=='login'" class="suggestion">
Don't have an account?
<nuxt-link to="/signup">Sign up</nuxt-link> instead!
</div>
<div v-if="kind=='signup'" class="suggestion">
Have an account?
<nuxt-link to="/login">Log in</nuxt-link> instead!
</div>
<div v-if="loading" class="loading">Loading</div>
<button #click.prevent="submitted" v-if="!loading">{{button_text}}</button>
</form>
</div>
</template>
<script>
export default {
name: "AuthForm",
props: ["kind", "error", "loading"],
methods: {
submitted() {
this.$emit("submitted", {
email: this.email,
password: this.password,
confirm_password: this.confirm_password,
full_name: this.full_name,
login: this.login,
username: this.username
});
}
},
computed: {
button_text() {
if (this.kind == "login") return "Log in";
if (this.kind == "signup") return "Sign up";
},
inputs() {
return this.possible_inputs.filter(
input => input.when == "always" || input.when == this.kind
);
}
},
data() {
return {
email: "",
password: "",
confirm_password: "",
full_name: "",
login: "",
username: "",
possible_inputs: [
{
caption: "Full Name",
type: "text",
when: "signup",
model: this.full_name
},
{
caption: "Email",
type: "email",
when: "signup",
model: this.email
},
{
caption: "Email or Username",
type: "text",
when: "login",
model: this.login
},
{
caption: "Username",
type: "text",
when: "signup",
model: this.username
},
{
caption: "Password",
type: "password",
when: "always",
model: this.password
},
{
caption: "Confirm Password",
type: "password",
when: "signup",
model: this.confirm_password
}
]
};
}
};
</script>
(This is some additional text because stackoverflow says “It looks like your post is mostly code, please add some more details”, just ignore it)

In data(){} you cannot assign in this way model: this.email so you need to assign it in mounted() {} hook, check the code below:
<script>
export default {
data() {
return {
email: "",
password: "",
confirm_password: "",
full_name: "",
login: "",
username: "",
possible_inputs: []
};
},
mounted() {
this.possible_inputs = [
{
caption: "Full Name",
type: "text",
when: "signup",
model: this.full_name
}, {
caption: "Email",
type: "email",
when: "signup",
model: this.email
}, {
caption: "Email or Username",
type: "text",
when: "login",
model: this.login
}, {
caption: "Username",
type: "text",
when: "signup",
model: this.username
}, {
caption: "Password",
type: "password",
when: "always",
model: this.password
}, {
caption: "Confirm Password",
type: "password",
when: "signup",
model: this.confirm_password
},
];
},
};
</script>

Related

Vuejs get dynamic form values

I have select and input component with made by buefy. Everything is ok till I realize how can I get the data.
I'm sort of new on vuejs. So I will be glad if you help me out.
I'm getting dynamic form from backend
So my question is how can get values these inputs and submit to backend again with getOffer() methot.
Here is my codes;
Input.vue
<template>
<b-field :label="fieldLabel">
<b-input
:name="inputName"
:type="inputType"
:maxlength="inputType == 'textarea' ? 200 : null"
></b-input>
</b-field>
</template>
<script>
export default {
name: "Input",
props: {
inputType: {
type: String,
required: true,
default: "text",
},
inputName: {
type: String,
required: true,
},
fieldLabel: {
type: String,
required: true,
}
}
};
</script>
Home.vue
<template>
<div class="container is-max-desktop wrapper">
<div v-for="element in offer" :key="element.id">
<Input
v-model="element.fieldValue"
:value="element.fieldValue"
:fieldLabel="element.fieldLabel"
:inputType="element.fieldType"
:inputName="element.fieldName"
v-if="element.fieldType != 'select'"
class="mb-3"
/>
<Select
v-model="element.fieldValue"
:fieldLabel="element.fieldLabel"
:options="element.infoRequestFormOptions"
:selectName="element.fieldName"
v-if="element.fieldType == 'select'"
class="mb-3"
/>
</div>
<b-button type="is-danger" #click="getOffer()">GET</b-button>
</div>
</template>
<script>
import axios from "axios";
import Select from "../components/Select.vue";
import Input from "../components/Input.vue";
export default {
name: "Home",
data() {
return {
offer: [],
};
},
components: {
Select,
Input,
},
methods: {
getOfferForm() {
axios({
method: "get",
url: `/GETDYNAMICFORM`,
})
.then((response) => {
this.offer = response.data;
})
.catch(() => {
this.$buefy.toast.open({
duration: 3000,
message: "oops",
position: "is-bottom",
type: "is-danger",
});
});
},
getOffer() {
console.log(this.offer);
},
},
created() {
this.getOfferForm();
},
};
</script>
Example Dynamic Form Response like;
[
{
"id": 58,
"fieldLabel": "Name Surname",
"providerLabel": "Name Surname",
"fieldName": "nmsrnm",
"fieldType": "text",
"fieldValue": null,
},
{
"id": 60,
"fieldLabel": "E-mail",
"providerLabel": "E-mail",
"fieldName": "e_mail_60",
"fieldType": "email",
"fieldValue": null,
},
{
"id": 2,
"fieldLabel": "Budget",
"providerLabel": "Budget",
"fieldName": "bdget",
"fieldType": "select",
"fieldValue": "",
"infoRequestFormOptions": [
{
"id": 1,
"orderNum": 0,
"optionValue": 0,
"optionText": "Select",
"minValue": null,
"maxValue": null
},
{
"id": 2,
"orderNum": 1,
"optionValue": 1,
"optionText": "10-30",
"minValue": 10,
"maxValue": 30
}
]
}
]

How to make this three components into a multistep form wizard

Here I have made three components. That is displaying one after other I want to make this component to display like multistep form. like step1, step2, step3, Here if we click next button from step1 than it should go to step2. and so on..., So if any one have an idea on this pleas help me thank you.
<head>
<script src="https://unpkg.com/vue#2.5.17/dist/vue.min.js"></script>
<script src="https://unpkg.com/vue-form-generator#2.3.4/dist/vfg.js"></script>
<script src="https://unpkg.com/vue-form-generator#2.3.4/dist/vfg.css"></script>
</head>
<div class="container" id="app">
<div class="panel panel-default">
<div class="panel-heading">Form</div>
<div class="panel-body">
<vue-form-generator :schema="schema" :model="model" :options="formOptions"></vue-form-generator>
</div>
</div>
<vue-form-generator :schema="schema" :model="model" :options="formOptions"></vue-form-generator>
<vue-form-generator :schema="schema" :model="model" :options="formOptions"></vue-form-generator>
<vue-form-generator :schema="schema" :model="model" :options="formOptions"></vue-form-generator>
<script>
vue.js
var vm = new Vue({
el: "#app",
components: {
"vue-form-generator": VueFormGenerator.component
},
data() {
return {
model: {
id: "",
name: "",
password: "",
age: "",
skills: "",
email: "",
status: ""
},
schema: {
fields: [{
type: "input",
inputType: "text",
label: "ID",
model: "id",
readonly: true,
featured: false,
disabled: true
}, {
type: "input",
inputType: "text",
label: "Name",
model: "name",
readonly: false,
featured: true,
required: true,
disabled: false,
placeholder: "User's name",
}, {
type: "input",
inputType: "password",
label: "Password",
model: "password",
min: 6,
required: true,
}, {
type: "input",
inputType: "number",
label: "Age",
model: "age",
min: 18,
validator: VueFormGenerator.validators.number
}, {
type: "input",
inputType: "email",
label: "E-mail",
model: "email",
placeholder: "User's e-mail address",
validator: VueFormGenerator.validators.email
}, {
type: "checklist",
label: "Skills",
model: "skills",
multi: true,
required: true,
multiSelect: true,
values: ["HTML5", "Javascript", "CSS3", "CoffeeScript", "AngularJS", "ReactJS", "VueJS"]
}, {
type: "switch",
label: "Status",
model: "status",
multi: true,
readonly: false,
featured: false,
disabled: false,
default: true,
textOn: "Active",
textOff: "Inactive"
}]
},
formOptions: {
validateAfterLoad: true,
validateAfterChanged: true
}
};
},
});

Vuejs2- How to do an inline alignment of a radio button in vue-form-generator?

Iam using "vue-form-generator" plugin for dynamic loading of form fields. Among the fields, I am using "radio-button" for the "gender" field. Options are displayed in one below the other but I want the option should be displayed in the "inline" style
How to align the radio button option in the same row(inline)?
Here is my code: addMember.vue
<template>
<div class="panel-body">
<vue-form-generator :schema="schema" :model="model" :options="formOptions"></vue-form-generator>
<input type="submit" value="Submit">
</div>
</template>
<script>
import Vue from 'vue'
import VueFormGenerator from "vue-form-generator";
import "vue-form-generator/dist/vfg.css";
Vue.use(VueFormGenerator);
export default {
data: () => ({
model: {
building: "",
unitCategory: "",
unit: "",
fullName: "",
gender: "",
},
schema: {
groups: [{
fields: [{
type: "select",
inputType: "text",
label: "Building",
model: "building",
required: true,
styleClasses:'col-md-6',
values: [
{ id: "", name: 'Select Building' },
{ id: 'A', name: 'Block-A'},
{ id: 'B', name: 'Block-B'},
],
selectOptions: {
hideNoneSelectedText: true,
}
}]
},{
fields: [{
type: "select",
inputType: "text",
label: "Unit Category",
model: "unitCategory",
required: true,
styleClasses:'col-md-3',
values: [
{ id: "", name: 'Select Unit Category' },
],
selectOptions: {
hideNoneSelectedText: true,
}
},{
type: "select",
inputType: "text",
label: "Unit",
model: "unit",
required: true,
styleClasses:'col-md-3',
values: [
{ id: "", name: 'Select Unit' },
],
selectOptions: {
hideNoneSelectedText: true,
}
}]
},{
fields: [{
type: "input",
inputType: "text",
label: "Full Name",
model: "fullName",
placeholder: "Enter Full Name",
required: true,
styleClasses:'col-md-3'
},
{
type: "radios",
label: "Gender",
model: "gender",
values: [
"Male",
"Female",
"Other"
],
styleClasses:'col-md-3'
}]
}]
},
formOptions: {
validateAfterLoad: true,
validateAfterChanged: true
}
}),
}
</script>
You can add custom css to your radio input
{
type: "radios",
label: "Gender",
model: "gender",
values: [
"Male",
"Female",
"Other"
],
styleClasses:'col-md-3 display-inline'
}
and in your css
.display-inline label {
display: inline !important;
}
var vm = new Vue({
el: "#app",
components: {
"vue-form-generator": VueFormGenerator.component
},
data() {
return {
model: {
},
schema: {
fields: [{
type: "radios",
label: "Select your gender",
model: "friend",
values: [
"Male",
"Female",
"Others"
],
styleClasses: "display-inline"
}]
},
formOptions: {
validateAfterLoad: true,
validateAfterChanged: true
}
};
}
});
.display-inline label {
display: inline !important;
}
<link href="https://cdn.jsdelivr.net/npm/vue-form-generator#2.2.2/dist/vfg.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/vue-form-generator#2.2.2/dist/vfg.min.js"></script>
<script src="https://unpkg.com/vue#2.2.1/dist/vue.min.js"></script>
<h1 class="text-center">Demo of vue-form-generator</h1>
<div class="container" id="app">
<div class="panel panel-default">
<div class="panel-heading">Form</div>
<div class="panel-body">
<vue-form-generator :schema="schema" :model="model" :options="formOptions"></vue-form-generator>
</div>
</div>
</div>

Vuejs2- Issue in vue-form-generator

I am using "vue-form-generator" plugin for loading fields dynamically but I have encountered an error
[Vue warn]: Failed to mount component: template or render function not defined. found in vue-form-generator
Here is my code:
<template>
<vue-form-generator :schema="schema" :model="model" :options="formOptions"></vue-form-generator>
</template>
<script>
import Vue from 'vue'
import VueFormGenerator from "vue-form-generator";
Vue.use(VueFormGenerator);
export default {
components: { VueFormGenerator },
data: () => ({
model: {
id: 1,
name: "John Doe",
password: "J0hnD03!x4",
skills: ["Javascript", "VueJS"],
email: "john.doe#gmail.com",
status: true
},
schema: {
fields: [{
type: "input",
inputType: "text",
label: "ID (disabled text field)",
model: "id",
readonly: true,
disabled: true
},{
type: "input",
inputType: "text",
label: "Name",
model: "name",
placeholder: "Your name",
featured: true,
required: true
},{
type: "input",
inputType: "password",
label: "Password",
model: "password",
min: 6,
required: true,
hint: "Minimum 6 characters",
validator: VueFormGenerator.validators.string
},{
type: "select",
label: "Skills",
model: "skills",
values: ["Javascript", "VueJS", "CSS3", "HTML5"]
},{
type: "input",
inputType: "email",
label: "E-mail",
model: "email",
placeholder: "User's e-mail address"
},{
type: "checkbox",
label: "Status",
model: "status",
default: true
}]
},
formOptions: {
validateAfterLoad: true,
validateAfterChanged: true
}
})
}
</script>
To use it as local component, you should use this syntax
import VueFormGenerator from "vue-form-generator";
//component javascript
export default{
components:{
"vue-form-generator": VueFormGenerator.component
}
}
If you use
import VueFormGenerator from "vue-form-generator";
Vue.use(VueFormGenerator);
then it already registered VueFormGenerator as global. You don't need to register in components section of your code.
Here is our code with local component:
<template>
<vue-form-generator :schema="schema" :model="model" :options="formOptions"></vue-form-generator>
</template>
<script>
import Vue from 'vue'
import VueFormGenerator from "vue-form-generator";
export default {
components:{
"vue-form-generator": VueFormGenerator.component
},
data: () => ({
model: {
id: 1,
name: "John Doe",
password: "J0hnD03!x4",
skills: ["Javascript", "VueJS"],
email: "john.doe#gmail.com",
status: true
},
schema: {
fields: [{
type: "input",
inputType: "text",
label: "ID (disabled text field)",
model: "id",
readonly: true,
disabled: true
},{
type: "input",
inputType: "text",
label: "Name",
model: "name",
placeholder: "Your name",
featured: true,
required: true
},{
type: "input",
inputType: "password",
label: "Password",
model: "password",
min: 6,
required: true,
hint: "Minimum 6 characters",
validator: VueFormGenerator.validators.string
},{
type: "select",
label: "Skills",
model: "skills",
values: ["Javascript", "VueJS", "CSS3", "HTML5"]
},{
type: "input",
inputType: "email",
label: "E-mail",
model: "email",
placeholder: "User's e-mail address"
},{
type: "checkbox",
label: "Status",
model: "status",
default: true
}]
},
formOptions: {
validateAfterLoad: true,
validateAfterChanged: true
}
})
}
</script>

how to dynamically load a vue-form-generator schema?

I need to dynamically load (part of) a form schema asynchronously.
For example, I want to create the schema after a REST call.
I started using vue-form-generator,
I tried to manipulate the schema creating a component that:
creates a text input with a label Name-TEST-failed
asynchronously call a function that changes the label in Name-TEST-success
Code:
<template>
<div class="panel-body">
<vue-form-generator :schema="schema" :model="model" :options="formOptions"></vue-form-generator>
</div>
</template>
<script>
import Vue from 'vue';
import VueFormGenerator from "vue-form-generator";
Vue.use(VueFormGenerator);
export default {
created(){
setTimeout(() => {
console.log("start!");
Vue.set(this.$data.schema.fields,
[{
type: "input",
inputType: "text",
label: "Name-TEST-success",
model: "name",
placeholder: "Your name",
featured: true,
required: true
}]
)
console.log("end!");
}, 1000);
},
data() {
return {
model: {
name: "John Doe"
},
schema: {
fields: [{
type: "input",
inputType: "text",
label: "Name-TEST-failed",
model: "name",
placeholder: "Your name",
featured: true,
required: true
}]
},
formOptions: {
validateAfterLoad: true,
validateAfterChanged: true
}
}
}
}
</script>
both the messages start! and end! appear in the console, but the label of the input test does not change.
How can I change the schema (and the model) dynamically?
Just put the schema in a computed property and make it dependant on a data property. So the schema will change everytime you change a property on which it depends.
export default {
created(){
setTimeout(() => {
console.log("start!");
this.labelName = "Name-TEST-success"
}, 1000);
},
data() {
return {
model: {
name: "John Doe"
},
// Add a new property that you can change as you wish
labelName: 'Name-TEST-failed",
formOptions: {
validateAfterLoad: true,
validateAfterChanged: true
}
}
},
computed: {
schema () {
var result = {
fields: [{
type: "input",
inputType: "text",
label: this.labelName,
model: "name",
placeholder: "Your name",
featured: true,
required: true
}]
}
return result
}
}
}
UPDATE:
You don't need computed properties, they can lead to problems with validity check. Just manipulate the properties direclty.
PS: The $set method needs an index to work correct on arrays.
export default {
created(){
setTimeout(() => {
console.log("start!");
this.fieldObject.label = "Name-TEST-success"
}, 1000);
},
data() {
var fieldObject = {
type: "input",
inputType: "text",
label: this.labelName,
model: "name",
placeholder: "Your name",
featured: true,
required: true
}
return {
fieldObject, // now you can change label with "fieldObject.label = ..."
model: {
name: "John Doe"
},
schema: {
fields: [fieldObject]
},
formOptions: {
validateAfterLoad: true,
validateAfterChanged: true
}
}
}
}