Phone number with dropdown country code vue js not working? - javascript

I am following this link: https://codepen.io/otuzel/pen/PooBoQW?editors=1011
but giving error Unknown custom element: - did you register the component correctly?
i have installed plugin --> npm install vue-tel-input
<div id="app">
<v-app id="inspire">
<v-form>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="3">
<vue-tel-input v-bind="bindProps" v-model="phone" v-on:country-changed="countryChanged"></vue-tel-input>
</v-col>
</v-row>
</v-container>
<v-btn
color="success"
#click="submit"
>
submit
</v-btn>
</v-form>
in script
<script>
export default {
data() {
return {
phone: null,
country: null,
bindProps: {
mode: "international",
placeholder: "Enter a phone number",
required: false,
enabledCountryCode: true,
enabledFlags: true,
autocomplete: "off",
name: "telephone",
maxLen: 25,
inputOptions: {
showDialCode: true
}
}
}
},
methods: {
countryChanged(country) {
this.country = '+' + country.dialCode
},
submit() {
console.log(this.phone)
console.log(this.country)
}
}
}
</script>
giving error Unknown custom element: - did you register the component correctly? Why it is happening?
i have installed plugin --> npm install vue-tel-input

Related

Can't validate v-text-field [migrating from older version of Vuetify]

I've been migrating an old project from last year since Entity Framework 5 was released. Since I'm also migrating the frontend from the previous version of Vuetify I worked with last year (from 2.2.11 to 2.4.0), I've encountered some issues that I've had to look up online and fix, but I got this sudden issue that I can't quite lay a finger on and haven't been able to find a similar issue with an answer.
I'm trying to validate a v-text-field inside a v-card to not save a record if the v-text-field length is less than 3 or greater than 50 characters. Despite that I've followed up the same code I used last year to validate my v-text-field, I get the following errors on chrome console:
The last 2 errors from this image pop up when you click save when it should show the validation message:
The code used in the component is the following.
For the Validation message that should pop below the description v-text-field in red:
VUE:
<template v-slot:top>
<v-toolbar flat>
<v-dialog v-model="dialog" max-width="500px">
<template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark class="mb-2" v-bind="attrs" v-on="on">New</v-btn>
</template>
<v-card>
<v-container>
<v-row>
<v-col cols="12" sm="12" md="12">
<v-text-field v-model="name" label="Name"></v-text-field>
</v-col>
<v-col cols="12" sm="12" md="12">
<v-text-field v-model="description" label="Description"></v-text-field>
</v-col>
<v-col cols="12" sm="12" md="12" v-show="valida">
<div class="red--text" v-for="v in validaMessage" :key="v" v-text="v">
</div>
</v-col>
</v-row>
</v-container>
</v-card>
</v-dialog>
</v-toolbar>
</template>
JAVASCRIPT:
<script>
import axios from 'axios'
export default {
data(){
return {
categories:[],
dialog: false,
dialogDelete: false,
headers: [
{ text: 'Options', value: 'actions', sortable: false, class:"primary--text" },
{ text: 'Name', value: 'name', class:"primary--text" },
{ text: 'Description', value: 'description', sortable: false, class:"primary--text" },
{ text: 'Status', value: 'status', sortable: false, class:"primary--text" },
],
search: '',
desserts: [],
editedIndex: -1,
editedItem: {
name: '',
calories: 0,
fat: 0,
carbs: 0,
protein: 0,
},
id: '',
name: '',
description: '',
valida: 0,
validaMessage:[]
}
},
methods: {
save () {
if (this.valida()){
return;
}
if (this.editedIndex > -1) {
//Code to update
}
else {
let me=this;
axios.post('api/Categories/Create',{
'name': me.name,
'description': me.description
}).then(function(response){
me.close();
me.list();
me.clean();
}).catch(function(error){
console.log(error);
});
}
},
valida(){
this.valida=0;
this.validaMessage=[];
if (this.name.length < 3 || this.name.length > 50){
this.validaMessage.push("The name must have between 3 and 50 characters.")
}
if (this.validaMessage.length){
this.valida=1;
}
return this.valida;
}
},
}
</script>
This is how it used to show like in my older version of the project:
I don't know if something that was changed in the Vuetify update version from 2.2.11 to 2.4.0 is interfering with the ability to implement this method inside the component to be able to show or hide the validation message. I'm trying to resolve this to avoid having to recur to 3rd party validation services like vee-validate or vuelidate. What could it be? Thank you for taking your time in reading this!
To sum up, these were the reasons for the errors:
There were a data property and a method with the same name - valida
v-btn component had a deleted method initialize provided to #click event.
And another tip as a bonus:
You have a v-col that spans to 12 columns: <v-col cols="12" sm="12" md="12">. Since it should span 12 columns on every screen size, there's really no need to define the columns span for small and medium breakpoints. So in this case it really should be only <v-col cols="12"> - will save you a little file size and loading time.

