Parasails.js and using (Vue Router or virtualPages) - javascript

Parasails.js documentation mentions that it does support router and virtualPages, but does not actually specify how to interact with these options.
I am somewhat used to the normal Vue setup, of importing Vue, VueRouter and each individual component directly into the .vue file.
But with parasails.js, I feel that these parameters are expecting objects that are not defined in the documentation, so I'm just guessing at this point.
I have gotten to this point so far:
parasails.registerComponent('mainSearch', {
props: [
'prop1',
'prop2',
],
html5HistoryMode: 'history',
virtualPages: [
{ path: '/foo', component: 'page2' },
],
template: `
<div class="test">
<p>Test</p>
<router-link to="/foo">Foo</router-link>
<router-view />
</div>
`,
beforeMount: function() {
//…
// Attach any initial data from the server.
_.extend(this, SAILS_LOCALS);
},
mounted: async function(){
//…
},
beforeDestroy: function() {
//…
},
});
But I am receiving the error:
TypeError: In the HTML template (during render): Cannot read property 'matched' of undefined
Has anyone successfully used router or virtualPages in parasails.js and can help me out?
Also, my next question is: When passing components to virtualPages, do I just supply the name of another parasails registered component as a string? Or do I have to include that component in the code, and pass it as an object as one would do in VueRouter?
Thanks for any and all help!
EDIT
Using virtualPages on a parasails component apparently will not work.
But adding these properties to a parasails page seems to be the intended usage:
virtualPages: true,
html5HistoryMode: 'history',
virtualPageSlug: undefined,
virtualPagesRegExp: /^\/test\/?([^\/]+)?/,
Now, although I am no longer receiving errors, the <router-view></router-view> element is not being populated with the proper view when the <router-link to="/test/foo/">Foo</router-link> is clicked on the page.
I have added the following route to the project
'/test/foo/' : {
view: 'pages/test'
},
Any clues as to why my router-view is not being updated properly?
I think this documentation requires some serious updates as this is a pure guessing game every step of the way.

You're right, that link you provided does seem like its missing some info on how to set the virtual pages. I dont know much about using just parasails but in Sails v1 this is how I set virtual pages. (I use this mostly to have linkable modals.)
In your page script you define your data:
virtualPages: true,
html5HistoryMode: 'history',
virtualPageSlug: undefined,
virtualPagesRegExp: /^\/foo\/bar\/?([^\/]+)?/,
In your ejs file you can add this to a wrapping div:
v-if="virtualPageSlug === 'new'"
Routes file:
'GET /foo/bar/:virtualPageSlug?': { action: 'foo/view-bar' },

Related

How to transfer state between pages in multipage vue app?

