How can I add condition in class on vue.js 2? - vue.js

My component vue is like this :
<template>
<a href="javascript:" class="btn btn-block" :class="{ product == 'responseFound' ? ' btn-default' : ' btn-success' }" #click="add($event)">
...
</template>
There exist error :
invalid expression: :class="{ product == 'responseFound' ? '
btn-default' : ' btn-success' }"
How can I solve it?

Simply remove the brackets in :class:
<template>
<a href="javascript:" class="btn btn-block" :class="product == 'responseFound' ? ' btn-default' : ' btn-success'" #click="add($event)">
...
</template>
If you want to add more conditions, wrap it with [] to create an array:
:class="[product == 'responseFound' ? ' btn-default' : ' btn-success', foo ? 'foo' : 'bar']"

I would use a computed property for this kind of behaviour.
Which removes the logic from your template, and moves it into your script part.
<template>
<a href="javascript:" class="btn btn-block" :class="classes" #click="add($event)">
</template>
<script>
export default {
computed: {
classes() {
return this.product == 'responseFound' ? 'btn-default' : 'btn-success'
}
}
}
</script>

Related

validate form inputs bootstrap4

I have this code in my vue template
<div class="form-row" :class="{'was-validated': this.checkPassword()}">
<div class="col-6">
<label>Password</label>
<input :type="showPassword ? 'text' : 'password'" class="form-control" ref="password" required v-model="password">
<div class="valid-feedback" v-if="!error">
Password match
</div>
<div class="invalid-feedback" v-else>
Password not match
</div>
</div>
<div class="col-6">
<label>Confirm password</label>
<div class="input-group">
<input :type="showPassword ? 'text' : 'password'" class="form-control" ref="passwordCheck" required v-model="passwordCheck" #change="checkPassword()">
<div class="input-group-append">
<button class="btn btn-secondary" #click.prevent="copyToClipboard()"><i class="fas fa-clipboard"></i></button>
</div>
</div>
</div>
</div>
I want to show like the bootstrap4 documentation a green input field if the password matches or a red one if the password aren't matching. I'm trying by adding the was-validated class to the form-row if the demanded method return true but when the view where the password inputs are rendered the two input fields are always red. How I can fix this to give the correct feedback to the user?
Please always share all the relevant parts of the component otherwise, it's hard to tell where the problem resides. Here, you haven't shared your <script> section. Anyway, I guess this should put you on the right track.
<template>
<div class="form-row" :class="{'was-validated': this.checkPassword()}">
<div class="col-6">
<label>Password</label>
<label>
<input :type="showPassword ? 'text' : 'password'" class="form-control" :class="getPasswordClass()"
ref="password" required v-model="password">
</label>
</div>
<div class="col-6">
<label>Confirm password</label>
<div class="input-group">
<label>
<input :type="showPassword ? 'text' : 'password'" class="form-control" :class="getPasswordClass()"
ref="passwordCheck" required v-model="passwordCheck" #input="checkPassword()">
</label>
<div class="input-group-append">
<button class="btn btn-secondary" #click.prevent="copyToClipboard()"><i
class="fas fa-clipboard"></i></button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
password: null,
passwordCheck: null,
error: true,
showPassword: true,
}
},
methods: {
checkPassword() {
this.error = this.password !== this.passwordCheck;
},
getPasswordClass() {
if (!this.password || !this.passwordCheck) {
return '';
}
return this.error ? 'is-invalid' : 'is-valid'
},
copyToClipboard() {
//
}
}
}
</script>
So, in my opinion, you should only set the dynamic class (is-valid or is-invalid) when both inputs are provided. In this example I've added that to both password and passwordCheck fields but I think it's enough to just apply it to the passwordCheck because that's the one checked against the password.
If you only want to check after user leaves the field you could adjust the code like this:
In the template remove:
:class="{'was-validated': this.checkPassword()}"
And update:
#blur="checkPassword()
In the data() add:
blurred: false,
In the methods update:
methods: {
checkPassword() {
this.blurred = true;
this.error = this.password !== this.passwordCheck;
},
getPasswordClass() {
if (!this.blurred) {
return '';
}
return this.error ? 'is-invalid' : 'is-valid'
},
...
}

Cannot read property 'focus' of undefined in VUE When setting focus to button

