How to get all pages and components as object in nuxt js project - vue.js

I have
pages/
index.vue
other.vue
components/
CustomButton.vue
CustomInput.vue
I need to get index.vue, other.vue, CustomButton.vue, CustomInput.vue as VueComponent object to access their data() variables.
I'm using Nuxt2.

Related

Content Will Only Display After Reload

I'm attempting to display a simple calendar based on the jsCalendar library. When I navigate to the page, the calendar won't appear; however, when I reload the page [⌘-R] or enter the page URL directly, the content appears normally. I've tested in Safari and FireFox and the behavior is the same.
Desired Outcome:
Display the content when the page is reached via Vue Router or direct navigation.
Calendar.vue
<template>
<div class="auto-jsCalendar black-theme"
data-navigator-position="right"
data-month-format="month YYYY"
data-day-format="DDD">
</div>
</template>
<script>
import 'simple-jscalendar'
export default {
emits: ['page-data'],
mounted() {
this.$emit('page-data', {title: 'calendar', content: '',})
},
}
</script>
<style>
#Import '~simple-jscalendar/source/jsCalendar.css';
#Import '~simple-jscalendar/themes/jsCalendar.darkseries.css';
</style>
Navigating to Calendar.vue
When navigating to the page, the div looks like this:
<div class="auto-jsCalendar black-theme" data-navigator-position="right" data-month-format="month YYYY" data-day-format="DDD"></div>
Reload or Direct Navigation
When reloading the page or entering the URL directly into the browser, the div looks like this:
<div class="auto-jsCalendar black-theme" data-navigator-position="right" data-month-format="month YYYY" data-day-format="DDD" jscalendar-loaded="true"></div>
(The dynamic attribute jscalendar-loaded (which is added to the div when the calendar object is displayed) is not established when navigating to the page.)
Environment:
Dave#[SNIP] my_spa % npm list
my_spa#0.1.33 /.../my_spa
├── #vue/cli-plugin-babel#4.5.15
├── #vue/cli-plugin-router#4.5.15
├── #vue/cli-plugin-vuex#4.5.15
├── #vue/cli-service#4.5.15
├── #vue/compiler-sfc#3.2.20
├── babel-eslint#10.1.0
├── chart.js#3.6.0
├── chartjs-plugin-annotation#1.1.0
├── chartjs-plugin-datalabels#2.0.0
├── core-js#3.19.0
├── eslint-plugin-vue#7.20.0
├── simple-jscalendar#1.4.4
├── vue-router#4.0.11
├── vue#3.2.20
├── vue3-smooth-dnd#0.0.2
├── vuex-persist#3.1.3
└── vuex#4.0.2
EDIT: In consulting with the author of jsCalendar, I've come to learn that the script acts on the page load event which explains why the content doesn't update when navigating to the view. The external script has an autoFind() function which could be called from mounted() which should update the content; however, I've been unable to find the right way to call the function.
import jsCalendar from 'simple-jscalendar'
mounted() {
jsCalendar.autoFind()
this.$emit('page-data', {title: 'calendar', content: '',})
},
results in:
Unhandled Promise Rejection: TypeError: simple_jscalendar__WEBPACK_IMPORTED_MODULE_0___default.a.autoFind is not a function.
I looked at the documentation from the link, here is what I would do:
remove the auto-jsCalendar from the div as this is the hook that makes it work when you load the page, but not when you navigate and add a ref.
Then in your mounted hook call the jsCalendar.new as documented here:
https://gramthanos.github.io/jsCalendar/docs.html (Javascript Create Calendar)
<template>
<div class="black-theme"
data-navigator-position="right"
data-month-format="month YYYY"
data-day-format="DDD"
ref="calendar">
</div>
</template>
<script>
import 'simple-jscalendar'
export default {
emits: ['page-data'],
mounted() {
jsCalendar.new(this.$refs.calendar)
this.$emit('page-data', {title: 'calendar', content: '',})
},
}
</script>
<style>
#Import '~simple-jscalendar/source/jsCalendar.css';
#Import '~simple-jscalendar/themes/jsCalendar.darkseries.css';
</style>
Though in the long run I'd suggest to look for a library that was built for Vue. It is always a bit tricky if a third party library manipulates the DOM that is also used from Vue.

createApp({}).mount('#app') clears #app's child elements in vue3

So I'm trying to add Vue3 to an existing asp.net core project. What I'd like to happen is for my razor app to render as normal, then use custom vue components to give my frontend a more reactive feel. However, when I mount an empty vue app to my wrapper div (parent of all other body content), it seems to be deleting all innerHTML of that wrapper div, completely removing all server rendered body content.
In my _Layout.cshtml file, I'm wrapping all content in a div with id 'app'.
<body>
<div id='app'>
#RenderBody()
</div>
<script src="~/js/vue-app/dist/js/chunk-vendors.76316534.js"></script>
<script src="~/js/vue-app/dist/js/app.bf4c5ba9.js"></script>
</body>
in main.js
import { createApp } from 'vue'
const vueApp = createApp({}).mount('#app');
// component definitions below
With the app set up like this, when I run my .net project I see a blank white browser window instead of the razor compiled html that I expect. In Vue2, it was possible to do this:
const vueApp = new Vue({
el: '#app',
data: {
....
},
methods: {
....
}//, etc
});
Which would result in the app being rendered as normalthe vue app bound to #app, making vue available to the child content (model binding, vue click handling, etc).
I've tried playing around with the isHydrate optional parameter on mount(), but it causes no change in the result.
Am I missing something here? How do you slowly migrate an existing project to use vue3 if you can't mount the app without clearing content? Any guidance is much appreciated.
Thank you
Notes:
vue-next runtime-dom source If this method is the mount method getting called, I'm not sure why container.innerHTML would not be getting set in the component. {} is not a function, and render/template is not defined for it.
vue-next runtime-core apiCreateApp source If this is the method getting called....I have no idea.
Update
Vue 3, without template renderer, will not be able to handle the templates after it has been compiled. To fix that, you can import vue/dist/vue.esm-browser (and vue.runtime.esm-browser.prod for prod), instead of the default vue. This will allow run-time component rendering.

