How can I use a computed function inside a method function? - vue.js

Hi I am trying to call a computed function inside a method function.
VueJs Code:
<script>
export default {
created() {
this.isDisabled(0);
},
data: function() {
return {
form: {
branch_office_id: null,
cashier_id: null,
gross_amount: '',
released_tickets: '',
start_ticket: '',
end_ticket: '',
z_inform_number: '',
created_at: '',
support: null,
error_end_bill_number_validation: ''
},
postsSelected: "",
branch_office_posts: [],
cashier_posts: []
}
},
methods: {
checkEndBillNumber() {
if(this.form.start_ticket > this.form.end_ticket) {
this.isDisabled(1);
this.$awn.alert("El número de boleta inicial no puede ser ", {labels: {success: "Error"}});
} else {
this.isDisabled(0);
}
}
},
computed: {
isDisabled(value) {
if(value == 0) {
return true;
} else {
return false;
}
}
}
}
</script>
I am trying to user isDisabled() function inside checkEndBillNumber() method function but when I do that it says:
[Vue warn]: Error in v-on handler: "TypeError: this.isDisabled is not a function"
So I wonder how can I use it? how can I do that? Thanks!

Computed properties as mentioned above are not functions. Hence passing arguments like isDisabled(value) wont work. But you can trick it to anonymously accept the value like this
computed: {
isDisabled() {
return (value) => {
if(value == 0) return true;
else return false;
}
}
}
This way you don't need a data property.

You do not have computed functions, but computed properties! So you have to store the value you want to use as a parameter in your computed property - e.g. in a data attribute, and then use that:
<script>
export default {
created() {
this.disabledParam = 0;
this.isDisabled; // Evaluates to "true" - what do you want with that result?
},
data: function() {
return {
form: {
branch_office_id: null,
cashier_id: null,
gross_amount: '',
released_tickets: '',
start_ticket: '',
end_ticket: '',
z_inform_number: '',
created_at: '',
support: null,
error_end_bill_number_validation: ''
},
postsSelected: "",
branch_office_posts: [],
cashier_posts: [],
disabledParam: null,
}
},
methods: {
checkEndBillNumber() {
if (this.form.start_ticket > this.form.end_ticket) {
this.disabledParam = 1;
this.isDisabled; // Evaluates to "false" - what to you want to do with that value?
this.$awn.alert("El número de boleta inicial no puede ser ", {labels: {success: "Error"}});
} else {
this.disabledParam = 0;
this.isDisabled; // Evaluates to "true" - what to you want to do with that value?
}
}
},
computed: {
isDisabled() {
if (this.disabledParam == 0) {
return true;
} else {
return false;
}
}
}
}
</script>
Also, please note that your calls to isDisabled(1) wouldn't so anything even if you could use them as functions. You should probably do something with the return values of isDisabled.
And you do not need computed properties in this way - in your example, you should simply create isDisabled(value) as another method and call that. But I guess your code is just an example, not your real code. Computed properties usually are being used as values in your template.
My example code is just there to illustrate how you can pass parameters into the code of computed properties. Besides that, your code has some issues.

Related

Vuejs track input field

