How do you all recommend page reloads (i.e. if a User presses refresh page) when using variables within the URL?
I've generated a site statically with nuxt generate and am hosting it at http://www.wowrares.com/. The site generates links properly and is able to navigate to the zone when clicking on the sidebar nav link, but if I were to manually enter http://www.wowrares.com/zone/Ashenvale, it says Page Not Found
Looks like you've followed a broken link or entered a URL that doesn't exist on this site. with a link back to the homepage.
I have it setup so that the API calls are properly occurring when I click on a zone through the navigation, but I would like the above behavior to work properly so I'm assuming this will have to change.
<v-list-item
v-for="(zone, index) in zones"
:key="index"
nuxt
link
#click="mobsInfo(zone)"
>
<v-list-item-avatar>
<v-img :src="zone.image"></v-img>
</v-list-item-avatar>
<v-list-item-content>
<nuxt-link :to="{ name: 'zone-id', params: { id: zone.name } }">
<v-list-item-title class="grey--text subtitle-2">
{{ zone.name }}
</v-list-item-title>
</nuxt-link>
</v-list-item-content>
</v-list-item>
The method used to alter the state:
async mobsInfo(zone) {
this.$store.commit('setZone', zone)
await this.$store.dispatch('fetchMobs', zone)
}
When you go to the link https://wowrares.com/zone/Ashenvale the backend looks for a specific route, folder, file which is not existing in your case. I assume you have an index.html file under the root. That's why you got that message from the server.
Usually I use React or Angular and not that familiar with Vue but I guess hash router is the one what you are looking for. It helps the app identifying where to go once you copy and paste the link or just refresh the page.
Think about the following example, let's say you have the below link:
https://wowrares.com/#/zone/Ashenvale
Once you go the link then backend will ignore the rest of the URL part after the # character thus the original root html file will be opened where you need you handle the routes.
After a quick research I found a simple hash router for Vue in GitHub. Additionaly you can read further about fragment identifier here.
In Nuxt when you generate static website, it would not have an idea how to generate the dynamic routes, because there is lack of any context for it.
There is a way you can get around this issue, but I don't know if you are going to like it.. In nuxt-config.js there is a special property that handles this named generate and the usage is simple yet could get annoying if you have to do it constantly.
generate: {
routes() {
return [
'/posts/1',
'/posts/2',
'/posts/3',
]
}
}
You will be pleased to hear that there are 2 things that you can do to make your life easier, first you can make an http request to your API and return an array with those paths. Second you can even create a separate js file, where you export an array with those ids, either fetched from http request or written by hand (yikes) and them import it in nuxt-config.js and pass it to the routes() method.
Related
I am trying to update a store value before the router kicks in an navigates to the desired route.
This is my current code which is not working:
<NuxtLink :to="`/posts/${post.slug}`" #click="setPost(post)">
{{ post.title.rendered }}
</NuxtLink>
If I manually trigger the mutation by adding a button like so:
<button #click="setPost(post)">{{ post.title.rendered }}</button>
and then hit the NuxtLink, everything works as expected, but obviously this isn't correct.
How do I ensure that a store mutation is executed before going to the /posts/ page?
Thank you.
A link should be a navigation, not doing something else if following the semantics of HTML.
You can then have some logic when leaving or entering specific pages thanks to Vue router guards: https://router.vuejs.org/guide/advanced/navigation-guards.html
If you want to trigger a vue action (recommended over a vue mutation as stated in the documentation), you can totally call setPost(post) via a button and then, do a $router.push('/posts ....') with your variables as shown in the documentation: https://router.vuejs.org/guide/essentials/navigation.html#router-push-location-oncomplete-onabort
When I navigate to a form using vue-router by adding a link with a <router-link> element, the form does not work. When I hit submit I get a 404 response.
However, if I navigate to it using an <a> tag (triggering a page reload) then it works perfectly.
I suspect that this has to do with the page rendering as a SPA and for some reason not loading an important part of the form for Netlify unless the form page is reloaded? Why is this happening and is there an elegant solution to the problem? I could just replace all links to forms with tags but I'm sure that there is a better solution, I just don't understand the problem well enough to find it.
For context, I am using Nuxt. The forms are recognized by Netlify on the backend and can accept submission with the tag link so that is not the problem.
Since you're using Nuxt, you probably should go SSG/full static with target: 'static' (hostable on Netlify-like platforms) or with target: 'server' (hostable on Heroku-like platforms) but at any point, you should have ssr: true (default value). When you do have this, the biggest part is done.
In Nuxt, you should use <nuxt-link> rather than <router-link>, it works exactly the same (takes the same params etc) but it's more specific to Nuxt and SSR/SSG compatible while <router-link> is not. More details here: https://nuxtjs.org/docs/2.x/features/nuxt-components#the-nuxtlink-component
So, with all of this it should already work great. If it's not, I will gladly help you spot the issue if you have a github repo.
An alternative solution can be to use some form without any SSR dependency like Formspree: https://formspree.io/ (works fine with any SPA)
It works great, really simple. But I'd rather invite you to make a proper SSR form since you're using Nuxt.
PS: use <a> tags only for external links aka the ones which do not start with your domain name, nothing else. A follow of this kind of link is like a hard refresh and should be avoided at all costs.
EDIT: how to deploy by cleaning the cache.
EDIT on how to achieve a working form:
<template>
<div>
<form
netlify
action="/"
method="POST"
name="Contact"
>
<input type="hidden" name="form-name" value="Contact" />
<!-- ... -->
</form>
</div>
</template>
As told in the docs:
[...] inject a hidden input named form-name [...] and the hidden form-name input’s value matches the name attribute of form
Working fine. Could add a honeypot to it to make it even more secure!
I am using the Vue Router in my project. When i link to a route whose name does not exist, so for example:
<router-link :to="{ name: 'test-route' }"> link </router-link>
Vue complains in the console saying:
[vue-router] Route with name 'test-route' does not exist
But nothing happens to the user to indicate that something is wrong. The address bar gets changed to the root route (just /), but without the homepage actually showing, and my router.onError handler (which usually handles trying to navigate to lazy loaded components when you lose connection) doesn't fire in this case.
I want to show on screen that something is wrong, a redirection to my 404 page if nothing else.
My suggestion - don't allow a link to be clickable if it is not valid, you can make a condition inside the v-on directive.
v-on="{ to: <does link exist (access router)> ? { name: 'test-route' } : null}".
Might need some syntax fixing but that's the general idea.
Faced such a problem - I send data to the props of the /router-link/ tag, when I click on the link, I go to the article, it gets the data, everything works. Well, if you press the "back" button in the browser and then "forward" there will be no articles, there will be empty fields without data. How can this be avoided?
This is link to the article
<h3 class="database-article__title">
<router-link
:to="{name : 'article',params: {
id: item.id ,
type:item.type ,
name: item.name,
text: item.text,
author: item.author,
isFavorite: item.isFavorite
}}"> {{item.name}} </router-link>
</h3>
Little part of article-template.vue
<div class="content-type marketing">
{{$route.params.type}}
</div>
<h3 class="database-article__title">
{{$route.params.name}}
</h3>
<div class="database-article__text">
{{$route.params.text}}
</div>
Once again, the data transfer is good, when you click on the link, everything is displayed. The problem is that when clicking on the buttons in the browser "back" and "forward" - the browser history is not saved.
Does anyone know the solution to the problem, or where i can read how to solve it?
Thanks!
My guess is that your article route does not specify any of those params in its path. When you click the link, vue-router will remember the params object you specified in the <router-link> and will be accessible through $route.params in the article component.
However, when you click the browser back then forward buttons, the transition to the article route did not occur by clicking the <router-link> like it did the first time, and since those params were not included in the route's path, $route.params will be empty.
I'm guessing you're just trying to pass data from one route to another. If you want it to persist across history state changes (i.e. browser back/forward), then either:
The data needs to be included in the URL, either as params (e.g. /article/:id/:type etc, this needs to be specified upfront in the route's path) or in the query string (e.g. /article?id=1&type=foo). This isn't ideal for this situation.
(Recommended) Store the item object in such a way that it can be accessed by any route. Vuex is one way, but this may be overkill.
Realistically your URLs should only need to have the article's ID in it, like this /article/1. All the other stuff like type/name/etc don't belong in the URL. From the ID you should be able to fetch the full article object either from a REST API (XHR request), or obtain it from some in-memory data store abstraction (Vuex or anything else really).
I have a scenario where there are two major components on a page; a frame-like component that contains common functionality for many applications (including a bookmark/tab bar) and my actual application code.
Since the frame doesn't actually own the page that it's included on, it seems like it would be incorrect for it to define any routes, however the current page may define their own routes that may match one of those links. In that case, I'd like vue-router to handle those anchor clicks and navigate appropriately rather than doing a full page reload.
Here's a simplified template of what this looks like:
Frame (an external dependency for my app):
<Frame>
<TabStrip>
</TabStrip>
<slot></slot>
<Frame>
App1:
<Frame>
<App>You're looking at: {{ pageId }}!</App>
</Frame>
So when any of the app1 domain links are clicked from that tab strip, I want my route definitions in app1 to pick that up rather than it causing a page load. Since that component is owned by the frame, I don't have access to write <router-link> since links to many different apps may co-exist there.
Any thoughts?
Whoo, this is an old one! However, since this question was high in my search results when I was researching this problem, I figured I should answer it.
My use-case was similar to the one in the comments: I needed to capture normal <a> links within rendered v-html and parse them through the router (the app is rendering Markdown with a light modification that generates internal links in some cases).
Things to note about my solution:
I'm using Vue3, not Vue2; the biggest difference is that this is the new Vue3 composition-style single page component syntax, but it should be easy to backport to Vue2, if necessary, because the actual things it's doing are standard Vue.
I stripped out the markdown logic, because it doesn't have anything to do with this question.
Note the code comment! You will very likely need to design your own conditional logic for how to identify links that need to be routed vs. other links (e.g. if the application in the original question has same-origin links that aren't handled by the Vue app, then copy/pasting my solution as-is won't work).
<script setup>
import { useRouter } from "vue-router"
const router = useRouter()
const props = defineProps({
source: {
type: String,
required: true,
},
})
function handleRouteLink(event) {
const target = event.target
// IMPORTANT! This is where you need to make a decision that's appropriate
// for your application. In my case, all links using the same origin are
// guaranteed to be internal, so I simply use duck-typing for the
// properties I need and compare the origins. Logic is inverted because I
// prefer to exit early rather than nest all logic in a conditional (pure
// style choice; works fine either way, and a non-inverted conditional is
// arguably easier to read).
if (!target.pathname || !target.origin || target.origin != window.location.origin) {
return
}
// We've determined this is a link that should be routed, so cancel
// the event and push it onto the router!
event.preventDefault()
event.stopPropagation()
router.push(target.pathname)
}
</script>
<template>
<div v-html="source" #click="handleRouteLink"></div>
</template>