I got Vue errors rendering component - vue.js

I have a "vue-cli webpack" like the following :
src/components/Signin.vue:
<template>
...
<form v-on:submit.prevent="userSignIn">
...
<div class="field">
<p class="control has-icons-left has-icons-right">
<input
v-validate="'required|email'"
v-bind:class="{'is-danger': errors.has('name')}"
name="email"
v-model="form.email"
class="input"
id="email"
type="email"
placeholder="Email"
>
<span class="icon is-small is-left">
<i class="fa fa-envelope"></i>
</span>
<span class="icon is-small is-right">
<i class="fa fa-check"></i>
</span>
<span class="help is-danger" v-show="errors.has('email')">{{ errors.first('email') }}</span>
</p>
</div>
<div class="field">
<p class="control has-icons-left">
<input
v-validate="'required|min:5'"
v-bind:class="{'is-danger': errors.has('name')}"
name="password"
v-model="form.password"
class="input"
id="password"
type="password"
placeholder="Password"
>
<span class="icon is-small is-left">
<i class="fa fa-lock"></i>
</span>
<span class="help is-danger" v-show="errors.has('password')">{{ errors.first('password') }}</span>
</p>
</div>
<div class="field is-grouped">
<div class="control">
<button v-bind:disabled="errors.any()" class="button is-primary" type="submit" :disabled="loading">
Submit
</button>
</div>
</div>
</form>
...
</template>
<script>
...
export default {
data () {
return {
form: {
email: '',
password: '',
alert: false
}
}
},
computed: {
error () {
return this.$store.getters.getError
},
loading () {
return this.$store.getters.getLoading
}
},
watch: {
error (value) {
if (value) {
this.alert = true
}
},
alert (value) {
if (!value) {
this.$store.dispatch('setError', false)
}
},
methods: {
userSignIn () {
this.$store.dispatch('userSignIn', {email: this.email, password: this.password})
}
}
},
...
}
</script>
src/App.vue:
<template>
<main>
<router-view></router-view>
</main>
</template>
<style lang="sass">
#import "~bulma"
/* Your css for this file... */
</style>
src/main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import firebase from 'firebase'
import { store } from './store'
import VeeValidate from 'vee-validate'
import { firebaseConfig } from './config'
Vue.use(VeeValidate)
Vue.config.productionTip = false
firebase.initializeApp(firebaseConfig)
/* eslint-disable no-new */
const unsubscribe = firebase.auth()
.onAuthStateChanged((firebaseUser) => {
new Vue({
el: '#app',
router,
store,
render: h => h(App),
created () {
store.dispatch('autoSignIn', firebaseUser)
}
})
unsubscribe()
})
and I get two errors when I click the button :
Property or method "userSignIn" is not defined on the instance but
referenced during render. Make sure to declare reactive data
properties in the data option.
Signin.vue?d58e:24 Uncaught TypeError: _vm.userSignIn is not a
function

You've defined your methods inside your watch. Move them outside.
watch: {
error (value) {
if (value) {
this.alert = true
}
},
alert (value) {
if (!value) {
this.$store.dispatch('setError', false)
}
},
},
methods: {
userSignIn () {
this.$store.dispatch('userSignIn', {email: this.email, password: this.password})
}
}

Related

Submit form free when from errors in VueJs

