VueJs textarea does not show the stored information when editing - vue.js

I am using Vuejs and have, inside a form, a textarea field.
When editing i can not see the value, inside the textarea.
If i save i do not lose the previous information as expected.
If i edit it stores the data as expected.
I only can not find, how to present the textarea value, when editing.
Inside a v-for loop i have the textarea that extendes a parent textarea template :
<row v-for="(field, index) in fields" :key="index">
<div v-if="field.formType === 'textarea'">
<va-textarea
:id="field.index"
v-model='formInput[index]'
v-bind:value="formValue[index]"
></va-textarea>
The field is defined in the data property :
data () {
return {
fields: {
Commentts: {
label : 'Commentts',
sortable : false,
type : 'textarea',
formType : 'textarea',
formReadOnly : false
}
And i have the formSave method to insert or edit:
methods: {
formSave() {
if ( this.formValue.Id === undefined) {
this.formInput.Motivo_Id = this.formInput.Motivo.id
}
this.saveButton = true;
this.formLoading= true;
this.axios.post('Courses/save',
{
"data": { Id : this.formValue.Id,
Date : this.saveDateTime(this.formInput.Date),
faculty_Id: this.formInput.faculty_Id,
Commentts: this.formInput.Commentts
},
"route" : this.$route.name,
}).then((response) => {
How can i show the textarea information when editing the form ?

Looks strange but let's figure out.
Loop
<row v-for="(field, index) in fields" :key="index">
By your example fields is the object and variable index contains value "Commentts" and not an index. Is it what you want?
Data propagation
<va-textarea
:id="field.index"
v-model='formInput[index]'
v-bind:value="formValue[index]"
></va-textarea>
I know nothing about va-textarea component implementation but I hope parameters v-model and :value were configured properly.
And with current implementation component's data field must contain and:
data () {
return {
fields: {
Commentts: {
.....
},
formInput: {
Commentts: ...some data...
},
formValue: {
Commentts: ...some data...
},
Because declaration `v-model='formInput[index]'` requires `formInput` field in the root of the data field with `Commentts` inside.

Related

Why it is hard to use vue-i18n in vue data() (why it is not reactive)

I am using vue-i18n in a vue project. And I found it really confusing when using some data in vue data with i18n. Then if I change locale, that data is not reactive. I tried to return that data from another computed data but anyways it is not reactive because i18n is written in data. *My situation - * I want to show table with dropdown(list of columns with checkbox) above it. When user checks a column it will be showed in table if unchecks it won't. It is working fine until I change locale. After changing locale table columns is not translated but dropdown items is reactively translated and my code won't work anymore. Here is some code to explain better: In my myTable.vue component I use bootstrap-vue table -
template in myTable.vue
<vs-dropdown vs-custom-content vs-trigger-click>
<b-link href.prevent class="card-header-action btn-setting" style="font-size: 1.4em">
<i class="fa fa-th"></i>
</b-link>
<vs-dropdown-menu class="columns-dropdown">
<visible-columns :default-fields="columns" #result="columnListener"></visible-columns>
</vs-dropdown-menu>
</vs-dropdown>
<b-table class="generalTableClass table-responsive" :fields="computedFieldsForTable">custom content goes here</b-table>
script in myTable.vue
data(){
return {
fieldsForTable: [];
}
},
computed: {
computedFieldsForTable () {
return this.fieldsForTable;
},
columns() {
return [
{
key: 'id',
label: this.$t('id'),,
visible: true,
changeable: true
},
{
key: 'fullName',
label: this.$t('full-name'),,
visible: true,
changeable: true
},
{
key: 'email',
label: this.$t('email'),,
visible: true,
changeable: true
}
]
}
},
mounted () {
this.fieldsForTable = this.filterColumns(this.columns);
},
methods: {
filterColumns(columns = []) {
return columns.filter(column => {
if (column.visible) {
return column
}
})
},
columnListener ($event) {
this.fieldsForTable = this.filterColumns($event)
}
}
Can someone give me some advice for this situation ?
*EDIT AFTER SOME DEBUGGING: I think when filtering columns(in computed) and returning it for fieldsForTable inside filterColumns(columns) method, it actually returning array(of objects) with label='Label Name' not label=this.$t('labelName'). So after filtering the new array has nothing to do with vue-i18n. My last chance is reloading the page when locale changes.
Trying modify computedFieldsForTable as follows. You need to reference this.columns in computedFieldsForTable, so that Vue can detect the change of labels in this.columns.
computedFieldsForTable () {
return this.filterColumns(this.columns);
},
EDITED: put your this.columns in data. Then
columnListener ($event) {
this.columns = $event;
}
I hope i didn't misunderstand what you mean.
EDITED (again):
Maybe this is the last chance that I think it can work. Put columns in computed() still and remove computedFieldsForTable. Finally, just leave fieldsForTable and bind it on fields of <b-table>.
watch: {
columns(val) {
this.fieldsForTable = this.filterColumns(val)
}
},
method: {
columnListener ($event) {
this.fieldsForTable = this.filterColumns($event)
}
}
However, I think it is better and easier to reload page whenever local change. Especially when your columns have a more complex data structure.

Vue.js dynamic binding v-model and value

I use django-rest-framework + vue.js
My goal is to make a Form to edit user-profile.
Here is what i have:
<input type="email" v-model="userEdit.email">
<input type="text" v-model="userEdit.location">
<input type="text" v-model="userEdit.bio">
my inputs are bounded to data object "editUser"
data() {
return {
'editUser': {
email: '',
location: '',
bio: '',
image: '',
},
}
},
so now i can send this object to the server and change user-profile information.
sendChanges() {
const fd = new FormData();
fd.append('image', this.editUser.image, this.editUser.image.name)
fd.append('email', this.editUser.email)
fd.append('location', this.editUser.location)
fd.append('bio', this.editUser.bio)
this.axios.put(userDetailURL + this.routeUser, fd)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error.response)
})
},
this form works and updates info, but there is a thing i dont like:
The input fields are always empty, and user needs to fill all of them before can press save button.
even if the user wants to change only "location" he must fill other inputs which are empty.
adding dynamic :value="userDetail.email" to the input -- no work.
is there any other way to add current value to input field and still have v-model?
current data is here:
computed: {
userDetail() {
return this.$store.getters.userDetail;
},
},
The problem is that you are binding the values in data to the form and those values are initially empty.
The cleanest and easiest solution I can think of right now is updating the initial data in mounted lifecycle hook:
mounted () {
// Use Object.clone to prevent modifying the userDetail object directly
this.editUser = Object.clone(this.$store.getters.userDetail)
}
There are other solutions, though. You could use a computed setter whose getter defaults to whatever is in the store but can be overridden when set.

Vue.js - v-model with a predefined text

I have an input attribute that I want to have text from a source and is two-way binded
// messages.html
<input type="textarea" v-model="newMessage">
// messages.js
data () {
newMessage: ''
},
props: {
message: {
type: Object,
required: true,
default () {
return {};
}
}
// the message object has keys of id, text, and hashtag
I would like the initial value of input to be message.text. Would it be appropriate to do something like newMessage: this.message.text?
EDIT
I tried adding :value="message.text" in input but that didn't really show anything
Yes, you can reference the props in the data function.
data(){
return {
newMessage: this.message.text
}
}

vuejs2 passing data between parent-child is wiping childs value

In VueJS 2 I am trying to create a component that gets and passes data back to the parent which then passes it to another component to display.
The component that gets the data has a user input field it uses to search. When I have it pass data back to the parent using $emit the value in the input keeps being wiped.
I am receiving the below mutation error but I haven't directly tried to change the userSearch field in the component so I am not sure why.
"Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "userSearch" (found in PersonField)"
Relevant html
<person-field v-on:event_child="eventChild"></person-field>
<person-search :prop="personListArray" ></person-search>
Parent app
var app = new Vue({
el: '#app',
data: {
personListArray : [],
tempArray: []
},
methods: {
eventChild: function (arr) {
this.personListArray = arr
}
}
})
Component 1, displays a user input. Uses the input to search and bring back data. Starts search when the length of the input is more then 2. As soon as you hit the 3rd character something is causing the input to clear which I don't want.
Vue.component('person-field', {
props: ['userSearch'],
template: '<input class="form-control" v-model="userSearch" >',
watch: {
userSearch: function () {
var arr = []
if (typeof this.userSearch !== 'undefined') { //added this because once i passed 3 characters in the field the userSearch variable becomes undefined
if (this.userSearch.length > 2) {
$.each(this.getUsers(this.userSearch), function (index, value) {
var obj = {
Title: value.Title,
ID: value.ID
}
arr.push(obj)
});
this.$emit('event_child', arr) //emits the array back to parent "eventChild" method
} else {
console.log('no length')
}
} else {
console.log('cant find field')
}
},
},
methods: {
getUsers: function (filter) {
//gets and returns an array using the filter as a search
return arr
},
}
});
Component 2 - based on the personListArray which is passed as a prop, displays the results as a list (this works)
Vue.component('person-search', {
props: ['prop'],
template: '<ul id="personList">' +
'<personli :ID="person.ID" v-for="person in persons">' +
'<a class="" href="#" v-on:click="fieldManagerTest(person.Title, person.ID)">{{person.Title}}</a>' +
'</personli></ul>',
computed: {
persons: function () {
return this.prop
}
},
methods: {
fieldManagerTest: function (title, ID) { //Remove item from users cart triggered via click of remove item button
//var user = ID + ';#' + title
//this.internalValue = true
//this.$emit('fieldManagerTest');
//this.$parent.$options.methods.selectManager(user)
},
},
});
Component 3, part of component 2
Vue.component('personli', {
props: ['ID'],
template: '<transition name="fade"><li class="moving-item" id="ID"><slot></slot></li></transition>'
})
;
The reason you get the warning,
Avoid mutating a prop directly since the value will be overwritten
whenever the parent component re-renders. Instead, use a data or
computed property based on the prop's value. Prop being mutated:
"userSearch" (found in PersonField)
Is because of this line
<input class="form-control" v-model="userSearch" >
v-model will attempt to change the value of the expression you've told it to, which in this case is userSearch, which is a property.
Instead, you might copy userSearch into a local variable.
Vue.component('person-field', {
props: ['userSearch'],
data(){
return {
searchValue: this.userSearch
}
},
template: '<input class="form-control" v-model="searchValue" >',
...
})
And modify your watch to use searchValue.
Here is an example.

BootstrapValidator for bootstrap typeahead

I want to know if BootstrapValidator http://bootstrapvalidator.com/ has a validation for typeahead.
I have a form where where i am validating my fields using the validator. One of the fields is a inout field where a typeahead is attached so the input field is filled by the typeahead select.
But whenever I start typing in the input field the validator validates its true. I want something like it must validates only after typeahead selection and not by writing in the the input field.
$(document).ready(function() {
var options = {};
options.common = {
minChar: 1
};
options.ui = {
showVerdictsInsideProgressBar : true,
viewports : {
progress : ".pwstrength_viewport_progress"
}
};
.......
$('#user_country').on('input', function() {
$(this).parent().find('.small').hide();
});
$('#user_reg_form').bootstrapValidator({
excluded: ':disabled',
feedbackIcons: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
........
country: {
validators: {
notEmpty: {
message: 'city is required'
}
}
},
}
})
My typeahead looks like
$(ele).typeahead({
select:function(){
// here i do the select.....
}
});
I ran into a similar problem using a date picker - you could try manually binding the validation - e.g:
$('#userCountry').on('blur', function(e) {
$('#user_reg_form').bootstrapValidator('revalidateField', 'userCountry');
});
Does your typeahead control limit them to one of the options in the list?