Vuetify dialog component to correctly delete item from parent component

I have a delete dialog component that when clicking Cancel or Delete nothing happens, not even errors. What am I missing to correctly delete or cancel
<template>
<v-dialog
v-bind="$attrs"
v-on="$listeners"
max-width="500px"
persistent
>
<v-card>
<v-card-title
class="headline"
>
{{ title }}
</v-card-title>
<v-card-text>
{{ message }}
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn
color="grey darken-1"
text
#click="$emit('closeDeleteDialog')"
>
Cancel
</v-btn>
<v-btn
color="primary darken-1"
text
#click="$emit('deleteItem')"
>
Delete
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
name: 'DeleteDialog',
props: {
title: {
type: String,
required: true
},
message: {
type: String,
default: ''
}
},
emits: ['closeDeleteDialog', 'deleteItem']
}
</script>
This is how I use my component:
<DeleteDialog
v-model="dialogDelete"
title="Delete location"
message="Are you sure you want to delete this location?"
/>
On the same view as where I import my component I have my methods.
export default {
components: {
DeleteDialog: () => import('#/components/Shared/DeleteDialog'),
},
data: () => ({
locationId: null,
dialog: false,
dialogDelete: false,
})
},
methods: {
deleteItem () {
this.$store.dispatch('deleteFirebaseDoc', { docId: this.locationId, collection: 'locations' })
this.locationId = null
this.dialogDelete = false
},
deleteItemConfirm (item) {
this.locationId = item.docId
},
closeDeleteDialog () {
this.dialogDelete = false
}
}
}
</script>
How can I correctly access my component to delete and item or cancel the dialog?
In the parent component you need to to listen to those events you emit
<DeleteDialog
v-model="dialogDelete"
title="Delete location"
message="Are you sure you want to delete this location?"
#close-delete-dialog="dialogDelete = false" // or call closeDeleteDialog ()
#delete-item="deleteItem()"
/>
I've never used camelCase for events emitting so I'd rather write it like $emit('close-delete-dialog') and $emit('delete-item')

How to get changed object field from vuetify form written in Vuex store

I have the following vue component and the values are loaded correctly from the store and displayed on the form. However if I change the value in a field it is not updated in the store. How can I make it such that whenever I change a value in the form it is also committed to the store?
<template>
<v-form v-model="valid" justify="center" class="mx-5" :disabled="show">
<v-row justify="center">
<H1 class="my-10">{{coin}}</H1>
</v-row>
<v-row>
<H3 class="my-5 mx-10">Add account</H3>
</v-row>
<v-row justify="space-around">
<v-text-field v-model="settings.key" :rules="[rules.required]" class="mx-12" label="API Key" />
</v-row>
</v-form>
</template>
<script>
import store from '../store'
export default {
name: "Settings",
store,
props: ["coin", "show"],
data: () => ({
valid: true,
rules: {
required: (value) => !!value || "Required.",
},
}),
computed: {
settings: {
get() { return store.getters.getSettingsBySymbol(this.coin) },
set(value) { store.commit("setSettingsBySymbol", value) },
}
},
}
</script>
==== EDIT =====
settings = {
coin: "hh",
key: "12345",
secret: "ajksjlkuT6ty",
}

how to pass variable between to vue file?