I'm currently building a form in Vue and I'm having a hard time submitting the form when the form is free from error messages.
I'm currently fixed so that the errors show when they should but the goal is to change the page after pressing the submit button.
I would appreciate any tip that could help me :)
HTML
<template>
<form #submit.prevent="submitMessage">
<div class="form-control">
<label for="user-name">Name*</label>
<input id="user-name" name="user-name" type="text" v-model="userName" />
</div>
<div class="form-control">
<label for="age">Age</label>
<input id="age" name="age" type="number" v-model="userAge" />
</div>
<div class="form-control">
<label for="email">Email*</label>
<input id="email" name="email" type="email" v-model="email" />
</div>
<div class="form-control">
<label for="referrer">How did you hear about us?</label>
<select id="referrer" name="referrer" v-model="referrer">
<option value="google">Google</option>
<option value="wom">Word of mouth</option>
<option value="newspaper">Social Media</option>
<option value="other">Other</option>
</select>
</div>
<div class="form-control">
<label for="message">Message*</label>
<textarea rows="5" cols="50" id="message" name="message" v-model="message">Aa</textarea>
</div>
<div>
<button id="send" #click="sendForm()">Send Message</button>
</div>
<div class="errors">
<p v-if="errors.length > 0">
<b>Please correct the following error(s):</b>
<ul>
<li v-for="error in errors">{{ error }}</li>
</ul>
</p>
</div>
</form>
</template>
Vue
<script>
export default {
data() {
return {
userName: '',
userAge: null,
referrer: 'google',
email: '',
message: '',
errors: []
};
},
methods: {
submitMessage(e) {
this.userName = '';
this.userAge = null;
this.email = '';
this.referrer = 'google';
this.message = ''
},
sendForm() {
this.errors = [];
if (!this.userName) {
this.errors.push('Name is required');
}
if (!this.email) {
this.errors.push('Email is required');
} else if (!this.validEmail(this.email)) {
this.errors.push('Valid email required.');
}
if (!this.message) {
this.errors.push('Message is required');
}
if (!this.errors.length) {
return true;
}
if (this.errors.any()) {
this.$router.push('/thankyou');
}
},
validEmail: function (email) {
var re = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
}
}
</script>
Router.js
import {
createRouter,
createWebHistory
} from 'vue-router';
import HomeBeerSearch from './pages/beers/HomeBeerSearch.vue';
import BeerList from './pages/beers/BeerList.vue';
import CustomerSupport from './pages/contact/CustomerSupport.vue';
import ThankYou from './pages/contact/ThankYou.vue'
const router = createRouter({
history: createWebHistory(),
routes: [{
path: '/',
component: HomeBeerSearch
},
{
path: '/beers',
component: BeerList
},
{
path: '/support',
component: CustomerSupport
},
{
path: '/thankyou',
component: ThankYou
}
]
});
export default router
You can change the page by Vue router on SPA:
this.$router.push({ name: 'route name' })
or you can use raw JavaScript for external links:
window.location.href = 'http://www.google.com';
// there is no such function errors.any()
if (this.errors.any()) {
this.$router.push('/thankyou');
}
Your doing the navigation correctly but I think that the if statment logic is a little flawed. Try this instead:
// check if there are errors; if not go to the thank you page
if (!this.errors.length) {
this.$router.push('/thankyou');
}

VueJs Internal Server Error 500 when direct access url

I have created one login page using VuejS and when I'm accessing directly into the browser in server it gives me 500 error. but when i click from my website it works.
My Login.vue :
<template>
<div>
<div v-if="progress" class="progress-bg">
<div class="lds-ellipsis"><div></div><div></div><div></div><div></div></div>
</div>
<section class="container login">
<h1 class="login-title text-center">Login With Email</h1>
<form>
<p v-if="error">{{error}}</p>
<div class="form-group">
<input type="text" v-on:keyup="validate()" v-model="email" :disabled="disabled" class="edt-text" name="email" placeholder="Email">
<p v-if="emailError">{{ emailError}}</p>
</div>
<div class="form-group">
<input type="password" v-on:keyup="validate()" v-model="password" :disabled="disabled" class="edt-text" name="password" placeholder="Password">
<p v-if="passwordError">{{ passwordError}}</p>
</div>
<p class="label-forgot-password">Forgot Password?</p>
<div class="form-group">
<button type="button" :disabled="disabled" v-on:click="login" class="btn-login">Login</button>
</div>
</form>
<p class="text-center">Or Connect With</p>
<div class="row social-login-buttons text-center">
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
<button type="button" class="btn-google"><i class="fa fa-google"></i>Google</button>
</div>
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
<button type="button" class="btn-facebook"><i class="fa fa-facebook"></i>Facebook</button>
</div>
</div>
<div class="row">
<p class="text-center yellow-text margin-20">Don't you have an account?</p>
</div>
</section>
</div>
</template>
<script>
import axios from 'axios'
export default {
name:"Login",
data() {
return {
email:'',
password:'',
progress:false,
disabled:false,
emailError:null,
passwordError:null,
error:null,
}
},
methods: {
async login() {
this.error = ''
if (this.email && this.password && this.validEmail(this.email)) {
this.progress = true
this.disabled = true
let result = await axios.get(
`https://example.com/login/direct?email=${this.email}&password=${this.password}`
)
this.progress=false
this.disabled=false
if(result.status == "200"){
if(result.data['status'] == true) {
localStorage.setItem("user-token", JSON.stringify(result.data['token']))
this.$router.push({name:'Home'})
}
else {
this.error = "Invalid email address / password"
this.email=''
this.password=''
}
}
}
else {
this.validate()
}
},
validate() {
if (!this.email) {
this.emailError = 'Email address required.';
}
else if (!this.validEmail(this.email)) {
this.emailError = 'Enter valid email address.';
}
else{
this.emailError = null;
}
if (!this.password) {
this.passwordError = 'Password is required';
}
else{
this.passwordError = null;
}
},
validEmail(email) {
var re = /^(([^<>()[\]\\.,;:\s#"]+(\.[^<>()[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
},
}
};
</script>
My router/index.js :
import Vue from 'vue'
import VueRouter from 'vue-router'';
import ChatList from '../views/Chat/ChatList.vue'
import Chat from '../views/Chat/Chat.vue'
import Login from '../views/Login/Login.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/inbox',
name: 'ChatList',
component:ChatList
},
{
path: '/chat',
name: 'Chat',
component:Chat
},
{
path: '/login',
name: 'Login',
component:Login
},
]
const router = new VueRouter({
mode:'history',
routes
})
export default router
I'm able to access my login page when i click from my site which is linked via hyper link but when i directly hit the url into browser address bar it gives me Internal server error.

How to restrict user to enter only 30 characters in Vuejs?

<script>
export default {
name: "Register",
props: {
msg: String,
},
};
</script>
-------------main.js---------------
new Vue({
data:{
max:30,
text:''
},
render:h => h(App),
}).$mount('#app'
<template>
<div class="pop-up-mask">
{{ msg }}
<div class="pop-up">
<input type="text" class="input-section"
placeholder="Enter your Name" :maxlength="max" v-model="text" />
</div>
</template>
If the user tries to enter more than 30 characters, user should get an error message: you can only enter 30 characters. Try with above logic like maxlength="max" v-model="text"
I had done something similar in the past, so I built on that component (plus some research) to build this component that solves the problem.
<template>
<div class="input-max">
<div class="form-row">
<div class="col-md-8">
<input class="form-control" type="text" placeholder="Address"
v-model="address" #keyup="updateAddress">
</div>
<div class="col-md-4">
<span v-if="displayWarning" class="error-msg">* You can only enter {{ maxLength }} characters</span>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
address: '',
previousAddress: '',
maxLength: 30,
displayWarning: false
}
},
methods: {
updateAddress(event) {
let newValue = event.target.value;
if (newValue.length > this.maxLength) {
event.preventDefault()
this.address = this.previousAddress;
this.displayWarning = true;
}
else {
this.address = newValue;
this.previousAddress = newValue;
this.displayWarning = false;
}
}
}
}
</script>
<style scoped>
.error-msg {
color: red;
}
</style>

