How do I use Vuelidate with a custom validator? - vue.js

I’m trying to validate a 6 digit code with vuelidate. If this.validationcode equals false I want to show a validation error. I'm pretty new to vue so I'm not entirely sure where I'm going wrong. How do I get this to work?
The error I get is:
TypeError: Cannot read property '__isVuelidateAsyncVm' of undefined
JS
data() {
return {
validationcode: false,
validationRules: [
{ vcode: {
required,
numeric,
minLength: minLength(6),
maxLength: maxLength(6),
validCode () { return this.validationcode }
} },
],
};
},
I also tried it as an arrow function but it doesn't get the value properly from the looks of it.
validCode: () => {
console.log("the val code is " + this.validationcode)
return this.validationcode
}
HTML - v.formData.vcode.validCode - In the current front end view, this rule is triggered every time.
<div class=“form-group”>
<input
type=“text”
class=“form-control”
:class=“hasError(‘vcode’) ? ‘is-invalid’ : ‘’”
placeholder=“Enter your 6 digit code”
v-model=“formData.vcode”
/>
<div v-if=“hasError(‘vcode’)” class=“invalid-feedback”>
<div class=“error” v-if=“!$v.formData.vcode.required || !$v.formData.vcode.minLength || !$v.formData.vcode.maxLength”>
Enter your 6 digit code
</div>
<div class=“error” v-if=“!$v.formData.vcode.numeric”>
Should be a valid value.
</div>
<div class=“error” v-if=“!$v.formData.vcode.validCode”>
Code incorrect, please try again.
</div>
</div>
</div>
This is the method that I am assigning true/false to this.validationcode.
verifyNumber() {
var numbers = /^[0-9]+$/;
if (code.match(numbers)) {
// Twilio functions do not accept multipart/form-data
const data = new URLSearchParams();
data.append("phone_number", m.mobileNumber);
data.append("verification_code", code);
fetch("https://saffron-cheetah-1234.twil.io/check", {
method: "POST",
body: data,
})
.then((response) => response.json())
.then((json) => {
if (json.success) {
console.log("Successfully verified the token.");
this.validationcode = true;
} else {
this.validationcode = false;
console.log(this.validationcode);
console.log("Incorrect token.");
}
})
.catch((err) => {
console.log(err);
});
} else {
}
},

Related

How can I replace element in vue.js?

Here's my code:
window.onload = (event) => {
new Vue({
el: "#test",
mounted: function() {
this.fetch();
setInterval(this.fetch, 60000);
},
data: function() {
return {
tracker: {
serverInfo: {
servername: ""
}
}
}
},
methods: {
fetch() {
fetch("https://pt.dogi.us/ParaTrackerDynamic.php?ip=pug.jactf.com&port=29071&skin=JSON")
.then(response => response.json())
.then(data => {this.tracker = data});
},
}
})
}
<script src="https://unpkg.com/vue#2.4.4/dist/vue.min.js"></script>
<div id="test">
<span style="font-weight:bold">SERVER NAME:</span> {{tracker.serverInfo.servername}}
Using vue.js how can I replace ^4Re^5fresh^11-PUG output element to
<span style="font-weight:bold">SERVER NAME:</span> <span style="color:blue">Re</span><span style="color:cyan">fresh</span><span style="color:red">1-PUG</span>
where ^4 stands for <span style="color:blue">
etc
Final result should looks like this: image
Use this regex to split the string: https://regex101.com/r/G2s23R/1
const regex = /(\^\d)([^\^]+)/gm;
// Alternative syntax using RegExp constructor
// const regex = new RegExp('(\\^\\d)([^\\^]+)', 'gm')
const str = `^4Re^5fresh^11-PUG`;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}
Then, I believe that you can process the remaining tasks.

Live Search Component

I am fetching my data from external API link and I would like to filter them - live searching, so when I type a letter, the results that includes that letter will get filtered.
For now I am not able to do it and when I click into my input I just get all the results printed out and nothing is happening when I am trying to filter them.
This is my logic in script:
data() {
return {
result: "",
modal: false,
results: [],
filteredResults: [],
};
},
mounted() {
axios
.get("secretDataURL")
.then((response) => {
this.filteredResults = response.data;
})
.catch((error) => (this.filteredResults = console.log(error)))
.finally(() => console.log("Data successfully loaded"));
},
methods: {
filterResults() {
if (this.result.lenght == 0) {
this.filteredResults = this.results;
}
this.filteredResults = this.results.filter((result) => {
return result.toLowerCase().startsWith(this.result.toLowerCase());
});
},
setResult(result) {
this.result = result;
this.modal = false;
},
},
watch: {
state() {
this.filterResults();
},
}
And my template
<div #click="modal = false"></div>
<input
type="text"
v-model="result"
autocomplete="off"
#input="filterResults"
#focus="modal = true"
/>
<div v-if="filteredResults && modal">
<ul>
<li
v-for="(filteredResult, index) in filteredResults"
:key="index"
#click="setResult(filteredResult)"
>
{{ filteredResult.name }}
</li>
</ul>
</div>
How can I make it work, where my logic is failing ?
U get the data in hook mounted.
And then lost it.
Change this.filteredResults = response.data; to this.results = response.data;