how to pass variable between to vue file ?
Hello, this is my file SendCode.vue has variable NewEmail which I want to use it in another file changePass.vue .
Is there anyway to sole this ?
Can someone help me ? Thanks
<template>
<v-app id="inspire">
<v-content>
<v-container class="fill-height" fluid>
<v-row align="center" justify="center">
<v-col cols="12" sm="8" md="4">
<v-card class="elevation-12">
<v-toolbar color="#ff8c00">
<v-toolbar-title>Glömt lösenord!</v-toolbar-title>
</v-toolbar>
<v-card-text>
Skrive ditt email.
<v-form>
<v-text-field v-model="email"
:error-messages="emailErrors"
label="E-mail"
required
#input="$v.email.$touch()"
#blur="$v.email.$touch()"></v-text-field>
</v-form>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn #click="getCode" color="primary">Skicka koden</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</v-content>
</v-app>
</template>
<script>
import axios from 'axios'
import router from '#/router.js'
import { validationMixin } from 'vuelidate'
import { required, email } from 'vuelidate/lib/validators'
export default {
mixins: [validationMixin],
validations: {
email: { required, email },
checkbox: {
checked(val) {
return val
}
}
},
props: {
source: String,
},
data: () => ({
email: ""
}),
methods: {
getCode: async function() {
let obj = {
"email": this.email,
};
let NewEmail = this.email;
let response = await this.$store.dispatch("getCode", obj);
//console.log(email)
//console.log(this.email)
if (response.status == 200) {
setTimeout(function() {
router.push({
path: 'ChangePass'
});
}, 500);
}
}
}
}
</script>
I want to use/pass variable NewEmail in this file from SendCode.vue file
I am new in vue and javascript so I do not know how to do this.
<template>
<v-app id="inspire">
<v-content>
<v-container class="fill-height" fluid>
<v-row align="center" justify="center">
<v-col cols="12" sm="8" md="4">
<v-card class="elevation-12">
<v-toolbar color="#ff8c00">
<v-toolbar-title>ÄNDRA LÖSENORDET</v-toolbar-title>
</v-toolbar>
<v-card-text>
<v-form>
<v-text-field :error="pass1Error" label="Koden" v-model="code1" type="password" />
<v-text-field :error="pass2Error" label="Lössenord" v-model="newPassword" type="password" />
<v-text-field :error="pass1Error" label="Samma Lössenord" v-model="rePassword" type="password" />
</v-form>
</v-card-text>
<v-alert v-if="passError" type="error">
password are not same
</v-alert>
<v-alert v-if="passwordChanged" type="success">
Password has been updated!
</v-alert>
<v-card-actions>
<v-spacer />
<v-btn #click="change" color="primary">Ändra</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</v-content>
</v-app>
</template>
<script>
import axios from 'axios'
import SendCode from "#/views/SendCode.vue";
import { validationMixin } from 'vuelidate'
import { required, email } from 'vuelidate/lib/validators'
export default {
mixins: [validationMixin],
validations: {
email: { required, email },
checkbox: {
checked(val) {
return val
}
}
},
props: {
source: String,
},
data: () => ({
code1: "",
newPassword: "",
rePassword: ""
}),
methods: {
change: async function() {
let obj = {
"code1": this.code1,
"newPassword": this.newPassword,
"rePassword": this.rePassword,
};
console.log(obj)
let response = await this.$store.dispatch("changePass", obj);
}
}
}
</script>
We recommend that you use Vuex (State management) for easy transfer and management of data through pages
Documentation:
https://vuex.vuejs.org/
If its only a variable with some value in it you can store it in localstorage i assume.
So in your function where you have the data you want to pass add:
localStorage.setItem('email', variable).
This works as a key value pair where email is the key and the variable is the data you want to access.
Then where you want to access the data you can use:
localStorage.getItem('email')
You probably don't want to do what you're trying to do, but would be better off with state management (vuex/pinia/genericVueStore), or, if you want to pass the data between components in the same app (same project), then the main method is $emits and $props. Check Vue documentation to see if that is what you want, which it probably is.
Nevertheless, within a Vue project, you can generally use Node/ES methods. So, the following would be fine, and would fit into the "composables" category if they weren't ".vue" files.
>> file1.vue
<script setup>
const oneData = "this_text"
export {oneData}
...
>> file2.vue
import {oneData} from "#/file1.vue"
console.log(oneData}
This would be an anti-pattern. Just follow the documentation for the standard things people try to accomplish.

Two vue components are sharing instance