VueJS: components not rendering

I'm going through my first Vue tutorial and am a bit stuck. I've got an App.vue file, which I can see with the browser inspector extension is loading, a router index.js file, and login/signup forms. I can see the default Hello component.
I should be able to go to /login and /signup, but the components do not load. There are no console errors. Where do I begin troubleshooting?
App.Vue:
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style>
body {
background-color: #f7f7f7;
padding-top: 50px;
padding-bottom: 50px;
}
.is-danger {
color: #9f3a38;
}
</style>
Router index.js file:
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '#/components/HelloWorld'
import SignUpForm from '#/components/Auth/SignUpForm'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/signup',
component: SignUpForm
}
]
}))
SignUpForm.vue:
<template>
<div class="ui stackable three column centered grid container">
<div class="column">
<h2 class="ui dividing header">Sign Up, it's free!</h2>
<Notification
:message="notification.message"
:type="notification.type"
v-if="notification.message"
/>
<form class="ui form" #submit.prevent="signup">
<div class="field" :class="{ error: errors.has('name') }">
<label>Full Name</label>
<input type="text" name="name" v-model="name" v-validate="'required'" placeholder="Full name">
<span v-show="errors.has('name')" class="is-danger">{{ errors.first('name') }}</span>
</div>
<div class="field" :class="{ error: errors.has('username') }">
<label>Username</label>
<input type="text" name="username" :class="{'input': true, 'is-danger': errors.has('username') }" v-model="username" v-validate="'required'" placeholder="Username">
<span v-show="errors.has('username')" class="is-danger">{{ errors.first('username') }}</span>
</div>
<div class="field" :class="{ error: errors.has('email') }">
<label>Email</label>
<input type="email" name="email" :class="{'input': true, 'is-danger': errors.has('email') }" v-model="email" v-validate="'required|email'" placeholder="Email">
<span v-show="errors.has('email')" class="is-danger">{{ errors.first('email') }}</span>
</div>
<div class="field" :class="{ error: errors.has('password') }">
<label>Password</label>
<input type="password" name="password" :class="{'input': true, 'is-danger': errors.has('password') }" v-model="password" v-validate="'required'" placeholder="Password">
<span v-show="errors.has('password')" class="is-danger">{{ errors.first('password') }}</span>
</div>
<button class="fluid ui primary button" :disabled="!isFormValid">SIGN UP</button>
<div class="ui hidden divider"></div>
</form>
<div class="ui divider"></div>
<div class="ui column grid">
<div class="center aligned column">
<p>
Got an account? <router-link to="/login">Log In</router-link>
</p>
</div>
</div>
</div>
</div>
</template>
<script>
import Notification from '#/components/Notification'
export default {
name: 'SignUpForm',
components: {
Notification
},
data () {
return {
name: '',
username: '',
email: '',
password: '',
notification: {
message: '',
type: ''
}
}
},
computed: {
isFormValid () {
return Object.keys(this.fields).every(key => this.fields[key].valid)
}
},
beforeRouteEnter (to, from, next) {
const token = localStorage.getItem('tweetr-token')
return token ? next('/') : next()
},
methods: {
signup () {
axios// eslint-disable-line no-use-before-define
.post('/signup', {
name: this.name,
username: this.username,
email: this.email,
password: this.password
})
.then(response => {
// save token in localstorage
localStorage.setItem('tweetr-token', response.data.data.token)
// redirect to user home
this.$router.push('/')
})
.catch(error => {
// display error notification
this.notification = Object.assign({}, this.notification, {
message: error.response.data.message,
type: error.response.data.status
})
})
}
}
}
</script>
My main.js file:
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios'
import VeeValidate from 'vee-validate'
window.axios = axios
axios.defaults.baseURL = 'http://127.0.0.1:3333'
Vue.config.productionTip = false
Vue.use(VeeValidate)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
Your main Vue instance needs to mount itself to the #app element:
new Vue({
router
}).$mount('#app');
Here's a basic example with vue router. Codepen
Couple other things to try in main.js:
// render function
new Vue({
el: '#app',
router,
render: h => h(App)
})
// component
new Vue({
el: '#app',
router,
App
})
My mistake was router configuration. It was not allowing me to go to the proper route without a #. I needed to add mode:'history' to the new Router object.
Proper router configuration:
export default new Router({
mode: 'history',
routes: [
blahblahblah
]
})

