Add 404 page view outside <router-view> in Vue 3 - vue.js

I am working on a simple Vue-powered web app in which a list of projects is obtained as JSON from an API. I’m getting started with the Router and slots, and have gotten the following to work so far…
The app also features a header, and navigation menu. The navigation menu features links to the projects as retrieved from the API. Click on a project from the navigation menu send the user to website.com/projects/project1, the Vue Router matches website.com/projects/:slug. Based on matching the $route slug parameter, the project JSON is filtered and the currentProject is shown in the <router-view> section of the webpage (snippet from App.vue):
...
<router-view :currentProject="currentProject" v-slot="{ Component }">
<transition name="projectswitch" mode="out-in">
<component :is="Component" :key="$route.params.slug" />
</transition>
</router-view>
...
I would like to add a 404 page view, which does not include the header and navigation menu, when the user navigates to a non-existing route. I have made a simple template, PageNotFound.vue, that I would like to show as an independent page. Right now, it shows it inside the <router-view>, rather than rendering a whole new page, that includes only the template PageNotFound.vue.
How to handle this in terms of component architecture?
Thank you!

Related

Vue component communication between header component and components in the router-view

Im facing a problem for my VUE app, Im using the vue Router to navigate to my component
In my Header component I use router-link to navigate to a Home component
The problem is :
In my Header component I would like a checkBox (a boolean variable) that change the content of my Home component (rendered in the router-view) like a v-if that would check the boolean variable in the Header
Here is my App.vue template I was trying to solve the problem through emits but Im Kinda stuck for passing data inside a component (inside the router-view)
<template>
<div class="content">
<HeaderComponent #eventCheckBox="handleCheckBox" />
<router-view />
<FooterComponent />
</div>
Do you guys have already faced this issue, is there a way to do it the classic way or should I try plugins like Portal or Teleport ?
Portal and Teleport are the same, just a different name (teleport in Vue3, being the official name).
As of the rest of the question, this explains it very well: https://stackoverflow.com/a/49702934/8816585
Mainly, you need to see if you need to use a store like Pinia (recommended one) and Vuex. Most of the time, you could use a parent/child relationship. Here is another article explaining when you would need something like that: https://markus.oberlehner.net/blog/should-i-store-this-data-in-vuex/#alternatives-to-storing-data-in-vuex
In Vue3, you could even not use a store and rely solely on the singleton pattern + composables (again, a lot of articles are available for that one).
TLDR: use your Vue devtools and inspect the state flowing.
If you need more, reach for more powerful tools.

Vue Router - Nested Routes Not Working as Expected

I'm trying to create a simple nested routing:
App (root component, main navigation)
Topic1 (sub-navigation)
Topic1/Sub
Topic2
My demo on Codesandbox has the following issues:
1. When navigating from /topic1 to /topic1/sub, I expected the content from topic1 to show up and the content from topic1/sub to be shown below, like this:
However, Topic 1 does not show anymore.
2. How can I avoid showing "App" twice?
I know I've added path: "/topic1", component: App, but only because without it the routing did not work at all. As per the comments in router/index.js:
component: App, // Option 1 - Navigation to topic1,2 and /sub works (why?) 'App' is displayed twice
component: Topic1, // Option 2 - Navigation to /sub does not work but at least 'App' is only displayed once
I seem to be missing something essential - thank you already for any answers.
App component is showing twice because it is mounted twice. First it is mounted in main.js when you create the app. Then it is mounted in router-view as the route component. To avoid this, you shouldn't use the App component in router, instead make another Layout component where you define the page layout to be used by the vue-router. Also, this will allow the scenario where, while having a single entry point for your app (App), you can define different layouts for different routes, if needed.
Regarding the first question, the content of Topic1 component is not shown when navigating to Sub route, because it is wrapped in router-view. router-view displays only the content of the current route component. Avoid placing any content in router-view as it will be replaced on route navigation. This will work:
<h1>Topic1</h1>
<h2>Topic1 Content</h2>
<p>
<router-link to="/topic1/Sub">/topic1/sub</router-link>
</p>
<router-view> </router-view>
Here is the working codesandbox.
Also I refactored a bit your router index.js.

Vue.js Vue3 different Templating with for sub components

I have a Vue 3 project,
Most of my Components use the Template in App.vue (My understanding goes that this is Similar to a "Master Page in .net core with the completeness inheriting the style and layout from the App.vue. In my case, the app.vue will have the dashboard layout (top and sides) and then I will load the restricted components in the content section.
However, I cannot seem to figure out how to make public-facing pages, such as login and register not reference the Dashboard template at all as they are not logged in, but still allow some Vue functionality. Post for login, errors returned, etc. How can I split them or have multiple Master App.vue templates for different users, based on their role or logged-in status.
your help is greatly appricated.
In App.vue you can use vue js built in component tag to render dynamic layouts
<component :is="activeLayout"></component>
you can bind it to a computed property and return the appropriate component to bind for different scenarios

Modal window in nuxt architecture

Before I was working with Vue2JS and I used to creating modal as just component within App.vue root component for example:
<template>
<div>
<app-navbar></app-navbar>
<router-view></router-view>
<app-footer></app-footer>
<my-modal v-if="someBoolean"></my-modal>
</div>
</template>
Now basing on some custom events or Vuex storage I was able to change someBoolean and trigger when I want modal to be visible.
Since in Nuxt we don't have such thing as root App.vue component I'm wondering how to achieve same as above but with Nuxt.
Of course I could use some package as bootstrap-vue but I don't really want to inject this big package just for that one purpose.
You can write code in layouts/default.vue file and this file works on your defaults, work the code at where you used as a layout of your pages(generally almost everywhere.)
Different approach is use portalvue to render components whereever you want. Nice article here but in Turkish.

Switching Between Components in a Vue App

I'm building a single-file-based Vue application from a template generated with the Vue UI tool.
I understand how a .vue file defines the styling/structure/behavior of a component, how smaller components can be composed into bigger components, and how the top-level "App" component mounts everything to an HTML Div.
As the user progresses through the app, though -- say from a login screen to a master screen to a detail screen -- what's the accepted approach to switching out the current screen-level component?
Ty in advance.
--The Vuebie
This is quite an open ended question so ill just show you what I have done in my own projects. I split my components directory into two directories; 'pages' and 'common'. (Ignore the 'firebase' directory is it beyond the scope of this question).
The common directory holds components that may be used in a page or re used in several different pages.
For example the 'account form' is used in my 'Edit Account page' and the category bar is used in several of my pages.
The pages directory holds components that are technically no different from my common components but they represent full pages on my website. A page component may contain several common components.
Now the biggest distinction between common and pages is in the router. I route different paths relative to the main url (that is probably not the technically correct description but hopefully you get the point) to each of the pages. Here is my index.js file from my router directory:
As you can see, I have a route pointing to each one of my pages. You can " switch out the current screen-level component" (as you put it) by using router-link tag's to navigate between different page components. These are clickable urls that your client can use, they can also be wrapped in buttons and such.
For example, this router link navigates to my home page, the component name is 'Helloworld'. See its corresponding reference in my router's index.js and in the pages directory so you can connect it all in your head.
<router-link class="nav-item nav-word" :to="{ name: 'HelloWorld' }">
Finally, I will talk a bit about the App.vue file. The App.vue acts like a base component as it contains the 'router view' tag within it's template:
<router-view/>
This means that every page that you route will be placed in the position of the 'router view tag'. I.e this tag will be replaced with the page. It is common practise to surround this tag with html code that you would like to be shown in each page. For example I have my router view tag between my nav bar and footer. So that the nav bar and footer will show on each page.