vuejs $emit in confirm dialog invalid - vue.js

I tried to get the request sent by the child page from the parent page, but it was unsuccessful。
1.parent code
<do-more #onreloadtab="reloadTab" :selectFolder="selectFolder"></do-more>
methods: {
reloadTab:function(){
console.log('reload')
}
}
2.child code
methods: {
async delete (row) {
let that = this
await this.$confirm("Are you sure to delete?", "confirm")
.then((config) => {
that.$emit('onreloadtab')
return
})
.catch(() => {
});
}
why parent cannot get emit message?

You don't need to use a then method after using await. The then method is called after Promises but await returns the value inside of a Promise, rather than a Promise. So, try calling emit after the await statement without the then method block.

In order to catch an event in your parent, Your need created() here is how you log the event in your parent
<template>
<do-more :selectFolder="selectFolder"></do-more>
</template>
<script>
export default {
data(){
return{
}
},
created() {
reloadTab(event){
console.log(event)
}
}
}
</script>

Related

Vue3 Emit Event not triggering method in parent

After making an API call I want to stop a loading spinner from displaying. Before calling the child component I set the this.showLoader property to true. This displays the spinner graphic. However once the API call has been made the graphic does not disapear. The updateLoader method never gets called.
child.vue
export default {
methods: {
fetchData() {
fetch(url, options)
.then((response) => response.json())
.then(this.$emit('hideLoaderEvent', false));
}
}
}
parent.vue
<template>
<MyComponent #hideLoaderEvent="updateLoader" />
</template>
export default {
data() {
return {
showLoader: false,
},
methods: {
updateLoader() {
this.showLoader = false;
}
}
}

asyncData() or fetch() does not work async, but in mounted it works correctly

I'm enough. I spent a few hours, but cant figure out how it works. My code works in SPA by the mounted() hook, but I migrate to nuxt now and faced with problems.
I'm trying to get data from store by asyncData()
async asyncData({store}) {
console.log("start getting schools")
const schools = await store.dispatch('GET_SCHOOLS_FROM_API').then((schools) => {
console.log(schools)
})
console.log(schools + " schools")
return schools
},
or fetch()
async fetch({store}) {
const sch = await store.dispatch('GET_SCHOOLS_FROM_API')
this.schools = store.SCHOOLS; //SCHOOLS is a getter in store
});
},
but it does not wait for dispatch to complete and returns undefind.
store:
async GET_SCHOOLS_FROM_API({ commit }) {
return axios.get('http://localhost:3000/schools').then((schools) => {
commit('SET_SCHOOLS_TO_STATE', schools.data)
return schools;
}).catch((error) => {
console.log(error);
return error;
})
}
does somebody have an idea where I am wrong?
The problem is that you are intersecting the Promise with an additional then block, when you add the await you are actually waiting for the result of the promise inserted in the then block, there you have a function that doesn't return anything, hence it returns undefined.
This can be easily fixed like:
async asyncData({ store }) {
console.log("start getting schools");
const schools = await store.dispatch('GET_SCHOOLS_FROM_API');
console.log(schools);
return { schools };
}
Another thing is that according to the example in the docs they return the value as an object, can you try that?
Ref https://nuxtjs.org/docs/2.x/features/data-fetching/
<template>
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.description }}</p>
</div>
</template>
<script>
export default {
async asyncData({ params, $http }) {
const post = await $http.$get(`https://api.nuxtjs.dev/posts/${params.id}`)
return { post } // <===== Like this
}
}
</script>
the thing was, that I did not remove data() from a component, and it was a mistake. After that, the code above works correctly

The prop object's property is undefined in refresh function