I need to check whether my input field is empty or not.
Logic
if form.name has value, use increase function
if form.name is empty, use decrease function
do not use increase, decrease functions on each character that user inputs or removes
Code
<el-form-item label="Product name *">
<el-input v-model="form.name"></el-input>
</el-form-item>
methods: {
increase() {
this.percentage += 8.3;
if (this.percentage > 100) {
this.percentage = 100;
}
},
decrease() {
this.percentage -= 8.3;
if (this.percentage < 0) {
this.percentage = 0;
}
},
}
any idea?
Update
Script
data() {
return {
form: {
name: '', // require
slug: '',
price: '', // require
supplier_id: '', // require
new_price: '',
base_price: '',
sku: '',
qty: 1, // require
active: '', // require
photo: '',
photos: [],
shortDesc: '',
longDesc: '',
origin: '',
tags: [],
brand_id: '', // require
categories: [],
user_id: '',
seoTitle: '',
seoTags: '',
seoPhoto: '',
seoDescription: '',
variations: [],
options: [],
condition: '', // require
isbn: '',
ean: '',
upc: '',
height: '',
weight: '',
lenght: '',
width: '', // require
},
}
},
methods: {
onSubmit(e) {
e.preventDefault();
axios.post('/api/admin/products/store', this.form)
.then(res => {
// do my things
})
.catch(function (error) {
console.log('error', error);
});
},
}
HTML
<el-form ref="form" :model="form" label-width="120px" enctype="multipart/form-data">
// my inputs (listed in form part in script above)
<el-button type="primary" #click="onSubmit" native-type="submit">Create</el-button>
</el-form>
One possible solution would be to use #focus and #blur events to check if form.name has a value before increasing or decreasing, this would be fired on focus or on blur events, so you will not have the methods fired on each character input or deletion.
for example:
<el-form-item label="Product name *">
<el-input #focus="checkName" #blur="checkName" v-model="form.name"></el-input>
</el-form-item>
methods: {
checkName() {
//If form.name has a value then run increase method, otherwise run decrease method
!!this.form.name ? this.increase() : this.decrease()
},
increase() {
this.percentage += 8.3;
if (this.percentage > 100) {
this.percentage = 100;
}
},
decrease() {
this.percentage -= 8.3;
if (this.percentage < 0) {
this.percentage = 0;
}
},
}
You can see a working fiddle HERE
UPDATE
Alright so i did follow the rules you state on your question, and i didn't know you wanted to get the percentage of completion of the form, so in order to do that, i would suggest to use a computed property, you can read more about computed properties in the VueJS Documentation, this way the percentage is calculated based on the criteria we can give it, and only if the form has values.
computed: {
formProgress: function () {
let totalInputs = Object.keys(this.form).length;
let filledInputs = 0;
Object.values(this.form).forEach(val => {
if (!!val){
filledInputs++;
}
});
return (filledInputs/totalInputs)*100
}
},
As you can see in one single computed property you can handle the complex logic and return the value reactively, to explain it better, i'm counting the lenght of the form object, to get total number of inputs in your form, so it's important to have all your form data inside the form data object, then i convert that object to an array to iterate it, and i check if each property has a value on it, if does it, i add 1 to the filledInputs counter, and finally just return a simple math to get the percentage. please check the new Fiddle here to see it in action:
FORM PROGRESS FIDDLE
If you have any other doubt just let me know.
UPDATE 2:
All right in order to only count for specific inputs for the form progress, i have modified the code to work based on an array that contains the names of the properties that are required. here is the full code:
data() {
return {
form: {
name: '',
lastName: null,
categories: [{}],
},
requiredFields: ['name', 'categories']
};
},
computed: {
formProgress: function () {
let totalInputs = this.requiredFields.length;
let filledInputs = 0;
Object.entries(this.form).forEach(entry => {
const [key, val] = entry;
if (this.requiredFields.includes(key)){
switch (val.constructor.name) {
case "Array":
if (val.length !== 0){
if (Object.keys(val[0]).length !== 0){
filledInputs++;
}
}
break
case "Object":
if (Object.keys(val).length !== 0){
filledInputs++;
}
break
default:
if (!!val){
filledInputs++;
}
}
}
});
return Number((filledInputs/totalInputs)*100).toFixed(1)
}
},
And here is the updated FIDDLE
As you can see now i'm using Object.entries to get the key and value of the form object, so you can have a single form object to send to your backend, this way i'm checking first if the key is in the required fields, and if has a value, so all you need to do is update the requiredFields data array with the same names as your inputs data property to make the validation work, also there is a validation depending if is array, array of objects, or object, that way it will validate input on each data type.
Hope this works for you.

Try to call the vuex getter in watch

I'm trying to call a Vuex getter in the component watch.
But it tells me that it is undefined what is not.
So i try to return the getter in the computed object but still doesn t work.
name: "FreeTalk",
computed: {
...mapGetters(['getCharacter','getResultStatus', 'getFreeTalkText', 'getResult', 'freeTalkResult', 'getFreeTalkNoNative', 'getFreeTalkMedium','getFreeTalkNative']),
progressStatus() {
return this.getResult.progress
},
getStatus() {
return this.getResultStatus
}
},
watch: {
progressStatus: (val) => {
if (val == 100) {
this.status = this.getStatus()
if (this.getStatus === 0) {
this.outputText = this.getFreeTalkNoNative.result;
} else if (this.getStatus === 1) {
this.outputText = this.getFreeTalkMedium;
} else if (this.getStatus === 2) {
this.outputText = this.getFreeTalkNative;
}
}
}
},
data() {
return {
outputText: '',
ready: false,
isRecordDone: false,
status: -1
}
}
}

