Why is my imported VueJS Component not displayed? - vue.js

I have the following Vue view named "PasswordResetView":
<template>
<v-content>
<v-card>
<v-card-title primary-title>
Passwort ändern
</v-card-title>
<v-card-text>
<v-text-field
id="password"
label="Passwort"
name="password"
prepend-icon="mdi-lock"
type="password"
/>
<v-text-field
id="passwordRepeated"
label="Passwort wiederholen"
name="passwordRepeated"
prepend-icon="mdi-lock"
type="password"
/>
<v-text-field
id="mail"
label="E-Mail"
name="mail"
prepend-icon="mdi-lock"
type="text"
/>
</v-card-text>
</v-card>
</v-content>
</template>
<script>
import axios from "axios";
export default {
name: "passwordreset",
data() {
return {
password: "",
passwordRepeated: "",
mail: "",
errormessage: "",
};
},
methods: {
changePassword() {
let payload = {mail: this.mail, password:this.password, passwordRepeated: this.passwordRepeated};
axios({
method: "post",
url: "/api/anonymous/register/pwreset",
data: payload,
}).then(() => {
this.$props.passwortresetkey = "good"
})
},
}
};
</script>
<style scoped/>
The view is imported by another vue component "PasswordReset" as following:
<template>
<div>
<PasswordReset v-if="pwresetkey === 'good'"></PasswordReset>
<div v-else>
<v-card>
<v-card-title primary-title>
Passwort ändern
</v-card-title>
<v-card-text>
Leider ist der Link ungültig.
</v-card-text>
</v-card>
</div>
</div>
</template>
<script>
import PasswordReset from "../../../components/anon/PasswordReset";
export default {
name:"passwordreset",
components: PasswordReset
};
</script>
The corresponding router:
{
path: "/pwreset",
name: "pwreset",
meta: {
requiresDisponent: false,
requiresRecurring: false,
requiresOneTime: false,
requiresAnon: true
},
component: () => import("#/views/recurring/account/PasswordReset"),
props: true
},
However, when I start the application, only the content from "PasswordReset" is shown (the v-card), but not the input fields.
Also, in the component "PasswordReset" it says that export default is ununsed.
Why is this marked as unused and the view not imported?

From vuejs docs:
If you use kebab-case
Vue.component('my-component-name', { /* ... */ })
When defining a component with kebab-case, you must also use kebab-case when referencing its custom element, such as in .
if you use PascalCase
Vue.component('MyComponentName', { /* ... */ })
When defining a component with PascalCase, you can use either case when referencing its custom element. That means both and are acceptable. Note, however, that only kebab-case names are valid directly in the DOM (i.e. non-string templates).

Try changing your password reset component like so:
<script>
import PasswordReset from "../../../components/anon/PasswordReset";
export default {
name:"passwordreset",
components: {PasswordReset}
};
</script>
VueJS Component Registration

Related

Can you extend a parent template in the child using Vue.js and Nuxt.js?

For example, I would like to have in the parent:
<template>
<v-layout column justify-center align-center>
<v-form id="myForm">
<v-text-field v-model="formData.firstName" label="first name" />
<v-text-field v-model="formData.lastName" label="last name" />
<!-- SOME TAG/MARKER HERE -->
</v-form>
</v-layout>
</template>
<script>
export default {
components: {},
data() {
return {
formData: {
firstName: '',
lastName: ''
},
}
}
}
</script>
And in the child:
<template>
<v-text-field v-model="formData.age" label="age" />
</template>
<script>
export default {
extends: Parent,
components: {},
data() {
return {
formData: {
age: 0
},
}
}
}
</script>
So when the child is loaded, the page shows a form with first name, last name and age.
Is it possible to do this ? How ?
Thank you.

Get all input values from dynamic form in Vuejs