I use Vue.js and have a component. I pass a prop "request" to that component:
<adjustments-list
v-if="request"
:request="request"
/>
In the component I'm able to do this:
<text-input
:value="request.id"
/>
It works that is the value of "id" is displayed.
In props section of component:
props: {
request: Object
In mounted hook of component:
async mounted () {
await this.refresh()
},
In refresh function of component:
async refresh () {
console.log('this.request.id =', this.request.id)
if (this.request.id) {
const data = await requestApi.getRequestResultAdjustmentByReqId(this.request.id)
}
},
The this.request.id is undefined.
I'm not sure why.
If the request property is asynchronously available to the component then, you have to use combination of watchers like:
// adjustments-list component
new Vue({
props: {
request: Object
},
data() {
return {
apiData: null
}
},
watch: {
request(newValue, _oldValue) {
this.refresh(newValue);
}
},
mounted: function () {
// Do something here
},
methods: {
refresh (request) {
if (request.id) {
// Using promise instead of async-await
requestApi.getRequestResultAdjustmentByReqId(request.id)
.then(() => this.apiData = data);
}
}
}
});
Also, note that, mounted should be a plain old JS function and not an async function. That's the lifecycle method of the component supposed to behave in particular way.

VueJS: Computed Property Is Calculated Before Created in Component?

I have a component, which looks like this:
export default {
name: 'todos',
props: ['id'],
created () {
this.fetchData()
},
data() {
return {
}
},
computed: {
todos () {
return this.$store.state.todos[this.id]
}
},
methods: {
async fetchData () {
if (!this.$store.state.todos.hasOwnProperty(this.id)) {
await this.$store.dispatch('getToDos', this.id)
}
}
}
}
This is what's happening:
The component receives an id via props.
When the component loads I need to fetch some data based on the id
I have a created() hook from where I call a function fetchData() to fetch the data.
In methods, the fetchData() function dispatches an action to get the data. This gets and stores the data in Vuex store.
The computed property todos gets the data for this id.
The problem is that when the page first loads, the computed property todos shows up as undefined. If I change the page (client side) then the computed property gets the correct data from the store and displays it.
I am unable to understand why computed property doesn't update?
You could use following approach:
component.vue (and just render todoItem)
methods: {
async fetchData () {
const _this = this;
if (!this.$store.state.todos.hasOwnProperty(this.id)) {
this.$store.dispatch('getToDos', {id: this.id, callback: () => {
_this.todoItem = _this.$store.state.todos[_this.id]
}});
}
}
}
store.js
actions: {
getToDos: (context, payload) => {
// simulate fetching externally
setTimeout(() => {
context.commit("getToDos__", {newId: payload.id, task: "whatever" });
payload.callback();
}, 2000);
},
Base on here
When this hooks is called, the following have been set up: reactive data, computed properties, methods, and watchers. However, the mounting phase has not been started, and the $el property will not be available yet.
I think what might solve it is if you create a getter for todos.
So in your VueX Store add:
getters: {
todos(state) {
return state.todos;
}
};
And than in your computed use:
computed: {
todos () {
return this.$store.getters.todos[this.id]
}
}

mounted method is fired before data loaded - VueJS

I'm using Vue Resource to retrieve an images collection from a REST API. The request is sent in the created hook of my Vue component.
The problem is, I'm trying to access the retrieved data in the mounted hook, but the data isn't loaded.
I get this error in the console:
[Vue warn]: Error in mounted hook: "TypeError: Cannot read property 'forEach' of undefined"
Here is my component:
<script>
export default {
data() {
return { imgs : '' };
},
created() {
// the full url is declare in my main.js
this.imgs = this.$resource('acf/v3/pages/4');
this.imgs.query().then((response) => {
console.log('success', response);
this.imgs = response.data.acf.gallery;
}, (response) => {
console.log('erreur', response);
});
},
mounted() {
// get the ref="image" in my dom template
let imgs = this.$refs.image;
imgs.forEach((img) => {
// I do some stuff with imgs
});
}
}
</script>
If I wrap a setTimeout around the content of mounted, everything works fine.
So, I don't understand how I can wait for my data to load before the mounted hook is executed. Isn't this the role of the Vue lifecycle hooks?
Since the this.imgs.query() call is async, your mounted hook is being called before the then handler is setting this.imgs (which I'm assuming is being bound with v-for to an element in your template with an attribute ref="image"). So, even though the component has been mounted to the DOM, the $refs have not been set up yet.
I would make a method to "do some stuff with imgs" and then call that method in a $nextTick callback in the then handler of the async call. The callback passed to $nextTick will be "executed after the next DOM update cycle", meaning the $refs will be set up at that point.
<script>
export default {
data() {
return { imgs: '' };
},
created() {
// the full url is declare in my main.js
this.imgs = this.$resource('acf/v3/pages/4');
this.imgs.query().then((response) => {
console.log('success', response);
this.imgs = response.data.acf.gallery;
this.$nextTick(() => this.doStuffWithImgs());
}, (response) => {
console.log('erreur', response);
});
},
methods: {
doStuffWithImgs() {
// get the ref="image" in my dom template
let imgs = this.$refs.image;
imgs.forEach((img) => {
// I do some stuff with imgs
});
}
}
}
</script>
As shown in the Lifecycle Diagram of Vue instance. After Mounted Hook (which means we can access DOM), there is also beforeUpdate and updated hooks. These hooks can be used when data is changed. I think beforeUpdate or update hook can be used after getting data in created hook.
<script>
export default {
data() {
return { imgs : '' };
},
created() {
// the full url is declare in my main.js
this.imgs = this.$resource('acf/v3/pages/4');
this.imgs.query().then((response) => {
console.log('success', response);
this.imgs = response.data.acf.gallery;
}, (response) => {
console.log('erreur', response);
});
},
// here we can use beforeUpdate or updated hook instead of mounted
beforeUpdate() {
// get the ref="image" in my dom template
let imgs = this.$refs.image;
imgs.forEach((img) => {
// I do some stuff with imgs
});
}
}
I hope this helps.