Modal window in nuxt architecture - vue.js

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.

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 reloading App.vue on every new route

I have an App.vue file, which has a vue-router component in it that loads the content of my different pages, like this:
<template>
<div>
<router-view
:auth="auth"
:page_id="page_id"
>
</router-view>
</div>
</template>
I also have some AJAX calls in my created() method, which seem to be triggered every time I load a new page via the router. Is there any way to structure things so that my created() method only gets called once when the application loads, not every time a new page within the router loads?
One approach will be using Navigation Guards when you create a logic to determinate when to make your Ajax calls.
Other will be using Vuex, and create a state object to manage the Ajax calls, dispatch an event when the compontent had been loaded before, and bind a computed property to a getter that will contain the value if that component has been loaded previously.
Solution was a lot simpler than I thought:
The App.vue page was using a href links hard-coded to each route.
If you switch to using
<router-link to="path to your route">text here</router-link>
instead, everything works as normal - but Vue doesn't reload the App.vue component!

I want to change Vue components with media Queries

In my App.vue I've set my template like this
<app-header></app-header>
<router-view></router-view>
<app-footer ></app-footer>
app-header sets a header component to every other component of my project (so I don't have to repeat myself). app-footer does the same, but with a common footer for all of my components.
This works perfect with my Desktop web, but for Mobile I would like to change the header component to a new-header.vuecomponent, and I would like to get rid of the Footer when using a mobile device so it doesn't use screenspace.
How can I achieve this? I tried to use app-footer {display: none;} in a media query at App.Vue but its not working.
You do not want to use CSS to hide. The beauty of Vue is that in the case of mobile, the code will not even be generated at all.
Use a v-if directive, and add an isMobile property to your data, computed, store, etc. Or call a method to get it.
<app-footer v-if='!isMobile'></app-footer>
For the header, there are 2 ways. Using a component element with v-bind:is to swap in the correct one, or using v-if and v-else
<app-header v-if='!isMobile'></app-header>
<app-header-mobile v-else></app-header-mobile>
Here is the official link to the Vue dynamic component approach.
https://v2.vuejs.org/v2/guide/components-dynamic-async.html.
It would look like this:
<component v-bind:is="currentHeaderComponent"></component>
In this case, you would set currentHeaderComponent based on your conditions.
If you insist on CSS and media queries for the footer, set the component id or class, and that in your CSS
Component
<app-header id='app-header'></app-header>
<router-view></router-view>
<app-footer id='app-footer'></app-footer>
CSS
#app-footer {display: none;}

Vue Component with external template and style?

Can I have a Vue component where the template is found in an external file (.html)? Can we do the same with the style (.scss)?
This will assist our development where we can have front-end HTML devs work on the HTML and styling and the javascript devs can work on the component logic and behavior.
Is it possible to reference/import a template and style in a vue component?
The answer is yes, but the entry for you component would contain a template, not a script. From Single File Components section of Vue.js docs:
Even if you don’t like the idea of Single-File Components, you can still leverage its hot-reloading and pre-compilation features by separating your JavaScript and CSS into separate files:
<!-- my-component.vue -->
<template>
<div>This will be pre-compiled</div>
</template>
<script src="./my-component.js"></script>
<style src="./my-component.css"></style>

Vue-js and different layouts

how would one layout the router-views, if you have, lets say 3 different layout to use for you app (e.g. layout for customers, layout for employer and admin-interface).
At the moment i implemented the customer "view" like:
<template>
<div id="app">
<HeaderBar/>
<Navigation></Navigation>
<router-view></router-view>
</div>
</template>
inside the App.vue file. I could use something like:
<div id="app">
<router-view name="header">
<HeaderBar/>
<Navigation></Navigation>
</router-view>
<router-view></router-view>
</div>
</template>
and load different headers for those "subroutes" but this seem's to be odd.
Also what, if i'd like to use an other index.html?
I'm using webpack for this app.
Or would you suggest to create different apps for this?
Many thanks
rene
You could try using dynamic components.
Basically you change which component is being rendered depending on your route.
So it would probably be something like this:
<component v-bind:is="headerComponent"></component>
and then your app can contain heeaderComponent property in data object that has a default value and gets changed when you click on a route that should use different header. Rinse and repeat for the footer.
As for the last question, I think you should only use one app. As it is possible to do and everything is still connected. I'm not sure but I don't know how would you, if need be, communicate between different instances of Vue.