Use Vue.js Prop to populate vForm data? - vue.js

I am still fairly new to using Laravel and Vue.js and have been having some problems when trying to submit data to be used in a modal form.
overview.vue is displaying some information and triggering the modal component
My modal element:
<EditTeamModal :existing="existing_team"/>
In my template I am triggering the following function
#click="getExistingTeam(membership.team)"
Which triggers the following method:
getExistingTeam: function (team) {
this.existing_team = team;
this.$bvModal.show('edit_team');
},
EditTeamModal.vue
In my modal component I have several inputs like the one following:
<div class="form-group row">
<label for="name" class="col-md-4 col-form-label text-md-right">{{ $t('team.name') }} <span class="text-danger">*</span></label>
<div class="col-md-8">
<input type="text" v-model="form.name" :class="{ 'is-invalid': form.errors.has('name') }" class="form-control" id="name" name="name" required/>
<has-error :form="form" field="name" />
<small id="nameHelp" class="form-text text-muted">Unique name of your team (155 character limit).</small>
</div>
</div>
and am setting my props and vForm data as follows:
props: {
existing: {
type: Object,
required: true,
default: {}
}
},
// middleware: 'auth',
data () {
return {
form: new Form({
id: this.existing.id,
name: this.existing.name,
region: this.existing.region,
website: this.existing.website,
about: this.existing.about,
membership_password: "",
membership_password_confirmation: "",
avatar: null,
}),
}
},
However, my form inputs are always blank...
I can access this.exists.name directly and get the proper expected data output, however it will not seem to populate into my form fields?!
Is there a proper way to pull data from a vue property into vForm form data?

Was able to get the modal form data to update by adding the following to my EditTeamModal.vue
watch: {
existing: function(val) {
this.form.fill(this.existing);
}
},

Related

Vue v-model/v-for doesn't update on mount, but after first manual change

I have a dropdown list "functions" that is filled with database entries and a dropdown list with 2 hardcoded entries. When the vue website is opened the dropdown list remains empty but as soon as I change the value of the other dropdown field the desired data from the database is available.
I'm a bit confused because I expected that adding "retrieveFunctions()" into the mounted() function would trigger the v-for, and even more confused that changing something in another select field suddenly triggers it.
The HTML code:
<template>
<div class="submit-form">
<div v-if="!submitted">
<div class="row">
<div class="col-sm-12">
<p><a style="width:500px" class="btn btn-info" data-toggle="collapse" href="#generalInformation" role="button" aria-expanded="true" >
General Information</a></p>
<div class="collaps show" id="generalInformation">
<!-- NAME -->
<div class="form-group">
<input placeholder="Name" type="text" class="form-control"
id="name" required v-model="component.name" name="name">
</div>
<!-- DOMAIN -->
<div class="input-group mb-3">
<div class="input-group-prepend">
<label style="width:100px" class="input-group-text" for="inputGroupDomain">Domain</label>
</div>
<select v-model="component.domain"
class="custom-select"
id="inputGroupDomain"
>
<option value="Power System">Power System</option>
<option value="ICT">ICT</option>
</select>
</div>
<!-- FUNCTION -->
<div class="input-group mb-3">
<div class="input-group-prepend">
<label style="width:100px" class="input-group-text" for="inputGroupFunction">Functions</label>
</div>
<select v-model="_function" class="custom-select" id="inputGroupFunction">
<option :class="{ active: index == currentIndex }"
v-for="(_function, index) in functions"
:key="index"
value= _function.name>
{{ _function.name }}
</option>
</select>
</div>
</div>
<p>
<button #click="saveComponent" class="btn btn-success">Add Component</button>
</p>
</div>
</div>
</div>
<div v-else>
<h4>Component was added succesfully!</h4>
<button class="btn btn-success" #click="newComponent">Proceed</button>
</div>
The script part:
<script>
import FunctionDataService from "../services/FunctionDataService";
export default {
name: "add-component",
data() {
return {
component: {
id: null,
name: "",
type: "",
domain: "",
},
submitted: false
};
},
methods: {
retrieveFunctions() {
FunctionDataService.getAll()
.then(response => {
this.functions = response.data;
console.log(response.data);
})
.catch(e => {
console.log(e);
});
},
refreshList() {
this.retrieveFunctions();
},
},
mounted() {
this.retrieveFunctions();
}
};
</script>
refreshList() {
this.retrieveFunctions();
},
},
mounted() {
this.retrieveFunctions();
}
};
</script>
State in the beginning: Dropdown list empty
State after selecting something in the upper dropdown list: Database entries are visible and correct
You need to initiate all responsive properties on the data return object with either a value (empty string, array, object, etc) or null. Currently it's missing the _function attribute used in the select v-model and the functions array used in the v-for. You can try to change the data to the following:
data() {
return {
_function: "",
functions: [],
component: {
id: null,
name: "",
type: "",
domain: "",
},
submitted: false
};
},

