input character limit and number range - vue.js

I have an input and I want only numbers to be entered in this input and also the value entered should be between 0 and 36.
I want to set a maximum of 2 characters, but I have no idea, can you help?
<input type="number" min="0" max="36" maxlength="2" v-model.number="hello">
<script>
export default {
data() {
hello:""
}
},
</script>

You can create watcher and check if entered value is lower then 0 or bigger then 36:
const app = Vue.createApp({
data() {
return {
hello: null
}
},
watch: {
hello(newVal, oldVal) {
if(!newVal) {
this.hello = ''
return
}
this.hello = newVal < 1 || newVal > 35 ? oldVal : newVal
}
},
methods: {
check(e) {
if (e.which < 48 || e.which > 57) e.preventDefault()
}
}
})
app.mount('#demo')
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<input type="number" v-model.number="hello" #keypress="check($event)">
</div>

Related

Search Turkish Character Problem on VueJs Bootstrap Vue Table

I have a problem. I used bootstrap vue table. And I have a search box. I have a yield as "Istanbul". It doesn't see it when I press i in lower case. It accepts a capital letter I. I tried toLocaleLowerCase() but didn't run.
I type "istanbul" in the search box, but it does not find it in the table. It finds it when you write it as "İstanbul".
This is my template and dataset:
<template>
<div>
<b-table striped hover :fields="fields" :items="cities"></b-table>
</div>
</template>
<script>
export default {
data() {
return {
cities : [
{key:1,city:'İstanbul'},
{key:2,city:'İzmir'},
{key:3,city:'Adana'},
],
cityCopyArray : [
{key:1,city:'İstanbul'},
{key:2,city:'İzmir'},
{key:3,city:'Adana'},
],
fields:["city"]
}
}
</script>
This is my input:
<input
:placeholder="'City Name"
:id="'cityNamr'"
v-model="citySearchSearch"></input>
This is my watch:
citySearchSearch: {
handler(val) {
this.cities = this.cityCopyArray.filter((city) => {
return this.converter(city.name).includes(this.converter(val))
})t
},
},
And I used this code as converter :
converter(text){
var trMap = {
'çÇ':'c',
'ğĞ':'g',
'şŞ':'s',
'üÜ':'u',
'ıİ':'i',
'öÖ':'o',
};
for(var key in trMap) {
text = text.replace(new RegExp('['+key+']','g'), trMap[key]);
}
return text.replace(/[^-a-zA-Z0-9\s]+/ig, '')
.replace(/\s/gi, "-")
.replace(/[-]+/gi, "-")
.toLowerCase();
},
You can compare Turkish characters using toLocaleUpperCase('tr-TR') like:
const firstWord = 'istanbul';
const secondWord = 'İstanbul';
// If firstWord contains secondWord, firstWordContainsSecondWord will be true otherwise false.
const firstWordContainsSecondWord = firstWord.toLocaleUpperCase('tr-TR').indexOf(secondWord.toLocaleUpperCase('tr-TR')) !== -1;
Simple example:
new Vue({
el: '#app',
data: {
firstWord: 'istanbul',
secondWord: 'İstanbul',
result: null,
},
watch: {
firstWord() {
this.contains();
},
secondWord() {
this.contains();
}
},
mounted() {
this.contains();
},
methods: {
contains() {
// If firstWord contains secondWord, result will be true otherwise false.
this.result = this.firstWord.toLocaleUpperCase('tr-TR').indexOf(this.secondWord.toLocaleUpperCase('tr-TR')) !== -1;
}
}
});
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>
<div id="app">
<input placeholder="firstWord" v-model="firstWord">
<input placeholder="secondWord" v-model="secondWord">
<br/><br/>
<div>
Result =>
<br/> {{ firstWord }} contains {{ secondWord }} : {{ result }}
</div>
</div>

VueJS set date value as Date instead of String

I need to change type of datepicker value and it should return value as type Date instead of String https://prnt.sc/r6vr3g. But i don't know how can i make it.
Can anyone pls help me?
Here is code:
<template>
<q-input
#focusin="onFocusIn"
:value="value"
#input="e => $emit('input', e.toString())"
#click="alert = true"
>
<q-dialog v-model="alert">
<q-date
:value="value" #input="onInput"
:mask="mask"
/>
</q-dialog>
<script>
import _ from 'lodash'
export default {
props: {
..props
},
data () {
return {
alert: false,
sValue: ''
}
},
..computed
methods: {
onInput (e) {
let dateObj = new Date(e)
this.$emit('input', dateObj)
this.alert = false
},
onFocusIn (e) {
e.target.blur()
}
}
}
</script>
<style type="text/css">
</style>
<div class="col">
<s-datetime-picker v-model="data.dateStart" label="Date Start" required />
{{ data.dateStart }}
</div>
Here is code for datepicker component and after that there si example of using this component.
I've edited code, because i changed component. Now i have another error, in input field it shows message 'Invalid Date' and in console i got this error "failed for prop "value". Expected String with value "Invalid Date", got Date"
Format your emitting object before emit
<template>
<q-datetime-picker
..more properties
:value="value"
#input="formatDate(e)"
/>
</template>
<script>
import _ from 'lodash'
export default {
props: {
...all properties
},
computed: {
sLabel () {
if (!this.required || _.isUndefined(this.label)) return this.label
return this.label + ' *'
},
sRules () {
if (!this.required) return this.rules
let rule = val => { if (val.length === 0) return 'This field is Required' }
if (_.isUndefined(this.rules)) return [ rule ]
return (_.cloneDeep(this.rules)).push(rule)
}
},
formatDate(val){
let dateObj = new Date(val);
this.$emit('input', dateObj);
}
}
</script>
<style type="text/css">
</style>
<div class="col">
<s-datetime-picker v-model="data.dateStart" label="Date Start" required />
{{ data.dateStart }}
</div>
Format your date according to your need in formatDate function.
Hope this helps you,
Just pass the value you are getting as string to new Date it will return a date object.
var dt = "2020-02-13T00:00"; // <-- this is the value you get from date picker
var dtObj = new Date(dt); // <-- this one is date type
Full Vue Code
<template>
<div id="app">
<input type="date" v-model="dateFromField">
<button :click="showDate()">Submit</button>
</div>
</template>
<script>
export default {
name: "App",
data: function() {
return {
dateFromField: Date
};
},
methods: {
showDate() {
console.log(this.dateFromField);
console.log(typeof this.dateFromField);
let newDate = new Date(this.dateFromField);
console.log("conversion");
console.log(newDate);
console.log(typeof newDate);
}
}
};
</script>

Passing Array as prop not received on the other component

I am trying to pass an array of objects as a prop to a component. The Array is being passed without an array. I am neither receiving any compilation error.
I tried actually looking on to the object tried some stuff. But it did not work
Here is the code:
CardRenderer.vue:
<template lang="html">
<div>
<b-container class="bv-example-row">
<b-row v-for="(row, i) of rows" v-bind:key="i">
<b-col v-for="(item, j) of row" v-bind:key="j" >
<!-- you card -->
<b-card
:title="item.title"
img-src="item.icon"
img-alt="Image"
img-top
tag="article"
style="max-width: 20rem;"
class="mb-2"
>
<b-card-text>
<h1>{{item.name}}</h1>
<pre>{{item.description}}</pre>
</b-card-text>
<b-button :href="'/dashboard/'+item.name" variant="primary">More</b-button>
</b-card>
</b-col>
</b-row>
</b-container>
</div>
</template>
<script lang="js">
export default {
name: 'CardRenderer',
props: {
renderData: {
type: Array,
required: true,
default: () => ([]),
}
},
data() {
return {
rows: null
}
},
mounted() {
const itemsPerRow = 3
let rowss = []
// eslint-disable-next-line
console.log(this.renderData)
let arr = this.renderData
for (let i = 0; i < arr.length; i += itemsPerRow) {
let row = []
for (let z = 0; z < itemsPerRow; z++) {
row.push(arr[z])
}
rowss.push(row)
}
this.rows = rowss
// eslint-disable-next-line
// console.log(this.rows)
},
methods: {
},
computed: {
// rows() {
// }
}
}
</script>
<style scoped>
</style>
Something.vue
<template lang="html">
<!-- <h1>Something</h1> -->
<CardRenderer :renderData=valObj />
</template>
<script lang="js">
import CardRenderer from './CardRenderer'
export default {
name: 'something',
components: {
CardRenderer
},
props: [],
data() {
return {
valObj: []
}
},
mounted() {
let key = this.findUrl()
let value = this.$store.getters.responseAPI.apps.filter((elem) => {
if(elem.name == key) return elem.apps
})
if (value && value.length > 0)
this.valObj = value[0].apps
//eslint-disable-next-line
console.log(this.valObj)
},
methods: {
findUrl() {
let url = window.location.pathname.split("/").slice(-1)[0];
return url
}
},
computed: {
}
}
</script>
<style scoped >
.something {
}
</style>
This is what i am sending as a prop.
This is what i receive on the component
There's a couple of issues here.
First, you should be using kebab-cased attribute names and quotes around the value...
<CardRenderer :render-data="valObj" />
The second issue is timing related. In your component, you calculate rows based on the initial renderData in the mounted hook but this will not update when the parent component alters valObj.
What you should do instead is use a computed property which will react to valObj / renderData changes.
For example
data () { return {} }, // removed rows from data
computed: {
rows () {
let itemsPerRow = 3
let rows = []
for (let i = 0; i < this.renderData.length; i += itemsPerRow) {
rows.push(this.renderData.slice(i, i + itemsPerRow))
}
return rows
}
}

Vue: v-model undefined or default/fallback

Is there anyway to set a default value to an input to the value of another input field in case it has been left empty.
Looks like I can't specify this in the data nor in the v-model attribute:
<template>
<div>
<input type="number" v-model="font1 || 14"> <!-- gives error -->
<input type="number" v-model="font2 || font1"> <!-- gives error -->
<input type="number" v-model="font3 || font1"> <!-- gives error -->
</div>
</template>
<script>
export default {
data() {
return {
font1: 14,
font2: this.font2 || this.font1, // this approach also gives error
font3: this.font3 || this.font1 // this approach also gives error
}
}
}
</script>
Any help is welcome.
Thanks.
There is probably 37 different ways of doing it.
The question is what is important, robustness, maintainability, ease of implementation, scalability etc.
Here is a solution that prioritizes ease of implementation. It relies on using #change and :value instead of the v-model magic.
This will leave font2 and font3 as null if they are not changed.
new Vue({
el: '#app',
data: {
font1: 14,
font2: null,
font3: null,
},
methods: {
isNumber(n) { return !isNaN(parseFloat(n)) && !isNaN(n - 0) }
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="number" v-model="font1">
<input type="number" #change="font2 = $event.target.value" :value="isNumber(font2)?font2:font1">
<input type="number" #change="font3 = $event.target.value" :value="isNumber(font3)?font3:font1">
<pre>{{ {font1:font1, font2:font2, font3:font3} }}</pre>
</div>
You will have to use a combination of v-model and computed properties' getters and setters to achieve what you want.
Declare an internal data store for the fonts, let's call the f1, f2, and f3. Give f1 your default value of 14:
data: function() {
return {
f1: 14,
f2: null,
f3: null,
};
}
Now, when the component is mounted, you will want to interpolate the values accordingly. This can be done in the vm.mounted() callback:
mounted: function() {
// f2 takes the value of f1, if itself is falsy
this.f2 = this.f2 || this.f1;
// f3 takes the value of f2, if itself is falsy
this.f3 = this.f3 || this.f2;
}
The last step is to setup your computed properties, so that whenever font1, font2, or font3 changes, they will update the internal font data store appropriately:
computed: {
font1: {
set: function(val) {
if (val)
this.f1 = val;
},
get: function() {
return this.f1;
}
},
font2: {
set: function(val) {
this.f2 = val || this.f1;
},
get: function() {
return this.f2;
}
},
font3: {
set: function(val) {
this.f3 = val || this.f2;
},
get: function() {
return this.f3;
}
}
}
See proof-of-concept below:
Vue.component('test', {
template: '#test',
data: function() {
return {
f1: 14,
f2: null,
f3: null,
};
},
mounted: function() {
this.f2 = this.f2 || this.f1;
this.f3 = this.f3 || this.f2;
},
computed: {
font1: {
set: function(val) {
if (val)
this.f1 = val;
},
get: function() {
return this.f1;
}
},
font2: {
set: function(val) {
this.f2 = val || this.f1;
},
get: function() {
return this.f2;
}
},
font3: {
set: function(val) {
this.f3 = val || this.f2;
},
get: function() {
return this.f3;
}
}
}
});
new Vue({ el: '#app' });
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<test />
</div>
<script type="text/x-template" id="test">
<div>
<input type="number" v-model.number="font1">
<input type="number" v-model.number="font2">
<input type="number" v-model.number="font3">
</div>
</script>
You could use a Boolean set to false for both input 1 and input 2 elements and update it to true when a value is entered.
new Vue({
el: '#app',
data: {
font1: 14,
font2: {
value: 14,
defined: false
},
font3: {
value: 14,
defined: false
}
},
methods: {
Chg(font) {
if (font.value.length) {
font.defined = true;
return;
}
font.value = this.font1;
}
},
watch: {
font1() {
if (this.font2.defined === false) this.font2.value = this.font1
if (this.font3.defined === false) this.font3.value = this.font1
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="number" v-model="font1">
<input type="number" v-model="font2.value" #input="Chg(font2)">
<input type="number" v-model="font3.value" #input="Chg(font3)">
</div>

Custom Vue Material md-Input how to get isDirty or isTouched

I would like to create my own CustomMdInput, with basic validation. I would like to implement a input that work that way:
I use a <fp-input v-model="test"></fp-input>, and It is important, that when this input is required, when someone clicked on it or typesomething (turns 'touched' or 'dirty' property), and next defocus this input and go to the another input, the previous one stays Invalid with all the validation, so i have something like this:
<template>
<div class="md-layout-item">
<md-field>
<label :for="id">Imię</label>
<md-input :name="id" :id="id" :required="required" v-model="value" :ref="id" #input="emitValue()"></md-input>
<span class="md-error">Imię jest obowiązkowe</span>
</md-field>
</div>
</template>
<script>
export default {
name: 'FpInput',
props: {
value: {
required: true
},
id: {
required: true,
type: String
},
required: {
default: false,
type: Boolean
}
},
methods: {
emitValue () {
this.$emit('input', this.$refs[this.id].value)
}
}
}
</script>
<style scoped>
</style>
But i don't know how to check if this input isDirty or isTouched, and how can i set Validity of this input to check isFormValid after submit
give you an example
const MyInput = {
template: '#myInput',
props: ['value'],
data () {
return {
inputValue: this.value,
dirty: false,
touched: false,
inValid: false
}
},
methods: {
validate () {
if(this.inputValue.length<5){
this.inValid = true
this.dirty = true
}else{
this.inValid = false
this.dirty = false
this.touched = false
}
},
emitValue() {
this.validate()
this.$emit('input', this.inputValue);
}
}
}
var app = new Vue({
el: '#app',
components: {MyInput},
data () {
return {
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<my-input value="5"></my-input>
</div>
<script type="text/x-template" id="myInput">
<div>
<input v-model="inputValue" #input="emitValue()" #touchstart="touched = true" #mousedown="touched = true"/>
<span v-show="(dirty || touched) && inValid">must be at least 5 letters</span>
<div>dirty:{{dirty}}</div>
<div>touched:{{touched}}</div>
<div>inValid:{{inValid}}</div>
</div>
</script>
give you a full example
const MyInput = {
template: '#myInput',
props: ['value'],
data () {
return {
inputValue: this.value,
dirty: false,
touched: false,
inValid: false
}
},
methods: {
validate () {
if(('' + this.inputValue).length<5){
this.inValid = true
this.dirty = true
}else{
this.inValid = false
this.dirty = false
this.touched = false
}
},
emitValue(e) {
this.validate()
this.$emit('input', this.inputValue);
}
},
created () {
this.inputValue = this.value;
this.validate();
this.dirty = false;
}
}
var app = new Vue({
el: '#app',
components: {MyInput},
data () {
return {
inputList: new Array(4).fill('').map(o=>({val:5}))
}
},
methods: {
submit () {
if(this.$refs.inputs.some(o=>o.inValid)){
alert('you have some input invalid')
}else{
alert('submit data...')
}
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<form #submit.prevent="submit">
<my-input ref="inputs" v-for="item in inputList" v-model="item.val"></my-input>
<button type="submit">submit</button>
</form>
</div>
<script type="text/x-template" id="myInput">
<div>
<input v-model="inputValue" #input="emitValue()" #touchstart="touched = true"/>
<span v-show="(dirty || touched) && inValid">must be at least 5 letters</span>
</div>
</script>