Click-to-Edit text field with Vue

I am working on Vue js and having an issue editing a field. When I click on a field to edit it, all the editable fields become active. Here is my code.
export default {
props: ['profileHeight'],
data() {
return {
User: User,
isEditing: false,
form:{
name:'',
email: '',
},
};
},
mounted() {
},
methods: {
activateInEditMode() {
this.isEditing = true
},
deActivateInEditMode() {
this.isEditing = false
}
}
}
<span>Profile settings</span>
<p>Full name<span v-on:click="activateInEditMode" v-show="!isEditing">{{User.state.auth.name}}</span>
<span v-show="isEditing" >
<input v-model="form.name" type="text" class="form-control" >
</span>
</p>
<p>E-mail<span>{{User.state.auth.email}}</span>
<span v-show="isEditing" >
<input v-model="form.email" type="text" class="form-control" >
</span>
</p>
Try using focus and blur methods to show/hide form elements!
Hope this helps!
new Vue({
el: '#app',
data(){
return {
user : {
name: '',
email: ''
},
editField : ''
}
},
methods : {
focusField(name){
this.editField = name;
},
blurField(){
this.editField = '';
},
showField(name){
return (this.user[name] == '' || this.editField == name)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">
<h1>Profile settings</h1>
<label for="user-name">Full name</label>
<div class="field">
<span class="field-value" v-show="!showField('name')" #click="focusField('name')">{{user.name}}</span>
<input v-model="user.name" v-show="showField('name')" id="user-name" type="text" class="field-value form-control" #focus="focusField('name')" #blur="blurField">
</div>
<label for="user-email">Email address</label>
<div class="field">
<span class="field-value" v-show="!showField('email')" #click="focusField('email')">{{user.email}}</span>
<input v-model="user.email" v-show="showField('email')" type="email" class="field-value form-control" #focus="focusField('email')" #blur="blurField">
</div>
</div>
There are are dozens of ways to do this. I might recommend a component.
console.clear()
Vue.component("editable",{
props:["label", "value"],
template:`
<p>
{{label}}
<span #click="editing=true" v-show="!editing">
{{value}}
</span>
<span v-show="editing" >
<input :value="value"
#input="$emit('input', $event.target.value)"
#keydown.enter="editing=false"
type="text"
class="form-control" >
</span>
</p>
`,
data(){
return {
editing: false,
}
}
})
const User = {
name: 'bob',
email: 'bob#example.com'
}
new Vue({
el:"#app",
data() {
return {
form: User
};
},
})
<script src="https://unpkg.com/vue#2.2.6/dist/vue.js"></script>
<div id="app">
<span>Profile settings</span>
<editable label="Full name" v-model="form.name"></editable>
<editable label="E-mail" v-model="form.email"></editable>
<br>
{{form}}
</div>
I have written a component for this, I call it Click-to-Edit.
What it does:
Supports v-model
Saves changes on clicking elsewhere and on pressing Enter
ClickToEdit.vue:
<template>
<div>
<input type="text"
v-if="edit"
:value="valueLocal"
#blur.native="valueLocal = $event.target.value; edit = false; $emit('input', valueLocal);"
#keyup.enter.native="valueLocal = $event.target.value; edit = false; $emit('input', valueLocal);"
v-focus=""
/>
<p v-else="" #click="edit = true;">
{{valueLocal}}
</p>
</div>
</template>
<script>
export default {
props: ['value'],
data () {
return {
edit: false,
valueLocal: this.value
}
},
watch: {
value: function() {
this.valueLocal = this.value;
}
},
directives: {
focus: {
inserted (el) {
el.focus()
}
}
}
}
</script>