Vue 3 class-based-component doesn't call hook method - vue-component

I'm trying to get a little bit famliar with vue 3.
I wrote a class based component and try to call the mounded() Lifecycle method.
But for some reasons it doesn't work. The documentation isn't helpfull at this point to me.
So any help would be nice.
Here is the class:
<template>
<div class="hello">
<Header />
<div class="container mrgnbtm">
<div class="row">
<div class="col-md-8">
<!--<CreateUser #createUser="userCreate($event)" />-->
</div>
<div class="col-md-4">
<!--<DisplayBoard :numberOfUsers="numberOfUsers" #getAllUsers="getAllUsers()" />-->
</div>
</div>
</div>
<div class="row mrgnbtm">
<Users v-if="users.length > 0" :users="users" />
</div>
</div>
</template>
<script lang="ts">
import { Options, Vue } from "vue-class-component";
import { userService } from "../services/UserService";
import Header from "./Header.vue";
import CreateUser from "./CreateUser.vue";
import DisplayBoard from "./DisplayBoard.vue";
import Users from "./Users.vue";
Vue.registerHooks(
['beforeRouteEnter',
'mounted']
)
#Options({
components: {
Header,
CreateUser,
DisplayBoard,
Users,
},
})
export default class Dashboard extends Vue {
users: any;
numberOfUsers = 0;
getAllUsers() {
userService.getAllUsers().then((response) => {
console.log("Call UserService");
this.users = response.json;
this.numberOfUsers = this.users;
});
}
userCreate(data: any) {
console.log("data:::", data);
userService.createUser(data).then((response) => {
console.log(response);
this.getAllUsers();
});
}
mounted() {
console.log("mounted");
this.getAllUsers();
}
}
</script>
In case that mounted() isn't called, users is allways null.
Thanks in advance

Thanks to #Toni19.
The error was, that users wasn't initialized.
So I changed this an now all is working as expected.
Thanks

Related

I am trying to get driver related to vehicle using vue js

I have shown vechicle data just I want to get driver data related to vehicle but unfortuntly i am getting error undefined please help me how can i show into draggablelist thank u ?
Controller
public function index(){
return $vehicles = Vehicle::with('driver')->get();
}
template view
<div class="row">
<div class="col-6">
<q-card-section>
<div class="tw-grid">
<div class="tw-col-span-6">
<DraggableList
v-model="api.drivers"
label-key="username"
:colors="colors"
/>
</div>
</div>
</q-card-section>
</div>
</div>
vue js
export default {
data () {
return {
api: {
vehicles: [],
drivers: []
}
}
},
mounted () {
this.fetchVehiclesDriver()
},
methods: {
fetchVehiclesDriver () {
this.$api.get(this.apiRoute('client.vector.driver', {
}))
.then(({ data }) => {
this.api.vehicles = data.vehicles
this.api.drivers = data.vehicles.driver
console.log(data.vehicles.driver) // undefined
})
}
}
}

Vue3 composition API and pinia | submit data then reload the data

I'm learning Vue 3 composition API and Pinia. I'm making a todo.
When I submit a todo data through Pinia, I can submit to the DB, but it won't re-render until reload the page.
Do I need to use 'watch' to watch the state todos:[] and execute fetchTodos()?
any good solution?
here both codes, hope someone can help me. Thank you in advance.
----- VUE -----
<script setup>
import { ref, onMounted } from 'vue'
import { storeToRefs } = from 'pinia'
import { useTodoStore } from '../store/todo'
const store = useTodoStore()
const { getTodos } = storeToRefs(store)
onMounted(() => {
store.fetchTodos()
})
const todo = ref('')
const initForm = () => {
todo.value = ''
}
// submit via Pinia
const onSubmitToPinia = () => {
const payload = {
todo: todo.value,
}
store.addTodoFromPinia(payload)
initForm()
store.fetchTodo()
}
</script>
<template>
<h4>TODO</h4>
<!-- form addTodo -->
<form class="row g-4">
<div class="col-auto">
<input
class="form-control"
v-model="newName"
type="text"
placeholder="todo">
</div>
<div>
<button
class="btn btn-primary"
type="button"
#click="onSubmitToPinia(payload)">
submit through pinia</button>
</div>
</form>
<!-- render data from pinia -->
<div class="todo"
v-for="getTodo in getTodoss.todo"
:key="getTodo.id">
<b class="ms-2">{{ getTodo.todo }}</b>
</div>
</template>
---- PINIA ----
import { defineStore } from 'pinia'
import axios from "axios"
export const useAboutStore = defineStore('todo',{
state: () => {
return {
todos: []
}
},
getters: {
getTodos(state) {
return state.todos
}
},
actions: {
async fetchTodos() {
try {
const data = await axios.get('http://localhost:5000/todo')
this.todos = data.data
}
catch (error) {
alert(error)
console.log(error)
}
},
addTodoFromPinia(payload) {
const path = 'http://localhost:5000/todo'
axios.post(path, payload)
}
},
})
You don't need to use storeToRefs to accomplish what you want nor do you need to watch the state of the store.
<template>
<div class="todo"
v-for="getTodo in store.todos"
:key="getTodo.id">
<b class="ms-2">{{ getTodo.todo }}</b>
</div>
</template>
If for any reason the vue complains that the array is empty put a v-if checking if the store.todos.length is != 0.
And also fix your typos.
If the problem persists show me your new code and I help you again.