I have some reusable components:
TextField
Form
And a component where I import them both. I pass the TextField component as props to the Form. In this Form component I have a submit button which needs to get all the values from the passed TextField components. As far as I could read in the docs I could use the v-model to get the values. But for some reason I can't find how to get those values in my Form component. Maybe I am missing something and I hope someone can help me with it. I already took a look at this question: Get all Input values - Vuejs. However, this didn't solve my problem.
The TextField component looks like this:
<template>
<v-text-field
v-model="vModel"
:rules="rules"
:counter="counter"
:label="label"
:required="required"
:placeholder="placeholder"
:value="value"
></v-text-field>
</template>
<script>
export default {
name: "TextField",
props: {
rules: Array,
counter: Number,
label: String,
required: {
type: Boolean,
default: true
},
placeholder: String,
value: String
},
data: () => ({
vModel: '',
}),
};
</script>
The Form component looks like this:
<template>
<v-form>
<v-container>
<slot></slot>
<v-btn class="mr-4" #click="submit">Submit</v-btn>
</v-container>
</v-form>
</template>
<script>
export default {
methods: {
submit () {
// console.log form data
}
}
};
</script>
And the component where I import both components:
<template>
<Form>
<v-row>
<v-col cols="12" md="4">
<TextField :label="'Email address'" :vModel="email"/>
</v-col>
</v-row>
</Form>
</template>
<script>
import Form from "../../../components/Form/Form";
import TextField from "../../../components/Form/TextField";
export default {
components: {
Form,
TextField,
},
data: () => ({
email: '',
})
};
</script>
I also created a CodeSandBox.
Can anyone give me some advice on how I might get the v-model values from the TextField components inside the Form component? If it's not possible, or I might do this better in another way please let me know.
v-model is simply a shorthand to create two things:
a :value binding (passed as a prop to your component)
a #input event handler
Currently, the vModel variable in your TextField component may receive the value, but it does not send it back to the parent component.
You could try something like this:
TextField
<template>
<v-text-field
v-model="localValue"
:rules="rules"
:counter="counter"
:label="label"
:required="required"
:placeholder="placeholder"
></v-text-field>
</template>
<script>
export default {
name: "TextField",
props: {
rules: Array,
counter: Number,
label: String,
required: {
type: Boolean,
default: true
},
placeholder: String,
value: String
},
data: () => ({
localValue: '',
}),
created() {
this.localValue = this.value;
this.$watch('localValue', (value) => {
this.$emit('input', value);
}
}
};
</script>
Form
<template>
<v-form>
<v-container>
<slot></slot>
<v-btn class="mr-4" #click="submit">Submit</v-btn>
</v-container>
</v-form>
</template>
<script>
export default {
props: ['form'],
methods: {
submit () {
alert(JSON.stringify(this.form));
}
}
};
</script>
Your final component:
<template>
<Form :form="form">
<v-row>
<v-col cols="12" md="4">
<TextField :label="'Email address'" v-model="formvalentin#whatdafox.com"/>
</v-col>
</v-row>
</Form>
</template>
<script>
import Form from "../../../components/Form/Form";
import TextField from "../../../components/Form/TextField";
export default {
components: {
Form,
TextField,
},
data: () => ({
form: {
email: ''
}
})
};
</script>
More information on v-model: https://v2.vuejs.org/v2/guide/forms.html
Not exactly sure as to what you doing in your code, but to simplify the template and component with v-model would look something like the code below.
ContactUs.vue
<template>
<form method="POST"
autocomplete="off"
class="form--container relative box-col-center w-full"
name="contact"
action="/form/contact"
#submit.prevent="onSubmit">
<input class="form--field font-poppins w-full"
type="text"
name="name"
v-model="field.name"
placeholder="Your name"
autocomplete='name'>
<input class="form--field font-poppins w-full"
type="email"
id="email"
name="email"
v-model="field.email"
placeholder="Your email"
autocomplete='email'>
<textarea class="textarea form--field font-poppins w-full"
id="body"
name="body"
placeholder="I'd like to know about ..."
v-model="field.body"
rows="5">
</textarea>
<button type="submit"
#click.prevent="onSubmit()"
class="container--row container--center btn--purple btn--040 w-2/3 lg:w-full">
<span class="text--w-full uppercase">Submit</span>
</button>
</form>
</template>
<script>
export default {
name: 'ContactUs',
data() {
return {
fields:{
name: '',
email: '',
body: ''
},
}
},
methods: {
onSubmit() {
let vm = this;
return new Promise((resolve, reject) => {
axios.post('/forms/contact', vm.fields)
.then(response => {
resolve(response.data);
}).catch(err => {
reject(err.response);
});
});
},
}
}
</script>
If you are attempting to create a Form service class then it would almost the same, except you would abstract the form logic to that class.
FormService.js
export default class Form {
/**
* Create a new Form instance.
*
* #param {object} data
* #param type
*/
constructor(data) {
this.originalData = data;
for (let field in data) {
this[field] = data[field];
}
}
/**
* Submit the form.
*
* #param {string} requestType
* #param {string} url
*/
submit(requestType, url) {
return new Promise((resolve, reject) => {
axios[requestType](url, this.data())
.then(response => {
resolve(response.data);
}).catch(err => {
reject(err.response);
});
});
}
}
and then in your component, you would inject the form services and use the data
ContactUs.vue
import Form from '../services/FormService.js';
export default {
name: 'ContactUs',
data() {
return {
fields: new Form({
name: '',
email: '',
body: ''
}),
}
},
methods: {
onSubmit() {
let self = this;
self.form.post('/forms/contact')
.then(response => {
}).catch((err) => {
})
},
}

How do I edit vue data passed as a property?

I have a Vuex data store with an array of contacts. I display that array in ContactList.vue, where I have an "Edit" button that navigates to CreateEditContact.vue (I am passing in the contact as a prop named contactProp). All of this works, but as we all know, you can't edit a prop directly. I tried checking to see if the prop is populated when the template is created, and copying it to contact in data but it isn't working. What's the right way to do this?
ContactList.vue
<template>
<!-- ...redacted for brevity -->
<!-- I'm reusing the same .vue for creating new and editing contacts -->
<!-- edit contact button -->
<v-btn text
:to="{name: 'createEditContact',
params: {
action: 'edit',
id: contact.id,
contactProp: contact
}}">Edit</v-btn>
<!-- new contact button -->
<v-btn
:to="{ name: 'createEditContact', params: { action: 'create' } }"
outlined
rounded>New</v-btn>
</template>
CreateEditContact.vue
<template>
<div>
<h3>Create or Edit a Contact</h3>
<v-form #submit.prevent="saveContact">
<v-container>
<v-row>
<v-col>
<v-text-field label="Name" v-model="contact.name" />
</v-col>
<v-col>
<v-text-field label="Phone Number" v-model="contact.phone" />
</v-col>
<v-col>
<v-text-field label="Extension" v-model="contact.extension" />
</v-col>
<v-col>
<v-btn type="submit">Save</v-btn>
</v-col>
</v-row>
</v-container>
</v-form>
</div>
</template>
<script>
import axios from "axios";
const options = {
headers: { "Content-Type": "application/json" }
};
export default {
name: "CreateEditContact",
props: {
action: {
type: String,
required: true,
validator: value => ["create", "edit"].indexOf(value) !== -1
},
id: {
required: false
},
// contactProp gets set correctly when editing...
contactProp: {}
},
data() {
return {
// the empty contact (when creating a new contact)
contact: {
id: 0,
name: "",
phone: "",
extension: "",
fullString: "",
telephoneUrl: ""
}
};
},
methods: {
saveContact() {
// redacted for brevity
},
created() {
// when contactProp is populated, I need to use that...
// but contact is always empty when I try to edit one.
// this next line isn't doing what I think it should.
if (this.contactProp) this.contact = this.contactProp;
}
}
};
</script>

vue-i18n translation for validation error working only after form reset in vuetify form

I'm using form validation in application, I want my validation error message to be translated. It is getting translated only after reset form.
I have tried translation in computed property, and it's working when I do
computed as below, but error message is not disappearing after touched:
{
return [this.$t('LANGUAGE')]
}
In App Component
<template>
<div id="app">
<grid_Component/>
<div class="locale-changer" style="background: black">
<select v-model="$i18n.locale">
<option v-for="(lang, i) in lang" :key="`Lang${i}`" :value="lang">{{
lang }}
</option>
</select>
</div>
</div>
</template>
<script>
import form_Component from './components/form_Component.vue'
import form_Component from './components/form_Component.vue'
import i18n from './i18n'
export default {
data () {
return{
lang: ['GB', 'NO']
}
},
name: 'app',
components: {
form_Component,
},
}
</script>
GB.json file
{
"LANGUAGE": "English"
}
NO.json file
{
"LANGUAGE": "Norwegian"
}
form component
<template>
<v-form ref="form" v-model="valid" lazy-validation>
<v-text-field v-model="name" :counter="10" :rules="nameRules"
label="Name" required>
</v-text-field>
<v-btn :disabled="!valid" color="success" #click="validate">
Validate
</v-btn>
<v-btn color="error" #click="reset">
Reset Form
</v-btn>
<v-btn color="warning" #click="resetValidation">
Reset Validation
</v-btn>
</v-form>
</template>
<script>
export default {
data: () => ({
valid: true,
name: '',
}),
methods: {
validate () {
if (this.$refs.form.validate()) {
this.snackbar = true
}
},
reset () {
this.$refs.form.reset()
},
resetValidation () {
this.$refs.form.resetValidation()
}
},
computed: {
nameRules(){
return [v => !!v || this.$t('LANGUAGE')]
}
}
}
</script>

VueJS js how to show dynamic form

I'm new to vue.I have a vue which needs to receive and show different template models.
I've tried this (simulating dynamic injection of one input field):
<template>
<b-container v-if="show">
<b-row>
<b-col class="map-dialog" cols="12" sm="6" md="4" >
<h3>{{ title }}</h3>
<component v-bind:is="fields"></component>
<b-button v-on:click="hide">Close</b-button>
</b-col>
</b-row>
</b-container>
</template>
<script>
import Vue from 'vue'
export default {
props: {
show: Boolean,
},
data() {
return {
title: null,
fields: null,
}
},
mounted() {
this.fields = Vue.component('fields', {
template: '<b-form-input v-model="text1" type="text" placeholder="Enter your name"></b-form-input>'
})
},
}
This gives an error:
[Vue warn]: You are using the runtime-only build of Vue where the template
compiler is not available. Either pre-compile the templates into render
functions, or use the compiler-included build.
What to do?
Thanks to help from #Boussadjra Brahim, I found a solution using async components.
Here is the amended code:
<template>
<b-container v-if="show">
<b-row>
<b-col class="map-dialog" cols="12" sm="6" md="4" >
<h3>{{ title }}</h3>
<FormFields/>
<b-button v-on:click="hide">Close</b-button>
</b-col>
</b-row>
</b-container>
</template>
<script>
import Vue from 'vue/dist/vue.js'
export default {
props: {
show: Boolean,
},
data() {
return {
title: null,
fields: null,
}
},
mounted() {
Vue.component('FeatureFields', function (resolve, reject) {
resolve({
template: '<b-form-input type="text" placeholder="Enter your name"></b-form-input>'
})
});
},
}
I also needed to change import Vue from 'vue' to import Vue from 'vue/dist/vue.js so that it would compile the template.