How can I change input value in Vue when value is set and update it when it is object of arrays?

I generate so many input boxes on loop of article array.
article is array of objects. Input boxes values are set with "value" key in each object.
<div
v-for="(option, i) in this.article"
:key="i"
class="form-row"
>
<div class="col">
<input
v-model="option.value"
:label="'label '+i"
:name="'inputValue'+i"
type="text"
required
/>
</div>
</div>
<button #click="submit"></button>
<script>
export default {
name: 'Article',
data(){
return(
article:[
{id: 'art1', value: 'artValue1'},
{id: 'art2', value: 'artValue2'},
{id: 'art3', value: 'artValue3'}
// There are about 50 objects
]
)
},
methods:{
submit(){
// How get values of inputs?
}
}
}
</script>
How can I make the value of input change and update the object in vue?
I created a sample Single File Component based on your code. Look at my modifications. The 'magic' of Vue reactivity is that the 'article' data is updated in real time as you change the input values.
<template>
<div class="input-bound-object-array">
<div class="row">
<div class="col-md-6">
<form #submit.prevent="submitForm">
<div class="form-group" v-for="(option, i) in article" :key="i">
<label>{{ option.id }}</label>
<input type="text" class="form-control" v-model="option.value"
required />
</div>
<button type="submit" class="btn btn-secondary">Submit</button>
</form>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
article: [
{ id: 'art1', value: 'artValue1' },
{ id: 'art2', value: 'artValue2' },
{ id: 'art3', value: 'artValue3' }
// There are about 50 objects
]
}
},
methods: {
submitForm() {
// 'this.article' is updated as the input values are changed, so at this point
// you have the data changes, so you can process it as needed, i.e. POST to REST endpoint
console.log(this.article);
}
}
}
</script>
You forgot to return the object from data function and you can pass option to submit handler and print the input values.
// How get values of inputs? -> Do you mean all of the inputs or input where ever the button clicked or anything else. Below code is to handle individual input and submit handlers
<template>
<div
v-for="(option, i) in article"
:key="i"
class="form-row"
>
<div class="col">
<input
v-model="option.value"
:label="'label ' + i"
:name="'inputValue' + i"
type="text"
required
/>
</div>
<!-- <button #click="submit(option)">Submit</button> to handle individual inputs -->
</div>
<!-- <button #click="submitAll()">Submit All</button> to handle all inputs -->
</template>
<script>
export default {
name: 'Article',
data() {
return { // you missed this
article:[
{id: 'art1', value: 'artValue1'},
{id: 'art2', value: 'artValue2'},
{id: 'art3', value: 'artValue3'}
]
}
},
methods: {
submit(option) { // current option
console.log(option.id, option.value)
},
submitAll() {
console.log(this.article) // which will have update input values as
you're using `v-model`, check `values`
}
}
}
</script>
Demo Link here

create vue.js v-model from dynamci value