I am new to vue I have component which if the endpoint fails, calls my generic 'Error' modal. All this is working fine but I keep getting the following error:
Cannot read property 'focus' of undefined
This only happens for the else part of my method function.
For this specific issue is I my 'failedPrcess' equals any of the following, this is when I get is, all others are fine:
existOrderSearchProdOrders
stockSearchStockLevels
cartFetchCouriers
Code
<template>
<div class="modal fade danger-modal" id="errorModal" tabindex="-1" role="dialog" aria-labelledby="errorModalTitle" aria-hidden="true"
data-keyboard="false" data-backdrop="static" style="z-index: 99999">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content danger-modal-content">
<div class="modal-header danger-modal-headerfooter">An error has occurred</div>
<div class="modal-body">
<p v-if="failedProcess === 'appGetAccount' || failedProcess === 'existOrderSearchProdOrders' || failedProcess === 'stockSearchStockLevels'
|| failedProcess === 'cartFetchCouriers'">
{{ contactTxt | capitalize }}
</p>
<p v-else-if="errorCount < 3">If the error continues, {{ contactTxt }}</p>
<p v-else>As the error has continued, {{ contactTxt }}</p>
<p>
<b>
01234 567890
<br />
Open from 00:00 to 07:00
</b>
</p>
<p>Advising of what you were doing when the error occurred.</p>
</div>
<div class="modal-footer danger-modal-headerfooter">
<a v-if="failedProcess === 'appGetAccount'" ref="logoutButton" class="btn btn-primary" :class="logoutButtClicked" #click="logoutClicked = true" href="/site/logout">
<span v-if="!logoutClicked" id="logoutButtonLabel">Logout</span>
<span v-else id="logoutSpinner">
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
Logging out
</span>
</a>
<router-link v-else-if="failedProcess === 'fetchOrderReportDetails'" to="/review" tag="button"
ref="existOrdersButton" class="btn btn-primary" type="button" data-dismiss="modal" #click.native="closeButton">
Return to existing orders
</router-link>
<button v-else-if="errorCount < 3 && (failedProcess !== 'productsFetchProducts' && failedProcess !== 'existOrderSearchProdOrders'
&& failedProcess !== 'stockSearchStockLevels' && failedProcess !== 'cartFetchCouriers')" ref="closeButton" class="btn btn-primary"
type="button" data-dismiss="modal" #click="closeButton">
Close
</button>
<router-link v-else to="/" tag="button" ref="homeButton" class="btn btn-primary" type="button" data-dismiss="modal" #click="closeButton">
Return to homepage
</router-link>
</div>
</div>
</div>
</div>
</template>
<script>
import * as params from '../params';
export default {
name: "ErrorModal",
data() {
return {
contactTxt: 'please contact us on:',
errorCount: 0,
failedProcess: '',
}
},
mounted() {
VueEvent.$on('show-error-modal', (failedProcess) => {
if (this.failedProcess !== failedProcess) {
this.errorCount = 0;
}
this.failedProcess = failedProcess;
$('#errorModal').modal('show').on('shown.bs.modal', this.focus);
});
},
methods: {
focus() {
if (this.failedProcess === 'appGetAccount') {
this.$refs.logoutButton.focus();
} else if (this.failedProcess === 'fetchOrderReportDetails') {
this.$refs.existOrdersButton.$el.focus();
} else if (this.errorCount < 3 && this.failedProcess !== 'productsFetchProducts') {
this.$refs.closeButton.focus();
} else {
this.$refs.homeButton.$el.focus();
}
},
}
}
</script>`enter code here`
I've tried using v-if before and I also had similar problems and the best solution I found was, instead of using v-if/v-else-if/v-else, use v-show instead to perform conditional rendering.
Also, as the Vue.js doc says:
Generally speaking, v-if has higher toggle costs while v-show has higher initial render costs. So prefer v-show if you need to toggle something very often, and prefer v-if if the condition is unlikely to change at runtime.

is there similar to standalone in vueJS

I'm asking if we have similar attribute as standalone in vuejs.
I want to add items in certifications.
Here is the button add :
<l-button #click="Add()"><i class="fa fa-plus"> </i></l-button>
The add function:
Add() {
this.certifications.push( item);
this.newItemAdded = true
},
<div v-for="(item,index) in certifications">
<fg-input type="text" required
:label="$t('candidate.certification.title')"
:placeholder="$t('candidate.certification.title')"
:disabled="disableIt && !newItemAdded ">
</fg-input>
</div>
My problem is that when i add new item, the previous input also is enabled.
I want to know if there is somathing similar to standalone( like angular) in vuejs.
You must use the index and length of certifications
<div v-for="(item,index) in certifications">
<fg-input type="text" required
:label="$t('candidate.certification.title')"
:placeholder="$t('candidate.certification.title')"
:disabled="(index+1!==certifications.length)">
</fg-input>
</div>
and when you need edit button:
data() {
return {
certifications: [],
editableIndex: null
}
},
methods: {
Add() {
...
},
Edit(index) {
this.editableIndex = index
},
}
}
and in template
<template>
<div>
<div v-for="(item,index) in certifications">
<fg-input type="text" required
:label="$t('candidate.certification.title')"
:placeholder="$t('candidate.certification.title')"
:disabled="(index+1!==certifications.length&&editableIndex===null) || editableIndex===index">
</fg-input>
<l-button #click="Edit(index)"><i class="fa fa-pen"> </i></l-button>
</div>
<l-button #click="Add()"><i class="fa fa-plus"> </i></l-button>
</div>
</template>

