Vuejs not refreshing the component after redirection - vue.js

I have a form in one component. After the submit-ion i am redirecting the view to the list where new submit should display.
But is doesn't.
I have to refresh the page and then the change will appear.
How do I instruct the page to reload the content after it is updated
Currently, in order to change the route, I am using:
methods: {
submitMovie () {
movieService.submitMovie(this.newMovie)
.then( this.$router.push('/movies'))
.catch( e=> { this.errors.push(e) })
}

.then(() => { this.$router.push('/movies') })
Thanks Phill.
I was trying to solve this for about 2 days.
All it needed was a function inside next.
Why I still don't understand but I will research about the issue
Thanks Again

Related

Why am I getting a "cannot read properties of null reading ParentNode" error from vue-router?

In my Vue project I'm using vue-router. When I navigate away from a certain page I get a vague error and the router stops working. Clicking links updates the URL in the browser, but the app won't navigate to the respective pages.
The error is
TypeError: Cannot read properties of null (reading 'parentNode')
The page in question uses a watcher to update the route query parameters when the user changes filtering and sorting options. This way, when the page is refreshed/copied/bookmarked, the same options will be selected on their return.
watch(
() => route.query,
() => {
selectedAddresses.value = selectedAddressesQuery.value
selectedStatuses.value = selectedStatusesQuery.value
selectedSortOrder.value = selectedSortOrderQuery.value
},
{ deep: true }
)
watch(
() => [
selectedAddresses.value,
selectedStatuses.value,
selectedSortOrder.value,
],
async () => {
router.replace({
query: {
...route.query,
address: selectedAddresses.value,
sort: selectedSortORder.value,
status: selectedStatuses.value,
},
})
}
)
Why am I getting this error when I navigate away from the page?
The problem was the watcher was being triggered when navigating away from the page because the query gets cleared, technically changing it.
The solution was to add a guard statement to the watch handler to check if we're still on the current page.
watch(
() => route.query,
() => {
// prevent triggering on page leave, which clears the query
if (route.name !== 'invoices') return
selectedAddresses.value = selectedAddressesQuery.value
selectedStatuses.value = selectedStatusesQuery.value
selectedSortOrder.value = selectedSortOrderQuery.value
},
{ deep: true }
)
This prevents the second watcher (that watches those values being set) from being triggered, which was trying to update the route that is no longer there.

How can I redirect to my home page after a state update in vue.js?

I am working on my first vue project, and am having an issue with the redirect that I want to have happen. My project is a basic to-do app. In my add todo component I have the following function that fires after I submit the form.
methods: {
addTodo:function(e) {
e.preventDefault()
let newTodo = {
title:this.title,
completed: false,
dueDate: new Date(this.date3)
}
console.log(newTodo)
this.$emit('add-todo', newTodo)
window.location.href = '/';
}
}
The event that is emitted then fires up the component tree until it reaches my app.vue file that fires the following method:
addTodo: function (newTodo) {
this.todos = [...this.todos, newTodo]
this.todos = this.todos.sort((a,b) => a.dueDate - b.dueDate)
}
Unfortunately the issue I am having is that my page redirects to my home page from the window.locatio.href method before my app can update state. I have also tried moving window.location.href='/' to the addTodo method in my app.vue file. However I am still facing the same problem. How can I redirect the user only once the new Todo is added to state?
use created(){} after the last},then add window.location.href="/";

Assert element exists after all XHR requests finished

I'm visiting a page which is fetching data Asynchronously (multiple XHR requests), and then asserting if a certain DOM element is visible/exists in the page.
So far I was only able to get the page and the data fetched with using cy.wait() either with an arbitrary time, or by aliasing the actual request, and using the promise-like syntax to make sure my cy.get() is done after the XHR response has completed.
Here is what doesn't work:
before(() => {
cy.login();
cy.server();
cy.route('/v0/real-properties/*').as('getRealPropertyDetails');
cy.visit('/real-properties/1/real-property-units-table');
});
beforeEach(() => {
Cypress.Cookies.preserveOnce('platform_session');
});
after(() => {
cy.clearCookies();
});
context('when viewport is below 1367', () => {
it('should be closed by default', () => {
cy.wait('#getRealPropertyDetails'); // the documentation says this is the way to go
sSizes.forEach((size) => {
cy.viewport(size[0], size[1]);
cy.get('.v-navigation-drawer--open.real-property-details-sidebar').should('not.exist');
});
});
Adding cy.wait(1000); in the before() or beforeEach() hooks also works, but this is not really an acceptable solution.
What works, but not sure if this is the way to do this (I would have to add this for every page, would be quite annoying) :
it('should be closed by default', () => {
cy.wait('#getRealPropertyDetails').then(() => {
sSizes.forEach((size) => {
cy.viewport(size[0], size[1]);
cy.get('.real-property-details-sidebar').should('not.be.visible');
});
});
});
I see that you have browser reloads there (beforeEach), which could potentially wipe out the route spy, but not sure why cy.wait().then would work. I would try switching from before to beforeEach though, creating things once is always trickier than letting them be created before each test

Is there a way to show a bootstrap-vue $toast feedback in beforeRouteEnter?

I have a component which loads a single user, so I use a vue-router guard to load data and in case of error redirect back to the users list component.
Is there a way to show a vue-bootstrap $toast? Usually I access $toast from this component, but obviously this does not exists yet in beforeRouteEnter.
I know I could manage in other ways (show the error in the page and use created(), or use vuex to keep the error and show it in the next page), but since I am using $toast everywhere I would like to keep consistency.
I have no ideas... if only I could access the root component I would have access to $toast but I can't see a way.
// userComponent
// ...
beforeRouteEnter(to, from, next) {
Promise.all([store.dispatch("users/fetchOne", { id: to.params.id } )])
.then(next)
.catch(() => {
// this.$root.$bvToast.toast("ERROR!!!", { variant: "danger" }); // can't do this :(
next("/users");
});
},
//...
You don't have access to this inside beforeRouteEnter. So you can do below :
next(vm => {
vm.$root.$bvToast.toast(...)
})

VueJS show splash screen after login (different landing page)

I have my VueJS application in which the user logins and depending on the role a specific landing page is pushed in the router.
Here the sample code or the store that handles login:
login({ dispatch, commit, state }, data) {
return API.post('api/account/login', data).then(({ data }) => {
if (data.success) {
var view = getView(data.data, state)
router.push(view);
}
return Promise.resolve(data);
});
},
So as you can see I can have different landing pages after login depending on user role. What I need to do is that no matter what landing page is I have to show a Splash screen (modal) after the user logins.
If its only one landing page for all I guess I could add something in the mount event of that view to show the modal, but because I have 9 different landing views I dont think the best way is to add the same code to the 9 views.
Is there a way I can do that in a propper or best practice way?
Thanks
If you have 9 different routes a user can be directed to, could you:
create a modal component
load it into these views/routes
open it when the route is mounted
This way the modal code is centralized in its own component, and can watch for a property change to appear.
As a followup on my comment: you can mount a separate Vue instance. You can do it with something like this:
createNewInstance: function(){
const splash = new Vue({
methods: {
closeHandler() {
return function() {
splash.$destroy();
splash.$el.remove();
};
}
},
render(h) {
return h(YourSplashComponent, {
mounted() {
setTimeout(this.closeHandler(), 3000)
}
});
}
}).$mount();
document.body.appendChild(splash.$el);
}
Just be sure to import and create a component on where YourSplashComponent is stated in the example.
Call the function right before you do trigger your route