I have a simple form to update a password with 3 inputs (old_password, new_password and new_password_confirmation).
After the submit, if it is updated successfully, the inputs are cleaned. The problem is that after this, the input errors are showed even when the conditional is false.
This is one of the inputs:
<input type="password" v-model="old_password">
<small class="text-danger" v-if="errors.old_password != ''">{{errors.old_password}}</small>
The logic:
<script>
export default {
data() {
return {
old_password: '',
errors: []
}
},
watch: {
old_password(value) {
this.old_password = value
if(value.length < 3) {
this.errors.old_password = 'Debes ingresar al menos 4 caracteres'
} else {
this.errors.old_password = ''
}
}
},
methods: {
updatePassword() {
this.$store.dispatch('updatePassword', data)
.then(response => {
this.old_password = ''
this.errors.old_password = ''
})
.catch(error => {
})
}
}
}
</script>
Because once input becomes empty your condition value.length < 3 is true and error will be shown
Simply add to your condition this one && value.length > 0
So the final code will look like
if(value.length < 3 && value.length > 0) {
this.errors.old_password = 'Debes ingresar al menos 4 caracteres'
} else {
this.errors.old_password = ''
}
Also, errors should be an object instead of an array - errors: {}
Related
I have some code where I update multiple files using a package.
Add / Remove seems to work if I console.log, but if I do a POST request, on server I get all files, even if I delete them.
Example: I add 3 files, I delete 2 of them and I do a POST, on server I get 3 files. (But on console.log it shows me that I have only 1 which is correct).
Also, I find this article , but I am not sure what to do in my case.
This is a short version of my code.
<div id="upload-files-on-update">
<file-upload
:multiple="true"
v-model="certifications"
input-id="certifications"
name="certifications[]"
#input-filter="inputFilter"
ref="upload">
<span class="button">Select files</span>
</file-upload>
</div>
new Vue({
el: '#upload-files-on-update',
data: function () {
return {
certifications: [],
}
},
components: {
FileUpload: VueUploadComponent
},
methods: {
updateFiles(){
let formData = new FormData();
this.certifications.forEach((file, index) => {
if (!file.status && file.blob) {
formData.append("certifications[]",
{
types: this.accept,
certifications_ids: this.certifications_ids,
}
);
this.loadingButton = true;
}
});
axios
.post("<?php echo $link;?>", formData, {
headers: {
"Content-Type": "multipart/form-data"
},
params:{
types: this.accept,
certifications_ids: this.certifications_ids,
}
})
},
inputFilter(newFile, oldFile, prevent) {
if (newFile && !oldFile) {
if (/(\/|^)(Thumbs\.db|desktop\.ini|\..+)$/.test(newFile.name)) {
return prevent()
}
if (/\.(php5?|html?|jsx?)$/i.test(newFile.name)) {
return prevent()
}
}
if (newFile && (!oldFile || newFile.file !== oldFile.file)) {
newFile.blob = ''
let URL = window.URL || window.webkitURL
if (URL && URL.createObjectURL) {
newFile.blob = URL.createObjectURL(newFile.file)
}
newFile.pending = true;
newFile.thumb = ''
if (newFile.blob && newFile.type.substr(0, 6) === 'image/') {
newFile.thumb = newFile.blob
}
}
},
// Remove file from table
removeFile(index) {
this.certifications.splice(index, 1);
},
}
});
I found a solution for this problem.
//I catch ajax request and I make sure that is the request that I want it
var self = this;
$.ajaxSetup({
beforeSend: function (xhr,settings) {
if(settings.type != 'POST'){
return ;
}
if(settings.data.get('controller') != 'wcfm-memberships-registration'){
return ;
}
// Here I set file input as an empty array
settings.data.set('certifications[]',[]);
// Here I add my new files from a VueJS array
self.certifications.forEach((file, index) => {
settings.data.append("certifications[]", file.file);
});
}
});
});
I am getting data from firebase and overriding my roomName value in the loop. But outside the loop, it will not get the updated value.
Can someone please help me with the same?
export default {
name: "Chat",
components: {
ChatMessages
},
data(){
return{
rooms: [],
roomName: null,
}
},
mounted() {
this.getRooms();
},
methods: {
getRooms() {
roomsRef.orderByChild('name').once('value').then(snapshot => {
this.rooms = snapshot.val();
});
},
selectUser: function(userId) {
$.each(this.rooms,function(index,data){
if((data.sender_id == firebase.auth().currentUser.uid && data.receiver_id == userId ) || (data.sender_id == userId && data.receiver_id == firebase.auth().currentUser.uid )){
this.roomName = data.room_name;
}
});
if(this.roomName == null){
console.log("Null");
console.log(this.roomName);
}else{
console.log("Not Null");
console.log(this.roomName);
}
},
}
}
As pointed out by User 28 in the comment section, you need to use an arrow function:
$.each(this.rooms,(index,data) => {
if((data.sender_id == firebase.auth().currentUser.uid && data.receiver_id == userId ) || (data.sender_id == userId && data.receiver_id == firebase.auth().currentUser.uid )){
this.roomName = data.room_name;
}
});
Explanation. A "normal" function binds its own this. An arrow function inherits the this of the parent scope. Read more here: https://www.codementor.io/#dariogarciamoya/understanding-this-in-javascript-with-arrow-functions-gcpjwfyuc
I have a table with an input column. This input column will have value if it has been saved in ddbb before.
If this value changes, handled with an event '#blur', I show a modal to confirm the change.
My problem is that if you want to keep the old value it will always change...
I tried to change this value with javascript, but it doesn't work... Any suggestions?
This is my code:
<b-tbody>
<b-tr
v-for="(driver, index) in drivers"
:key="driver.clientId">
<b-td
data-label="Client"
:title="driver.clientName">{{ driver.clientName }}</b-td>
<b-td data-label="Numerator">
<b-input
:id="'numeratorDriver_'+index"
class="driver-numerator text-right"
type="text"
:value="(driver.driverNumerator === undefined) ? 0 : $utils.formatNumber(driver.driverNumerator)"
#blur="calculatePricingDriver($event, index)" /></b-td>
<b-td
class="text-right"
data-label="Pricing"
:title="driver.pricingDriver"><span>{{ driver.pricingDriver }}</span></b-td>
</b-tr>
</b-tbody>
<script>
function calculatePricingCustomDriver (event, index) {
let lastValue = this.drivers[index].driverNumerator
if (this.$store.getters.price !== undefined) {
let title = 'Modify numerator'
let message = 'If you modify numerator driver, the calculated pricing will be deleted'
this.$bvModal.msgBoxConfirm(message, {
title: title,
size: 'sm',
buttonSize: 'sm',
okTitle: 'Yes',
okVariant: 'primary',
cancelTitle: 'No',
cancelVariant: 'primary',
hideHeaderClose: false,
centered: true
})
.then(confirmed => {
if (confirmed) {
this.$http.get('delete-price', { params: { id: this.$store.getters.id } })
.then((response) => {
if (response.status === this.$constants.RESPONSE_STATUS_OK) {
this.price = ''
let newNumerator = event.target.value
this.drivers[index].driverNumerator = Number(newNumerator)
let sumTotal = _.sumBy(this.drivers, 'driverNumerator')
for (let i = 0; i < this.drivers.length; i++) {
this.drivers[i].pricingDriver = (this.drivers[i].driverNumerator / sumTotal).toFixed(2)
}
} else {
this.drivers[index].driverNumerator = lastValue
// this is that I want change because it doesn't work fine
document.getElementById('numeratorDriver_' + index).value = lastValue
}
})
} else {
this.drivers[index].driverNumerator = lastValue
document.getElementById('numeratorDriver_' + index).value = lastValue
}
})
.catch(() => {
/* Reset the value in case of an error */
this.$utils.showModalError()
})
} else {
let newNumerator = event.target.value
this.drivers[index].driverNumerator = Number(newNumerator)
let sumTotal = _.sumBy(this.drivers, 'driverNumerator')
for (let i = 0; i < this.drivers.length; i++) {
this.drivers[i].pricingDriver = (this.drivers[i].driverNumerator / sumTotal).toFixed(2)
}
}
}
</script>
how is calculatePricingCustomDriver being loaded into your Vue component? For it to be called like that from #blur you would need to define it as a method:
<template>
<!-- your table-->
</template>
<script>
export default {
name: "MyComponent",
methods : {
calculatePricingCustomDriver () {
// your code
}
}
}
</script>
Or it could be installed as a global mixin
i have this code
computed: {
termOptions() {
if (this.newSchedule.originCharges.serviceType !== 'If Any') {
return this.serviceOptions.filter((val) => val.name !== 'If Any');
}
},
isMoreThanToday() {
if (this.newSchedule.validFrom) {
const date = new Date();
const isMore = this.newSchedule.validFrom < date.getDate();
return isMore;
}
},
}
and i got an error saying expected return value at the of method. Is there any way to fix this? thank you.
This is ESLint error. It tells you that a computed property should always return some value.
Your computed properties return values only when the condition of the if is true and don't return anything when it's false.
computed: {
termOptions() {
if (this.newSchedule.originCharges.serviceType !== 'If Any') {
return this.serviceOptions.filter((val) => val.name !== 'If Any');
}
else {
return []
}
},
isMoreThanToday() {
if (this.newSchedule.validFrom) {
const date = new Date();
const isMore = this.newSchedule.validFrom < date.getDate();
return isMore;
}
else {
return false
}
},
}
See this page for details.
I'm using vue-2.4 and element-ui 1.4.1.
Situation
I have a basic input which is linked with v-model to a computed property. When blur I check if the value input is greater or lower than min and max and I do what I have to do ... Nothing fancy here.
Problem
The value displayed in the input does not always equal enteredValue
Steps to reproduce
1) Input 60 --> Value displayed is the max so 50 and enteredValue is 50 (which is ok)
2) Click outside
3) Input 80 --> Value displayed is 80 and enteredValue is 50
Questions
How can I fix that so the value displayed is always the same as the enteredValue ?
Here is the minimal code to reproduce what I'm facing JSFIDDLE
<div id="app">
The variable enteredValue is {{enteredValue}}
<el-input v-model="measurementValueDisplay" #blur="formatInput($event)"></el-input>
</div>
var Main = {
data() {
return {
enteredValue: '',
max: 50,
min: 10
}
},
computed: {
measurementValueDisplay: {
get: function () {
return this.enteredValue + ' inchs'
},
set: function (newValue) {
}
},
},
methods: {
formatInput($event) {
let inputValue = $event.currentTarget.value;
if (inputValue > this.max) { this.enteredValue = this.max}
else if (inputValue < this.min) { this.enteredValue = this.min}
else this.enteredValue = inputValue
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
Reading this vuejs, will understand what happens
"computed properties are cached based on their dependencies. A computed property will only re-evaluate when some of its dependencies have changed."
Changed some comportament of the code. Made run:
computed() method not works properly for update value in window. But if looks at console the value yes updated.
So, i remove computed (getter and setter), and put into data, without setter and getter( i dont like this in javascript).
var Main = {
data() {
return {
measurementValueDisplay:'fff',
enteredValue: '',
max: 50,
min: 10
}
},
computed: {
/*measurementValueDisplay: {
get: function () {
console.log('Computed was triggered so I assume enteredValue changed',this.enteredValue);
return this.enteredValue + ' inchs'
},
set: function (newValue) {
console.log('setter de qye', this.enteredValue);
}
},*/
},
methods: {
formatInput($event) {
this.enteredValue = 0;
let inputValue = $event.currentTarget.value;
console.log(inputValue);
if (inputValue > this.max) { this.enteredValue = this.max}
else if (inputValue < this.min) { this.enteredValue = this.min}
else this.enteredValue = inputValue
this.measurementValueDisplay = this.enteredValue + ' inchs'
console.log(this.enteredValue, 'oioioioio0');
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
Your problem is that the values used in the computed property was not updated with the validation capping at 50 (Was 50, is now updated to 50, no need to recalculate), therefore v-model did not update the input.
I've edited your jsfiddle to use two computed properties:
One with an accessor to validate the entered value, one which returns the value with " inch" appended.
Here is the interesting part:
computed: {
measurementValueDisplay: {
get: function () {
return this.enteredValue
},
set: function (newValue) {
this.enteredValue = 0;
let inputValue = parseInt(newValue);
if(Number.isNaN(inputValue)){this.enteredValue = this.min}
else if (inputValue > this.max) { this.enteredValue = this.max}
else if (inputValue < this.min) { this.enteredValue = this.min}
else this.enteredValue = inputValue
}
},
valueWithInch(){
return this.enteredValue + " inch";
}
},
In case anybody still needs a hack for this one, you can use a value that will always change ( for example a timestamp )
var Main = {
data() {
return {
enteredValue: '',
max: 50,
min: 10,
now: 1 //line added
}
},
computed: {
measurementValueDisplay: {
get: function () {
return (this.now - this.now + 1 ) * this.enteredValue + ' inchs'; //line changed
},
set: function (newValue) {
this.now = Date.now(); //line added
}
},
},
methods: {
formatInput($event) {
let inputValue = $event.currentTarget.value;
if (inputValue > this.max) { this.enteredValue = this.max}
else if (inputValue < this.min) { this.enteredValue = this.min}
else this.enteredValue = inputValue
}
}
}