Vue.js how can i loop throw an array to add components to the dom according to array items

I am making an app that communicate with an api and fetch data,home page changes every day so i can't just add static components to it,
i need to create it according to the data that comes from the api.
i have a component for the home page called Home.vue
this component can have one or more Carousels depending on the data that i'am fetching.
i also have Carousel.vue which is responsible about displaying images and it had it's own props.
the question is :
How to add component to the dom from loop
this is Home.vue where i am making the loop :
<template>
<div>
<!--I Need The Loop right here-->
</div>
</template>
<script>
export default {
components: {},
data() {
return {
page_content: [],
widgets: [],
}
},
created() {
this.getHomeContent();
},
methods:
{
getHomeContent() {
window.axios.get(window.main_urls["home-content"]).then(response => {
this.page_content = JSON.parse(JSON.stringify(response.data));
console.log(this.page_content);
for (let index in this.page_content) {
switch (this.page_content[index].type) {
// if type is banner
case 'banner':
switch (this.page_content[index].display) {
// if display is carousel
case 'carousel':
console.log('carousel')
// end if display is carousel
this.widgets.push({
'type': 'Carousel',
'images': this.page_content[index].items,
})
}
// end if type is banner
}
}
});
}
}
}
</script>
and this is Carousel.vue which i need to be imported when needed with passing props :
<template>
<div>
<div >
<VueSlickCarousel>
<div v-for="image in images">
<img src="{{img}}">
</div>
</VueSlickCarousel>
</div>
</div>
</template>
<script>
import VueSlickCarousel from 'vue-slick-carousel'
import 'vue-slick-carousel/dist/vue-slick-carousel.css'
import 'vue-slick-carousel/dist/vue-slick-carousel-theme.css'
export default
{
components: {VueSlickCarousel},
name:'Carousel',
props:[
'images'
],
methods:
{
}
}
</script>
how to add Carousel.vue component to Home.vue dynamically some thing like:
if(data.display == 'carousel')
{
<carousel images="data.images"></carousel>
}
Import the component to your Home.vue :
import Carousel from './Carousel.vue'
export default {
components: {Carousel},
}
Then loop in your template:
<carousel v-for="(widget,index) in widgets" :key="index" :images="widget.images"/>
Best to use a widget.id rather than index for the key prop
This is the correct answer !
<template>
<div>
<template v-for="widget in widgets">
<div v-if="widget.type == 'carousel'" :key="widget.type">
<carousel
:images="widget.images"
:arrows ="widget.arrows"
:dots = "widget.dots"
>
</carousel>
</div>
</template>
</div>
</template>
<script>
import Carousel from './widgets/Carousel.vue'
export default {
components: {Carousel},
data() {
return {
page_content: [],
widgets: [],
}
},
created() {
this.getHomeContent();
},
methods:
{
getHomeContent() {
window.axios.get(window.main_urls["home-content"]).then(response => {
this.page_content = JSON.parse(JSON.stringify(response.data));
console.log(this.page_content);
for (let index in this.page_content) {
switch (this.page_content[index].type) {
// if type is banner
case 'banner':
switch (this.page_content[index].display) {
// if display is carousel
case 'carousel':
console.log('carousel')
// end if display is carousel
this.widgets.push({
'type': 'carousel',
'arrows':true,
'dots':true,
'images': this.page_content[index].items,
})
}
// end if type is banner
}
}
});
}
}
}
</script>

