I'm new to Vue 3, and can't wrap my head around how things should be done.
I have a Vue installation in a folder, from which I want to make axios calls to an API eventually. Problem is, I'm stuck at getting the input field values. The login function definitely runs though.
Login.vue
<script setup>
function login(){
console.log(this.username);
}
</script>
<template>
<div class="greetings">
<h1 class="green">LOGIN</h1>
<form name="login_form" class="login_form" @submit.prevent="default">
<div class="row">
<div class="col1"><label for="username">Username: </label></div>
<div class="col2"><input id="username" v-model="username" type="text" /></div>
</div>
<div class="row">
<div class="col1"><label for="password">Password: </label></div>
<div class="col2"><input id="password" v-model="password" type="text" /></div>
</div>
<button type="submit" @click="login">
Login
</button>
</form>
</div>
</template>
This generates an error in the console saying "TypeError: Cannot read properties of undefined (reading 'username')".
What am I missing here? Please advise on how to make this code work "the Vue way".
Edit:
main.js
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import App from './App.vue'
import Home from './pages/Home.vue'
import Login from './pages/Login.vue'
import './assets/main.css'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/login',
name: 'Login',
component: Login
}
]
const router = createRouter({
history: createWebHistory(),
routes,
})
createApp(App).use(router).mount('#app')
Okay, I may have posited the question a bit too broadly (didn't know better).
I talked to my colleagues, and turns out that the main issue may have been the confusion between Vue 3's Options vs. Composition API "coding styles".
<script setup>
can only be used in Composition style, and when you use it, you must not use export default{}
only what would go inside it. Unfortunately, most code examples contain it.
The answer provided by Taha Khabouss also uses Composition API, import { reactive }
but without <script setup>
and with export default{}
. I'm sure it would work, but I also learned that I must use Options API instead in the project, so no <script setup>
and import { reactive }
for me.
There are many subtle differences between the two API styles, and unfortunately, even the official documentation is unclear about them (if you don't already know some basics of Vue). It also wasn't clear what the data(){}
or reactive({})
portion does (still isn't, but it works without it too).
Note, that there is no <script setup>
only <script>
with export default{}
, and this.username
is "automagically" understood in the context.
So here's how to get input value in Options API style:
<script>
export default {
methods: {
login(){
console.log(this.username);
}
}
}
</script>
<template>
<div class="greetings">
<h1 class="green">LOGIN</h1>
<form name="login_form" class="login_form" @submit.prevent="default">
<div class="row">
<div class="col1"><label for="username">Username: </label></div>
<div class="col2"><input id="username" v-model="username" type="text" /></div>
</div>
<div class="row">
<div class="col1"><label for="password">Password: </label></div>
<div class="col2"><input id="password" v-model="password" type="text" /></div>
</div>
<button type="submit" @click="login">
Login
</button>
</form>
</div>
</template>