Nuxt-Router: Slug in URL should not be optional

My directory structure looks like that
/pages/request/guest/_slug/index.vue
If I call /request/guest/test-slug/ then Nuxt opens the index.vue file as expected.
But /request/guest/ without a slug also opens the same index.vue file.
Why is that? It should return an 404.
in index.vue you should check for route params and if there is no slug then return an error .
You can use validate props in your _slug/index.vue file to check if route.params.slug exists.
https://nuxtjs.org/api/pages-validate
otherwise it just show the index.vue

Creating a path to an asset dynamically

The issue is how to get Vue to render the correct path for an asset, if the path to the asset and the assets name is passed through as a props.
Explanation:
When using a Vue component... if passing in props which contain a path and a file name of an asset to be loaded
export default{
name: 'NewComponent',
props: ["path","file"],
computed:{
calculateCompletePath (){
return this.path+""+this.file;
}
}
}
If using something like the above in a manner such as:
<template>
<div>
<video>
<source :src="calculateCompletePath" type="video/mp4"/>
</video>
</div>
</template>
How can you get the src portion to render correctly - e.g Vue generates its own string referencing the media folder for example
/media/movie.6ac43bcf.mp4
Side note:
I've read somewhere there is the possibility to using require (<<asset>>) but that doesn't seem to work if used on the computed function e.g. return require (this.path+""+this.file);
Any ideas how to get this to work?
Please refer this document for a detailed explanation on how to resolve static assets:
https://cli.vuejs.org/guide/html-and-static-assets.html#relative-path-imports
I think the problem is that your asset(in this case an mp4 file) is not located in your computer's /media folder.
See these 3 points for a better understanding: https://cli.vuejs.org/guide/html-and-static-assets.html#url-transform-rules
If your media folder is located under the root folder(/), then, the computed value /media/movie.6ac43bcf.mp4 will work.
If your media folder is under src folder of the app, your computed property should return #/media/movie.6ac43bcf.mp4
If your media folder is somewhere else, then you should create a proper path using #/ or the ./ symbol to reach the file correctly.

Vue components re-rendering on router push

I have created a global component that i share across multiple routes. i have simplified the component below for demonstration purposes.
#name area-wrapper
<template>
<div id="area">
<div id="area-menu">
<menu/>
</div>
<div id="area-content">
<slot/>
</div>
</div>
</template>
Within the menu is a navbar which has options that will change the content of the slot which i could just turn into a component v-bind:is component.
What i have done is created several page for the routing
pages
_entity <--*** forgot to include this ***
app
index.vue
_appId.vue
new.vue
Each of these pages includes the component above and then adds in their own content for id="area-content
What i have been noticing is that the entire area-wrapper is being reloaded when i move from
website.com/app/112 (pages/app/_appId.vue)
website.com/app/11 (pages/app/_appId.vue)
I have noticed that if i move the area-wrapper to a layout then it works the problem is that the component will eventually be shared with several apps but will have a different <menu/> and layouts do not have slots
I'm not sure why vue is re-rendering the entire component even though it is shared among all the pages and is the same across each page.
What am i missing here?
If this is expected behavior my question becomes, how can i create a shared component that acts like a layout that i include in several pages without adjusting the props and have it not constantly reload
+==== UPDATE ====+
i have been trying to get nest routes to work because i believe this is what i am after. However nuxt is not generating them correctly
Per the documentation(``) i need to change my stucture to
pages
_entity
messaging
settings
index.vue
msg
index.vue
messaging.vue(wrong - changed back to index.vue) -> within here add the <nuxt-child> component
messaging.vue(need to move to _entity folder to create children)
nuxt should create the child components. However it is still continuing to create full routes. i am using nuxt-i18n will that cause a problem?
routes
...
{
path: "/:entity/messaging/messaging",
component: _8a865700,
name: "entity-messaging-messaging___en"
}, {
path: "/:entity/messaging/:msg?",
component: _1ef926cc,
name: "entity-messaging-msg___en"
}, {
path: "/:entity/messaging/settings",
component: _7b358e6a,
name: "entity-messaging-settings___en"
}
I originally created the nested route within the folder.Instead, you need to put the parent page within the root of what directory the folder exists.
pages
_entity
messaging
settings
index.vue
msg
index.vue
messaging.vue(wrong - changed back to index.vue) -> within here add the <nuxt-child> component
messaging.vue(need to move to _entity folder to create children)
You should define routing in your app as suggested here (pure Vue) or here (with vue-router). Without it you are reloading a whole page (and the app) when you change the URL.