Update image src on the fly with VueJS

I'm a new VueJS user, currently struggling with updating image src on the fly. This is what I've got:
Template:
<div v-for="place in places">
<img
v-bind:src="isPlacePrivate(place.data.place_is_private)"
v-on:click="setPlaceAsPrivate(place.data.place_is_private, place.data.place_id)"
>
</div>
<script>
export default {
data: function () {
return {
places: null,
}
},
mounted () {
this.username = this.$route.params.username;
axios.get('/api/' + this.username + '/places')
.then(response => {
this.places = response.data.data;
})
.catch(error => {
// show error
});
},
methods: {
isPlacePrivate: function (value) {
// If Place is private
if (value == 1) {
var src = '/icons/padlock-color.png'
} else {
var src = '/icons/padlock.png'
}
return src;
},
setPlaceAsPrivate: function (value, placeId) {
let data = {
isPrivate: value
};
axios.put('/api/' + this.username + '/places/' + placeId + '/edit', data)
.then(response => {
let newValue = response.data.data.private;
this.isPlacePrivate(newValue);
})
.catch(error => {
// show error
});
},
},
}
</script>
On a page load -> if a particular place is private it will show colored padlock icon or uncolored padlock if a place is public!
A user will be able to press on the padlock icon and change the value from public->private or private->public.
Everything is working fine but the padlock image is not updating on the fly when a user is clicking on it, I need to refresh a page to see changes! How to make it work?
I would suggest using a computed property so that it is reactive
Also according to your updates you are looping through an array of places so when you get your response from your axios call instead of just updating the icon I would try replacing the object in the array so I created the method called updatePlace() and I pass in the response object.
And change your places in the v-for to a computed property as well so that it is also reactive
Template:
<div v-for="place in placesArray" :key="index" v-if="places">
<img
v-bind:src="imgSrc"
v-on:click="setPlaceAsPrivate(place.data.place_is_private, place.data.place_id)"
v-if="imgSrc"
>
</div>
Script:
<script>
export default {
data() {
return {
src: '',
places: null
}
},
computed: {
imgSrc() {
return this.src
},
placesArray() {
return this.places
}
},
Methods: {
isPlacePrivate: function (value) {
// If Place is private
if (value == 1) {
this.src = '/icons/padlock-color.png'
} else {
this.src = '/icons/padlock.png'
}
},
setPlaceAsPrivate: function (value, placeId) {
let data = {
isPrivate: value
};
axios.put('/api/' + this.username + '/places/' + placeId + '/edit', data)
.then(response => {
console.log(response);
let newValue = response.data.data;
this.updatePlace(newValue);
})
.catch(error => {
console.log(error);
});
},
},
updatePlace(newPlace) {
const index = this.places.findIndex(place => place.id === newPlace.id)
this.places.splice(index, 1, place)
},
created() {
this.username = this.$route.params.username;
axios.get('/api/' + this.username + '/places')
.then(response => {
this.places = response.data.data;
})
.catch(error => {
// show error
});
}
}
</script>
Also make sure to move your mounted method to a created() method so that it is called before anything else is trying to render.
Apparently the problem is that you are calling the function and printing its return on the <img v-bind:src>, the isPlacePrivate function returns a value, so when you use this function within the setPlaceAsPrivate it returns the value only in scope of setPlaceAsPrivate.
The isPlacePrivate function does not modify any data value of the component, so the image always remains the same. You just need to set a data and manipulate its value in the isPlacePrivate function.
Template
<img
v-bind:src="bindSrc"
v-on:click="setPlaceAsPrivate(place.data.place_is_private, place.data.place_id)"
>
Script
<script>
export default {
data() {
return {
bindSrc: '/icons/padlock-color.png', // default img src value
... // your other values
}
},
Methods: {
isPlacePrivate: function (value) {
// If Place is private
if (value == 1) {
this.bindSrc = '/icons/padlock-color.png'
} else {
this.bindSrc = '/icons/padlock.png'
}
},
setPlaceAsPrivate: function (value, placeId) {
let data = {
isPrivate: value
};
axios.put('/api/' + this.username + '/places/' + placeId + '/edit', data)
.then(response => {
console.log(response);
let newValue = response.data.data.private;
this.isPlacePrivate(newValue);
})
.catch(error => {
console.log(error);
});
},
}
}
</script>