Vue.js | Filters is not return

I have a problem.
I am posting a category id with http post. status is returning a data that is true. I want to return with the value count variable from the back. But count does not go back. Return in function does not work. the value in the function does not return from the outside.
category-index -> View
<td>{{category.id | count}}</td>
Controller File
/**
* #Access(admin=true)
* #Route(methods="POST")
* #Request({"id": "integer"}, csrf=true)
*/
public function countAction($id){
return ['status' => 'yes'];
}
Vue File
filters: {
count: function(data){
var count = '';
this.$http.post('/admin/api/dpnblog/category/count' , {id:data} , function(success){
count = success.status;
}).catch(function(error){
console.log('error')
})
return count;
}
}
But not working :(
Thank you guys.
Note: Since you're using <td> it implies that you have a whole table of these; you might want to consider getting them all at once to reduce the amount of back-end calls.
Filters are meant for simple in-place string modifications like formatting etc.
Consider using a method to fetch this instead.
template
<td>{{ categoryCount }}</td>
script
data() {
return {
categoryCount: ''
}
},
created() {
this.categoryCount = this.fetchCategoryCount()
},
methods: {
async fetchCategoryCount() {
try {
const response = await this.$http.post('/admin/api/dpnblog/category/count', {id: this.category.id})
return response.status;
} catch(error) {
console.error('error')
}
}
}
view
<td>{{count}}</td>
vue
data() {
return {
count: '',
}
},
mounted() {
// or in any other Controller, and set your id this function
this.countFunc()
},
methods: {
countFunc: function(data) {
this.$http
.post('/admin/api/dpnblog/category/count', { id: data }, function(
success,
) {
// update view
this.count = success.status
})
.catch(function(error) {
console.log('error')
})
},
},

How to pass an array values from one function to another function in vuejs?

I am trying to get the array values from
"validateBeforeSubmit" function to "saveForm" function. But I am
getting values of "undefined" in "arrlength". Please help me to solve.
This my code in vue.js
export default {
name: '',
data() {
return {}
},
ready: function() {
this.validateBeforeSubmit()
this.saveForm();
},
methods: {
validateBeforeSubmit() {
var fieldsVal = new Array();
var firstName = document.getElementById('firstName').value
var lastName = document.getElementById('lastName').value
var designation = document.getElementById('designation').value
if (firstName != "" && lastName != "" && designation != "") {
fieldsVal.push(firstName);
fieldsVal.push(lastName);
fieldsVal.push(designation);
return fieldsVal;
} else {
fieldsVal.length = 0;
return fieldsVal;
}
return fieldsVal;
},
saveForm() {
var fieldsValArray = this.validateBeforeSubmit();
var arrLength = fieldsValArray.length;
}
}
}
I can see multiple issues in your code:
1) Don't apply jQuery-like approach for getting input values. Use v-model instead. This will simplify your code
<template>
<input v-model="form.firstName" type="text"/>
</template>
<script>
export default {
data: {
form: {
firstName: '',
}
},
methods: {
validateBeforeSubmit() {
// take `firstName` directly from `data` not need for `getElementById`
const firstName = this.form.firstName;
}
},
}
</script>
2) Remove validateBeforeSubmit and saveForm from ready. Ready hook is obsolete in vue#2. And also it makes no sense. It's better to call it on form #submit.
3) It's better to create array using [] syntax instead of new Array()
Why never use new Array in Javascript
4) Always provide name for your component for easier debug
export default {
name: 'ValidationForm',
}
5) I don't know where was an issue but it works. Check this link below. I have updated your code. Try to submit form and check the console:
https://codesandbox.io/s/w6jl619qr5?expanddevtools=1&module=%2Fsrc%2Fcomponents%2FForm.vue

watching one value, computing the other one, how to update computed value when watched changes

I am watching one value and I computed another value.
Something like this:
computed: {
modeText: function () {
if(this.mode == 'create')
return 'Create'
else
return 'Edit'
}
},
watch: {
mode(val, old) {
if(val == 'create')
update modeText
else
update modeText
},
},
How do I recompute the computed value when watched value updates?
It seems like modeText is only dependent on mode, so instead of using computed, you can go for something simpler:
data: {
modeText: '',
mode: ''
},
watch: {
mode(val, old) {
this.modeText = this.updateModeText(val);
},
},
methods: {
updateModeText(val) {
if (val === 'create') {
return 'Create';
}
return 'Edit';
}
}