I have a component named concepts, with its data and methods.
In another view I have two instance of this component (I'm using vuetify too):
// Index.vue
<template>
<v-card>
<v-toolbar>
<v-toolbar-title>Conceptos</v-toolbar-title>
</v-toolbar>
<v-tabs class="elevation-2" color="primary">
<v-tab>Ordinarios</v-tab>
<v-tab>Extraordinarios</v-tab>
<v-tab-item :key="1">
<concepts :is_extra="false" :key="1"></concepts>
</v-tab-item>
<v-tab-item :key="2">
<concepts :is_extra="true" :key="2"></concepts>
</v-tab-item>
</v-tabs>
</v-card>
</template>
<script>
import concepts from './Concepts.vue'
export default {
components: {
concepts,
},
data() {
return {
}
}
}
</script>
In the concepts component the is_extra property is used as a parameter, In the method created() of the vue instance, the function fetchAll retrieve from API the data correctly, the param is sent with the correct value:
// Concepts.vue
// this works correctly
created() {
const isExtra = this.is_extra //true or false depends of the property value
// GET /concepts?is_extra=true ...or false
this.server
.setParams({ is_extra: isExtra })
.fetchAll()
}
I have a method named upload (to upload a file) where I use this property again, but the value always is false, Always of the first component
...
// Concepts.vue
methods: {
upload() {
const isExtra = this.is_extra // always false
this.server.setParams({is_extra: isExtra}).upload()
}
}
The full Concepts.vue component here:
<template>
<v-data-table
:divider="true"
:headers="headers"
:items="concepts">
<template v-slot:top>
<v-toolbar flat color="white">
<v-spacer></v-spacer>
<template v-if="me.caps.canUploadCsv()">
<v-btn color="secondary" class="mr-2" dark>
Agregar concepto
</v-btn>
<input type="file" class="d-none" id="csv_file" #change="confirm" accept=".csv">
<v-btn #click="selectFile" :loading="uploading" color="green" dark>
<v-icon left>mdi-file-upload</v-icon> Cargar CSV
</v-btn>
</template>
</v-toolbar>
<v-dialog v-model="confirmDialog"
#click:outside="closeConfirm" #keydown="closeConfirm" max-width="320">
<v-card>
<v-card-title>
<span class="headline">Confirmar</span>
</v-card-title>
<v-card-text>
¿Desea continuar con la carga del archivo?
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn text #click="closeConfirm">
No
</v-btn>
<v-btn color="primary" dark #click="uploadFile">Si</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<template v-slot:item.description="{ item }">
<span :title="item.description">
{{ item.description.substr(0, 60) }}...
</span>
</template>
<template v-slot:item.amount_formated="{ item }">
$ {{ item.amount_formated }}
</template>
<template v-slot:item.iva_formated="{ item }">
$ {{ item.iva_formated }}
</template>
<template v-slot:item.total_formated="{ item }">
$ {{ item.total_formated }}
</template>
</v-data-table>
</template>
<script>
import { bus } from '../../app'
import User from '../../models/User'
import Concept from '../../models/Concept'
export default {
props: ['is_extra'],
data() {
return {
me: null,
headers: [
{ text: 'Clave', value: 'code' },
{ text: 'Categoría', value: 'category' },
{ text: 'Descripción', value: 'description' },
{ text: 'Unidad', value: 'unity' },
{ text: 'Total', value: 'total_formated', align: 'end' },
],
concepts: [],
model: null,
loaded: false,
inputFile: null,
confirmDialog: false,
uploading: false,
}
},
created() {
this.me = (new User()).getMe()
const params = this.$route.params
this.model = new Concept(params.companyId, params.contractId)
const isExtra = this.is_extra
this.model.server
.setParams({ is_extra: isExtra })
.fetchAll(this.onSuccess)
},
mounted() {
this.inputFile = document.getElementById('csv_file')
console.log('1', this)
},
methods: {
selectFile() {
if (this.uploading) {
return
}
this.inputFile.click()
},
confirm() {
this.confirmDialog = true
},
closeConfirm() {
this.inputFile.value = null
this.confirmDialog = false
},
uploadFile() {
console.log(this)
this.confirmDialog = false
this.uploading = true
const isExtra = this.is_extra
bus.$emit('snackbar', { color: 'info', text: 'Subiendo archivo...' })
this.model.server
.setParams({ is_extra: isExtra })
.upload(null, 'csv', this.inputFile, this.onSuccess)
},
onSuccess(resp) {
if (this.uploading) {
bus.$emit('snackbar', {
color: 'success', text: 'Conceptos actualizados correctamente'
})
}
if (this.inputFile) {
this.inputFile.value = null
}
this.uploading = false
this.concepts = resp.data
},
}
}
</script>
I put a console.log(this) inside of the created and upload methods, when I change the tab (vuetify tabs), in the first case I get:
VueComponent {_uid: 43, _isVue: true, ...} // created(), is_extra=false
VueComponent {_uid: 71, _isVue: true, ...} // created(), is_extra=true
but in the upload method (when upload the file) I get the same instance:
VueComponent {_uid: 43, _isVue: true, ...} // upload() is_extra=false
VueComponent {_uid: 43, _isVue: true, ...} // upload() is_extra=false
I added :key property but it didn't work.
Vue devtools show the two components with its correct data.
Before using vuetify tabs I already had the issue
Can someone help me please?

Categories