Why still adding even with validation form?

When I click the button on my modal with an empty field on my input its give me an undefined value on my console. And when I put a value on my input and click the button it is adding to my database. The problem is even the empty field or the undefined value are also adding to my database and the sweetalert is not working. I want to prevent the empty field adding to my database and prevent the undefined. Can somebody help me?
//start of method
checkForm: function(e) {
if (this.category_description) {
return true;
}
this.errors = [];
if (!this.category_description) {
this.errors.push('Category required.');
}
e.preventDefault();
},
addCategory : function() {
axios({
method : "POST",
url : this.urlRoot + "category/add_category.php",
data : {
description : this.category_description
}
}).then(function (response){
vm.checkForm(); //for FORM validation
vm.retrieveCategory();
console.log(response);
swal("Congrats!", " New category added!", "success");
vm.clearData();
}).catch(error => {
console.log(error.response);
});
},
//end of method
<form id="vue-app" #submit="checkForm">
<div class="modal" id="myModal" > <!-- start add modal -->
<div class="modal-dialog">
<div class="modal-content " style="height:auto">
<!-- Modal Header -->
<div class="modal-header">
<h4 class="modal-title"> Add Category </h4>
<button #click="clearData" type="button" class="close" data-dismiss="modal"><i class="fas fa-times"></i></button>
</div>
<!-- Modal body -->
<div class="modal-body">
<div class="form-group">
<div class="col-lg-12">
<input type="text" class="form-control" id="category_description" name="category_description" v-model="category_description" placeholder="Enter Description">
<p v-if="errors.length">
<span v-for="error in errors"> {{ error }} </span>
</p>
</div>
</div>
</div>
<!-- Modal footer -->
<div class="modal-footer">
<button type="submit"#click="category_description !== undefined ? addCategory : ''" class="btn btn-primary"> Add Category </button>
</div>
</div>
</div>
</div>
</form>
The easiest way to stop this is adding data check. And condition check at top of your method.category_description !== undefined. Btw, move your e.preventDefault() to top too.
First of all do this:
- <button type="submit" #click="category_description !== undefined ? addCategory : ''" class="btn btn-primary"> Add Category </button>
+ <button type="submit" #click.prevent="addCategory" class="btn btn-primary"> Add Category </button>
and then in addCategory:
addCategory() {
if (!this.category_description) {
return;
} else {
// do your stuff here
}
}
When you are clicking on Add Category button, it is triggering the addCategory along with your validation method.
The return value of validation method has no impact on triggering of addCategory.
This issue can be handled in following ways.
Call addCategory only when there is some valid data
<button type="submit" #click="category_description != undefined ? addCategory() : ''" class="btn btn-primary"> Add Category </button>
Call the validation method inside addCategory and then proceed.

How to set class to child element inside v-for loop

I need some help, I have v-for loop which outputs elements of array referenceDetailsDocumentsData, I need to check at the same time if the id of this element exists in another array documentsData, in this case I need to add custom class to child of this element.
<div class="loading-doc-item"
v-for="referenceDetails in referenceDetailsDocumentsData"
:key="referenceDetails.id">
<div class="loading-doc-show">
{{ referenceDetails.name }}
<span class="upload-status" v-if="checkUploadedDocuments(referenceDetails.id)">
<i class="fa fa-check-circle"></i>
</span>
<span class="upload-status" v-else>
<i class="fa fa-check"></i>
</span>
</div>
</div>
methods() {
checkUploadedDocuments(id) {
return this.documentsData.filter(item => item.id === id);
}
}
In my case, I am getting an error
Error in render: "TypeError: this.documentsData.filter is not a
function"
Your logic is wrong - the method checkUploadedDocuments will return Array but it must return Boolean.
<div class="loading-doc-item"
v-for="referenceDetails in referenceDetailsDocumentsData" :key="referenceDetails.id">
<div class="loading-doc-show">
{{ referenceDetails.name }}
<span class="upload-status">
<i class="fa"
:class="{documentsData && documentsData.length &&
documentsData.findIndex(item => item.id === referenceDetails.id) !== -1
? 'fa-check-circle' : 'fa-check'}"></i>
</span>
</div>
</div>