I want to transfer data between pages in multipage vue app. I tried vuex with store but it's not working.
I used vue.config.js file to make multipage app. each page has App.vue and main.js to itself. When I import store.js to main.js, Initiate it there and it works only for it's own App.vue. But I need to transfer data from one page to another page. from one App.vue to another App.vue.
(Eg:- when I click on a person's name on one page, it should load that person's profile with his details. (It is an another page)). My plan was when someone click on the profile picture, details about that person goes to the store and I wanted to retrieve them in profile page. It didn't work. I'm a newbie to Vue. Am I doing it wrong way? Is there a better way doing this? Could someone help me to make this success? Thank you!
ps- Database is also attached. If there is a way to pass the reference between pages that will work too.
part of vue.config.js
module.exports = {
pages: {
'index': {
entry: './src/pages/home/main.js',
template: 'public/index.html',
title: 'Home',
chunks: [ 'chunk-vendors', 'chunk-common', 'index' ]
},
'register': {
entry: './src/pages/register/main.js',
template: 'public/index.html',
title: 'Register',
chunks: [ 'chunk-vendors', 'chunk-common', 'register' ]
},
'login': {
entry: './src/pages/login/main.js',
template: 'public/index.html',
title: 'Login',
chunks: [ 'chunk-vendors', 'chunk-common', 'login' ]
},
store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.Store({
state:{
//this is not real data
i:0
},
Part of my code editor's file stack to get a better idea
I followed the method in below thread to make a multipage app
https://stackoverflow.com/questions/51692018/multiple-pages-in-vue-js-cli
If you want to have the same Vuex store using your app in different tabs try to use vuex persisted state plugin. Plugin would save your store in localStorage and that would give you possibility to share the same store between different tabs (or different instances of your app if you wish).

Vue.js Router-Link Params Undefined

In my vue.js,
I am using params in my navigation.vue to pass it onto the next page for it to be used for dynamic routing such as the following:
<router-link tag="p"
:to="{name: 'Main', params: {category: link.linkCategory}}"
:key="link.linkCategory">
The following is the part of router index.js:
export default [
{
path: '/origin/:category',
name: 'origin',
component: () => import('#/views/origin/origin.vue'),
props: true,
children: [
{
path: '',
name: 'Main',
props: true,
component: () => import('#/views/origin/Main.vue')
}
So basically I'm passing in the 'category' value as the param for dynamic routing.
However, I get this warning message in my console whenever I try to access through the router-link:
[vue-router] missing param for named route "Main": Expected "category" to be defined
All the linkCategory values are stored in a separate link js file for my convenience
and the routing does get the values when each link is clicked.
The routing of all pages works fine but the console warnings are very annoying...
I know that parameter will be empty before accessing the router-link but I need a way to go around the warnings.
I even tried the 'v-if' method but did not work here.
Please fix my code for the wrong things that I did.
What happens if you change the to attribute to a different format as follows?
<router-link tag="p"
:to="`/origin/${link.linkCategory}`"
:key="link.linkCategory"
>

Why I see Vue warning: "Property or method "msg" is not defined on the instance but referenced during render..."

The situation looks dead simple but the reason is absolutely not clear to me. I'm trying to implement one Vue component for a project with legacy code using ES5. Vue library is 2.6x (also tried 2.5x).
I have the following Vue component:
window.StoragesPage = Vue.extend({
name: MyConsts.COMP_STORAGES_PAGE,
template: '#storages-page-template',
data: function () {
return {
msg: 'aaaaaaaaaa',
instGid: '',
instDomain: ''
};
},
});
it has the following template:
<script type="x-template" id="storages-page-template">
<div> {{ msg }} </div>
</script>
and it uses the following way of instantiation:
Vue.component(MyConsts.COMP_STORAGES_PAGE, window.StoragesPage);
// Init vue root instance
new Vue({
el: '#my-app'
});
and a markup for Vue root instance looks like:
<div id="my-app">
<storages-page></storages-page>
</div>
and my constant with the component name looks like:
...
COMP_STORAGES_PAGE: 'storages-page',
...
Finally I have this Vue warning:
vue-2x.js:634 [Vue warn]: Property or method "msg" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
(found in Root)
The question are:
Why I see this warning at all?
Why it contains "found in Root", but "msg" data item actually is inside my Vue root child component?
Why after that I see properly rendered page with expected output "aaaaaa"?
PS: I also have double-checked that there is only one Vue library included on the page.
Ok, looks like I found the reason for this weird behavior, after detailed checking Vue instantiation process in Chrome debugger I found that my child Vue component template was rendered inside Vue app container <div> tag like this:
<div id="my-app">
<storages-page></storages-page>
<?= $childrenTemplates ?> // <--- this one
</div>
Unfortunately, I skipped this line of code in the description of the question thinking it is not so important. That's why the Vue root component mentioned in the warning. So to fix this I just moved children component templates output below the closing </div> tag:
<div id="my-app">
<storages-page></storages-page>
</div>
<?= $childrenTemplates ?>

How to define new router?

For this question I am referring to the vuestic-admin template from https://github.com/epicmaxco/vuestic-admin
This template is the most suitable template for me. However, I want to make some changes. To be exactly, I want to add a new page, but dont want this page shown in the sidebar. To do this I need to define new router. My problem is: I dont quite understand how to add new router.
Hier is what I have done:
Firstly, I made a .vue file in components/contact/Contact.vue. Its code:
<template>
<div class="contact">
<div class="row">
<div class="col-md-12">
<p>contact</p>
</div>
</div>
</div>
</template>
<script>
export default { name: 'contact' }
</script>
<style lang="scss"></style>
Secondly, I added a new .js file in store/modules/contact.js. Its code:
import lazyLoading from './lazyLoading'
export default {
name: 'Contact',
path: '/contact',
component: lazyLoading('contact/Contact'),
meta: {
default: false,
title: 'menu.contact',
iconClass: 'vuestic-icon vuestic-icon-extras'
}
}
Thirdly, in the store/modules/menu/index.js file, I changed the state defination by adding pages:
import contact from './contact'
const state = {
pages: [
contact
],
items: [
dashboard,
statistics,
forms,
tables,
ui,
extra,
auth
]
}
Fourthly, in router/index.js file, I made following changes:
export default new Router({
routes: [
...generateRoutesFromMenu(menuModule.state.items),
{path: '*', redirect: { name: getDefaultRoute(menuModule.state.items).name }},
...generateRoutesFromMenu(menuModule.state.pages),
{path: '*', redirect: { name: getDefaultRoute(menuModule.state.pages).name }}
]
})
By compiling the changes above I get the console error: Uncaught TypeError: Cannot read property 'name' of undefined
Based on my knowledge (and my guess) the problem should be in the fourth step.
Could anybody please show me a way out of this problem? Thanks a lot!
Looking at the source here for getDefaultRoute(),
function getDefaultRoute (menu = []) {
let defaultRoute
menu.forEach((item) => {
if (item.meta.default) {
defaultRoute = item
} else if (item.children) {
let defaultChild = item.children.find((i) => i.meta.default)
defaultRoute = defaultChild || defaultRoute
}
})
return defaultRoute
}
I would say that you don't need the line
{path: '*', redirect: { name: getDefaultRoute(menuModule.state.pages).name }}
since for contact you have set default: false and there are no children, which means the function returns null (hence the error message you received).
The framework seems to assume a single list of menu items and one of them to be set as default. But I think your approach should work.
The only potential problem is that it looks like you are changing framework code, which means a bit more work when upgrading to next version of the framework.
A note about upgrading
I just ran the basic install, and looking at the project I have to revise my remark about a potential upgrade problem.
Essentially, this is a template not a framework. The difference is that the installer creates starter code in your project's src folder, which you can freely modify and save to a github repository.
There is no package under node_modules that would overwrite your router changes when you run npm install on your project at a future date.
If epicmaxco create a new version of the template that you wish to use, you would simply create a new project and copy the changes you previously made within src to the new project (perhaps run a diff of the old and new src folders).

Angular 2 routes resolve different component

Here is my use case:
When i load url /product/123 i want to load component ProductComponent
This is my setup:
RouterModule.forRoot([
{
path: 'product/:productId',
component: ProductComponent
},
{
path: '**', component: NotFoundComponent
},
]),
Now I have added a resolver to check if that product id exists, so my setup looks like this:
RouterModule.forRoot([
{
path: 'product/:productId',
component: ProductComponent,
resolver: {
productResolver: ProductResolver
}
},
{
path: '**', component: NotFoundComponent
},
]),
My resolver checks if that productId parameter exists via api call. The problem i have is that when productId is not found I want to load NotFoundComponent rather than redirecting to different page (i dont want to change url like angular 2 documentation suggests).
Anyone knows how to do that? if not productId found via resolver load NotFoundComponent without changing url/navigate?
I think all you want to do is skip the location change when you navigate to your NotFoundComponent. I'm assuming you've injected the Router into your resolver and are doing something like this when the ID does not exist:
router.navigate(['someUrl']);
Or you might be using the navigateByUrl method. Either way, you can tell the router not to change the URL:
router.navigate(['someUrl'], {skipLocationChange: true});
Don't see why you'd need to load your component via router settings, I'd put it inside the Component that tries to fetch it from the service, and then if it doesn't get a result back toggle some boolean that controls whether the NotFoundComponent gets shown. Some pseudo-ish code below:
ngOnInit(){
if (this.route.snapshot.params && this.route.snapshot.params['id']){
myService.getTheThingById((success)=>{
this.isFound = true;
},(err)=> {
this.isFound = false;
});
}
Then assuming your NotFoundComponent has a selector in it like 'not-found-component' throw it in the template for the component that's calling the service.
<not-found-component *ngIf='!isFound'></not-found-component>
I once faced this problem.
What I did was, in the component, to create 2 other components (in your case, you have ProductComponent, NotFoundComponent, and the other one you want to navigate to, let's say ArticleComponent)
Then I inserted 2 of the components in the main one :
product.component.html
<app-notFound></app-notFound>
<app-article></app-article>
After that, in your ngOnInit, you see if the parameter is there. If he is, then you log it in a property, let's say isParam = true.
Your template becomes
<app-notFound *ngIf="!isParam"></app-notFound>
<app-article *ngIf="isParam"></app-article>
It may not be the best solution out there, but it worked for me !

Categories

Resources