I'm trying to do a check without vuevalidate. I just need to show this message below the input/field when I get an error or false.
I tried using :error-messages. But it returns me an error
Error: check failed for prop "errorMessages". Expected String, Array, got Function
Code
<v-text-field
class="ma-0 pa-0"
v-model="timeStart"
:counter="5"
:rules="rules_time"
label="Hora de início"
#blur="verificarHora"
:error-messages="messageErrors"
></v-text-field>
...
methos: {
...
verificarHora(element){
if(!element.target.value.match(/^[0-9]+$/)){
this.messageErrors()
}
},
messageErrors(){
return 'erro';
},
...
}
I usually accomplish this behaviour in Vuetify by adding the rules parameter (see more here).
So, as an example, if your input value is not allowed to exceed 20 characters and only letters are allowed, you could write the following code:
<template>
<v-text-field
counter="20"
:rules="myRules"
/>
</template>
<script>
export default {
...
data: () => ({
myRules: [
input => input.length <= 20 || "Input exceeds 20 characters.",
input => /^[A-Za-zäÄöÖüÜß]*$/.test(input) || "Only letters are allowed."
]
})
...
}
</script>
Related
I have passowrd rule like this
passwordRule(value){
const pattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##\$%\^&\*])(?=.{8,})/;
return (
pattern.test(value) ||
"Min. 8 characters with at least one capital letter, a number and a special character."
);
}
which I am using currently in
<v-text-field
autocomplete="current-password"
:value="userPassword"
label="Enter password"
:append-icon="value ? 'mdi-eye' : 'mdi-eye-off'"
:type="value ? 'password' : 'text'"
:rules="[passwordRule]"
></v-text-field>
as it currently shows "Min. 8 characters with at least one capital letter, a number and a special character." as error message,
How can I achieve like if password doesn't have capital letter it should display only message like "Atleast 1 capital letter". and if password doesn't have a number it should display "a number is required"
Please guide me how can I achieve that?
Your current rule assumes that the password must contain only latin uppercase letters.
If it's OK, use uppercaseEn rule from code below. Otherwise it should be better to use uppercase rule.
<v-text-field
v-model="password"
:rules="[rules.uppercaseEn, rules.special, rules.number, rules.length]"
label="Password"
></v-text-field>
...
data () {
return {
password: '',
rules: {
uppercase: value => {
//For non-latin letters also
return (value && value.toLowerCase() !== value) || 'At least 1 uppercase letter'
},
uppercaseEn: value => {
//For latin letters only
return /[A-Z]/.test(value) || 'At least 1 uppercase letter (A-Z only)'
},
number: value => {
return /\d/.test(value) || 'At least 1 number'
},
special: value => {
return /[!##\$%\^&\*]/.test(value) || 'At least 1 special symbol'
},
length: value => {
return (value && value.length >= 8) || 'Min password length: 8 symbols'
}
},
}
}
Test this at CodePen.
I have a v-data-table from Vuetify in my Vue.js app.
The table has a column of computed values.
I wanna make that column sortable.
What do I have to do?
What I tried:
I was looking into the sort function of the v-data-table-header.
It offers: sort?: (a: any, b: any) => number.
However, when I define that function for my column the values in the column are still not sorted.
HTML:
<v-data-table
:headers='headers'
:items='items'
>
<template v-slot:item.complete='{ item }'>
<span v-if='!isComplete(item)' class='error--text'>not complete</span>
<span v-else>complete</span>
</template>
</v-data-table>
Script:
readonly headers: DataTableHeader[] = [
{
text: 'Completeness',
value: 'complete',
sort: (a, b) => {
console.log(a, b);
return 1;
}
},
];
items = [
{
name: "foo",
tasks: 3
},
{
name: "bar",
tasks: 42
}
]
isComplete(item: any): boolean {
return 12 <= item.tasks && item.tasks <= 50;
}
The order doesn't change when I enable sorting and the log says:
undefined undefined
undefined undefined
undefined undefined
...
What do I need to do to sort computed values?
I don't think you can sort computed data in a table unless the objects inside items array each have a field called complete with some value, because that's what the table is looking for to get the value (hence undefined).
I am sending a get request to a api where the values are inside a array.
I want to get multiple values simultaneously.
How can I do this other than using index to get specific key values?
For example below, I want every result of results.data.message.body.artist_list.[4].artist.artist_name but don't want to have to use index [4].
methods: {
fetchMusic(e) {
if (e.key === 'Enter') {
// eslint-disable-next-line no-undef
axios.get(' ... ', {
headers: {
'Access-Control-Allow-Origin': '*',
},
})
.then((response) => response).then(this.setResults);
}
},
setResults(results) {
this.artists = results.data.message.body.artist_list.[4].artist.artist_name;
this.artistname = results.data.message.body.artist_list[0].artist.artist_name;
},
},
};
</script>
Thanks for any inputs on my code
Here is an example on how to fetch an API and display it's info by looping on the items: https://codesandbox.io/s/lucid-currying-nsoo3?file=/src/App.vue
Basically, get the results (an array so), then loop on each iteration of this array and display the wished data accordingly with something like
<div v-for="result in fetchedResults" :key="result.id">
<p>
<span>Name: {{ result.username }}</span> ~
<span>email: {{ result.email }}</span>
</p>
</div>
Btw, don't forget the key, it's important. More info here about this point.
Official documentation's examples on how to loop on an array.
When below object is rendered I can do for example something like this:
<div v-for="(card, groupIndex) in cards" v-bind:key="card.id">
<div> {{cards[groupIndex].group.length}} </div>
</div>
This will give me the length of each group and render this in a div
With below object this will result in 2 divs of which the first will show 4
[
{
"id":"BdSxtZL8V4S576i2BTRs",
"group_name":"nameA",
"group":[{
"back":"blabla,
"delayed_till":{"nanoseconds":0,"seconds":1576729260},
"examples":[{
"answer":"blabla",
"example":"blabla"
}],
"front":"blabla"
},
{
"back":"blabla",
"delayed_till":{"nanoseconds":0,"seconds":1095337800},
"examples":[{
"answer":"blabla",
"example":"blabla"
}],
"front":"blabla"
},
{
"back":"blabla",
"delayed_till":{"nanoseconds":0,"seconds":1577219040},
"examples":[
],
"front":"blabla"
},
{
"back":"blabla",
"delayed_till":{"nanoseconds":0,"seconds":1577092680},
"examples":[{
"answer":"blabla",
"example":"blablao"
}],
"front":"blabla"
}]
},
{
"id":"UtKzLYBPygu6iWOb1KMt",
"group_name":"nameB",
"group":[
etc.etc.etc..............
]
}
]
I would like to be able to render the number of items per group for which the date has not been passed yet.
You can use your exact same logic here, and just use a function below and pass in the group which applies a filter to the object collection and uses the delayed_till.seconds property to determine the validity check, something like this:
<div v-for="(card, groupIndex) in cards" v-bind:key="card.id">
<div v-text="groupItemsNotDelayed(cards[groupIndex].group)"> </div>
</div>
Then make your function which performs the filter:
groupItemsNotDelayed(group) {
return group.filter((item) => item.delayed_till.seconds < Date.now()).length
}
By using Date.now() we can get the current time in UTC Epoch, and compare that against our item.delayed_till.seconds to determine if the delayed period has passed (it would have to be less than the current epoch timestamp).
Then we can just call .length on the filtered items to get the count.
"vee-validate": "^2.2.11",
"vue": "^2.5.16",
I need a simple rule, the rule should be that the input must be required,numeric and greater than 0.
So in this case, if I input 0 it validates correctly(return false), but if I input something like this 0.0 vv returns true. Even if I remove is_not:0, the result still the same.
<sui-input
type="text"
v-validate="'required|decimal|is_not:0'"
name="cellSize"
v-model="cellSize">
You could also create a custom rule, like follows.
created() {
this.$validator.extend(
'greaterThanZero',{
getMessage: field => field + ' needs to be > zero.',
validate: (value) => {
// value must be > zero
if (value > 0 ) return true;
return false;
}
});
},
then call the code on your field instance.
v-validate="'required|decimal|greaterThanZero'"
more on custom rules here:
https://vee-validate.logaretm.com/v2/guide/custom-rules.html#creating-a-custom-rule
or you could also use this following style (if you were going to add more than one rule for example). Here the code would be inserted in the area where you do your imports, i.e. directly after the script tag.
import { Validator } from 'vee-validate';
Validator.extend(
'greaterThanZero',
(value) => {
// value must be > zero
if (value > 0 ) return true;
return false;
}
);
let instance = new Validator({ greaterThanZeroField: 'greaterThanZero' });
you can now add a second rule to the style directly above using the following code:
instance.extend('greaterThan1Million', {
getMessage: field => field +' needs to be > 1,000,000',
validate: value => (value > 1000000 ? true : false)
});
instance.attach({
name: 'greaterThan1MillionField',
rules: 'greaterThan1Million'
});
again that second rule could be called as follows:
v-validate="'required|decimal|greaterThan1Million'"
I found this solution(to leave everything greater than 0)
<sui-input
type="text"
v-validate="{ required: true, regex: /^(?=.*[1-9])\d+(\.\d+)?$/ }"
name="cellSize"
v-model="cellSize">
</sui-input>
Did you try to use a regex to exclude 0 ?
Example:
<input v-validate="{ required: true, regex: /[1-9]*/ }">