How to show if following or not Vue Js

I am trying to create a follow button, already wrote the code, so when the user follows, it goes straight to the database, the user id and the followed user id, in the component, i wrote a code that check if the user is already being followed to return true and false and then if following is true should display following and vice versa, but so far whenever the page loads it shows followed when true , if i go to another page and come back, it go backs to showing follow which is false, till i refresh the entire page again
<template>
<button v-bind:class="{followVendor:!following,followingVendor:following}"
type="button"
#click="followToggle"
class=" btn btn-sm btn-outline">
{{followText}}</button>
</template>
data:{
userFollowing:{},
following: false,
followText:'follow',
}
mounted(){
axios.get(`/api/user-following`,
{
headers: { Authorization: `Bearer ${this.user.access_token}` }
}).then(
response=>{
if (response.status === 200) {
this.userFollowing = response.data;
this.writer=true;
if (this.userFollowing.length > 0) {
if (this.userFollowing[0].user_id === this.user.id && this.userFollowing[0].vendorId === this.writterD.id) {
this.following = true;
this.followText = 'following';
}
}
}
}
)
}
methods: {
follow(params, name) {
let data = {
vendorName: name,
vendorId: params
};
if (this.auth) {
axios
.post("/api/user-following", JSON.parse(JSON.stringify(data)), {
headers: { Authorization: `Bearer ${this.token}` }
})
.then(response => {
if (response.status === 201) {
this.following = true;
this.followText = 'following';
this.$toasted.success("Successfully followed");
} else if (response.data === " Already following") {
this.$toasted.error("Already following");
} else {
this.$toasted.error("Error");
}
})
.catch(error => {
console.log(error);
});
} else {
this.$toasted.error("You have to log in to follow");
}
},
unFollow(){
let vendor = this.writterD.id;
let unfollow = confirm(`unfollow ${this.writterD.storeName}?`)
if (unfollow) {
axios.delete(`/api/user-following/${vendor}`,
{headers: {Authorization: `Bearer ${this.token}`}}).
then(response=>{
if (response.status === 200) {
this.following = false;
this.followText = 'follow';
this.$toasted.success("Successfully Unfollowed");
}else{
this.$toasted.error("Already Unfollowed");
}
})
}
},
followToggle(){
this.following? this.unFollow(): this.follow(this.writterD.id, this.writterD.storeName);
},
}
how can i make it always show the right one even if i don't reload the entire page please
What you need to do is force a rerender, the best way to do this is place a key on the component you need to update and then change the key when the info is updated. When the key is updated the data will update as the component will rerender. Like this:
<button :key="update" v-bind:class="{followVendor:!following,followingVendor:following}"
type="button"
#click="followToggle"
class=" btn btn-sm btn-outline">
{{followText}}</button>
...
data(){
return {
update: 0
}
}
...
this.followText = 'following';
this.update++
See here for a nice article on the topic:
https://michaelnthiessen.com/force-re-render

How to trigger a computed function after typing in input field in vue js?

Now I am using the following code. When I use #change it is not working?
<div class="col-md-3">
<div class="form-group">
<label>Longitude</label>
<input id="lngVillage"
type="text"
class="form-control"
placeholder="Longitude of Village"
name="lngVillage"
required=""
v-model="lng"
pattern="^[0-9]+\.[0-9][0-9][0-9][0-9]$"
maxlength="7"
oninvalid="this.setCustomValidity('Enter a valid Longitude')"
oninput="this.setCustomValidity('')">
</div>
</div>
<div v-if="isDisabled == false">
</div>
My computed function is
computed: {
isDisabled() {
if (this.lng.length > 5) {
axios.get('url')
.then(response => {
})
.catch(e => {
this.errors.push(e)
})
} else {
return true;
}
}
},
After typing in the input field I need to call isDisabled(). Please help me to have a solution.
There are more ways to approach this. You can solve it using the computed setter but I believe that watchers would be more appropriate here. Set a watch on the lng data using the following code.
computed: {
isDisabled() {
return (this.lng.length > 5) ? true : false
}
},
watch: {
lng: function(newValue, oldValue) {
if (newValue.length > 5 && this.lar.length > 5) {
this.executeCall();
}
},
lar: function(newValue, oldValue) {
if (newValue.length > 5 && this.lng.length > 5) {
this.executeCall();
}
}
},
methods: {
executeCall() {
axios
.get("url")
.then(response => {})
.catch(e => {
this.errors.push(e);
});
}
}
For more details please refer to https://v2.vuejs.org/v2/guide/computed.html#Watchers.