Can't post data to firebase

I am getting an error when trying to post data to firebase. Any idea what I am doing wrong? I have looked at a few tutorials and the official docs but I can't figure out what I'm missing.
Error in v-on handler: "TypeError: Cannot read property 'rsvp' of undefined"
Here are all of the relevant files:
HomePage.vue
<template>
<div>
<div>
<div>
<h3>RSVP</h3>
</div>
<div>
<form v-on:submit.prevent="addRsvp">
<div class="form-group">
<label>Name:</label>
<input type="text" class="form-control" v-model="newRsvp.name"/>
</div>
<div class="form-group">
<label>Number of guests:</label>
<input type="number" class="form-control" v-model="newRsvp.guests"/>
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary" value="SUBMIT"/>
</div>
</form>
</div>
</div>
</div>
</template>
<script>
import { db } from '../config/db';
export default {
name: 'HomePage',
firebase: {
rsvp: db.ref('rsvp'),
},
data () {
return {
newRsvp: {
name: '',
guests: '',
},
}
},
methods: {
addRsvp() {
this.$firebaseRefs.rsvp.push({
name: this.newRsvp.name,
guests: this.newRsvp.guests,
})
this.newRsvp.name = '';
this.newRsvp.guests = '';
alert("Succeessfully added");
}
}
}
</script>
main.js
import Vue from 'vue'
import App from './App.vue'
import { firestorePlugin } from 'vuefire'
Vue.use(firestorePlugin)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
App.vue
<template>
<div id="app">
<HomePage />
</div>
</template>
<script>
import HomePage from './components/HomePage.vue'
export default {
name: 'app',
components: {
HomePage,
}
}
</script>
<style lang="css">
#import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
</style>
config.js
import Firebase from 'firebase'
const firebaseConfig = {
// my app config from firebase
};
const app = Firebase.initializeApp(firebaseConfig)
export const db = app.database()
Any help would be appreciated! Any help would be appreciated!
Since you do import { firestorePlugin } from 'vuefire', it means you are using the Firestore database and not the Realtime Database.
However, your vuefire code corresponds to the Realtime database, see https://vuefire.vuejs.org/vuefire/writing-data.html#updates-to-collection-and-documents
So I think that instead of
export default {
name: 'HomePage',
firebase: {
rsvp: db.ref('rsvp'),
},
//...
}
you should do
export default {
name: 'HomePage',
firestore: {
rsvp: db.collection('rsvp'),
},
//...
methods: {
addRsvp() {
this.$firebaseRefs.rsvp.add({
name: this.newRsvp.name,
guests: this.newRsvp.guests,
})
//....
}
}
}
since you use Firestore and not the Realtime Database.
Or it is the exact opposite: your database IS the Realtime database, and then you need to adapt your main.js as follows:
import Vue from 'vue'
import App from './App.vue'
import { rtdbPlugin } from 'vuefire'
Vue.use(rtdbPlugin)
new Vue({
render: h => h(App),
}).$mount('#app')
See the doc here: https://vuefire.vuejs.org/vuefire/binding-subscriptions.html#declarative-binding

Vuex state change does not trigger reactivity on the page

I'm making a captcha component using vue. I try to fetch the captcha when the component created. When I do this in a async manner, the page will not be reactive, although the state has already been updated. But I when do it in sync manner, everything is fine. So, I'm wondering why async manner won't work?
This works
<template>
<section>
<div class="captcha-container">
<div v-if="captcha" v-html="captcha.data"></div>
</div>
</section>
</template>
<script>
import { mapState, mapActions } from "Vuex";
export default {
created: function() {
this.$store.commit('setCaptcha', {id: 'xx', data:'Hi'});
},
computed: {
...mapState(["captcha"])
},
};
</script>
This does not work
<template>
<section>
<div class="captcha-container">
<div v-if="captcha" v-html="captcha.data"></div>
</div>
</section>
</template>
<script>
import { mapState, mapActions } from "Vuex";
export default {
created: function() {
setTimeout(() => {
this.$store.commit('setCaptcha', {id: 'xx', data:'Hi'});
}, 1000);
},
computed: {
...mapState(["captcha"])
},
};
</script>

Resources