I am generating a some checkbox dynamically. Now I need to create v-model dynamic.
<div class="form-group input-group">
<label class="form-group-title">DIETARY PREFERENCES</label>
<p>Please mark appropriate boxes if it applies to you and/or your family</p>
<div class="check-group" v-for="v in alldietry" :key="v">
<input type="checkbox" v-model="userinfo.{{#Here will be the value}}" value="" id="Vegetarian">
<label for="Vegetarian">{{v.title}}</label>
</div>
</div>
into the v-model I have try v-model="userinfo.{{xyz}}" its shows error.
You can't use {{ }} interpolation inside attributes.
The v-model value is a javascript expression, so instead of
v-model="userinfo.{{xyz}}"
you can just do
v-model="userinfo[xyz]"
as you would normally do in javascript when accessing a dynamic property of an object.
To bind dynamic object to model, you need to access to key shared by the model value and the set of data used to display your list.
let vm = new Vue({
el: '#app',
data: {
userinfo: {
0: '',
1: ''
}
},
computed: {
alldietry() {
return [
{
id: 0,
title: 'Title'
},
{
id: 1,
title: 'Title'
}
]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" class="form-group input-group">
<label class="form-group-title">DIETARY PREFERENCES</label>
<p>Please mark appropriate boxes if it applies to you and/or your family</p>
<div class="check-group" v-for="(v, index) in alldietry" :key="index">
<input type="checkbox" v-model="userinfo[v.id]" value="" :id="v.id">
<label :for="v.id">{{v.title}}</label>
</div>
{{ userinfo }}
</div>

Vuejs - Proper way to clone an element, and append to DOM

I have a HTML input field to enter some information:
<div id="fruitForm">
<div class="inputArea">
<label for="fruit0">Enter Fruit Name</label>
<input id="fruit0"></input>
</div>
</div>
<button #click="newInputField">Add More Fruit Input Fields</button>
<button #click="submit">Submit Fruit</button>
And then I handle that click event:
export default {
data() {
return {
}
},
methods: {
newInputField() {
//Create another input area for users to input fruits
},
submit() {
//Do something here
}
}
}
When a user selects the Add More Fruit Input Fields button, it should create a new input area so that the HTML looks like this:
<div id="fruitForm">
<div class="inputArea">
<label for="fruit0">Enter Fruit Name</label>
<input id="fruit0"></input>
</div>
<div class="inputArea">
<label for="fruit1">Enter Fruit Name</label>
<input id="fruit1"></input>
</div>
</div>
<button #click="newInputField">Add More Fruit Input Fields</button>
<button #click="submit">Submit Fruit</button>
Now, I've been using traditional DOM manipulation methods via vanilla Javascript to accomplish this... stuff like this:
const inputArea = document.getElementsByClassName('inputArea');
And then I change the id's of the input field, and then I use appendChild to add the new input field to the DOM.
So my question is: how should I be cloning this element with vuejs? I feel I'm not approaching this in the vuejs way. Should I be approaching this like a list and using v-for? Or something else?
Avoid direct DOM manipulations with Vue. You can use data property as a model for your template. The answer would be yes, you can and probably should use v-for for what you call cloning:
var demo = new Vue({
el: '#demo',
data: {
counter: 0,
inputs: [{
id: 'fruit0',
label: 'Enter Fruit Name',
value: '',
}],
},
methods: {
addInput() {
this.inputs.push({
id: `fruit${++this.counter}`,
label: 'Enter Fruit Name',
value: '',
});
}
}
});
<script src="https://unpkg.com/vue#2.5.16/dist/vue.js"></script>
<div id="demo">
<div class="inputArea" v-for="input in inputs" :key="input.id">
<label :for="input.id">{{input.label}}</label>
<input :id="input.id" v-model="input.value"></input>
</div>
<button #click="addInput">Add input</button>
</div>

Vuejs cannot push to nested array

First question on stack overflow, I apologize if I am asking in the wrong place. New to Vue and been trying for several days to finish a small project. I've simplified it but here it is. I want to be able to enter as many customer names as I need, and then be able to add as many customer's childrens names as I need. So an array of customers with a nested array of children. I can get the customers to add, but I cannot figure out why I cannot push a new element into the children's array. Here is my code.
new Vue ({
el: '#app',
data: function () {
return {
formdata: [],
fields: [{
name: '',
childs: [{
cname: '',
}]
}],
};
},
methods: {
addRow: function() {
this.fields.push({
name: "",
childs: [{
cname:'',
}],
});
},
addChild: function() {
this.child.push({
});
},
},
});
And my html
<div id="app">
<button class="btn btn-success" #click="addRow">Add</button>
<div v-for="field in fields" >
<div class="input-group">
<input type="text" placeholder="Name" class="form-control" v-model="field.name">
</div>
<div v-for="child in field.childs" >
<div class="input-group">
<input type="text" placeholder="Child" class="form-control" v-model="child.cname">
<div class="input-group-btn">
<button class="btn btn-success" #click="addChild">Add</button>
</div>
</div>
</div>
</div>
</div>
Again, the problem is that i can push a new "name" to the fields array, but i cannot push a new child into the fields child array. I have been trying every permutation of child childs field fields etc, trying to find how to reference that array. Any help would be greatly appreciated!
In your addChild method, you need to be accessing the childs property of the relevant field. Currently, you are trying to access the childs property of the Vue instance, which doesn't exist.
You should pass the relevant field to the addChild method like so:
<button class="btn btn-success" #click="addChild(field)">Add</button>
And then update your addChild method to reference the childs array of the field passed in:
addChild: function(field) {
field.childs.push({});
}