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).
Related
I have a problem. I'm doing a software project for university but they want us to use python. Front end in javascript is allowed though and since this is a special course for non CompSci people or programmers even I decided to use the CDN version of vue and vue-router to avoid npm, node, etc to make it easier for them.
So now I have my routes defined like this in index.html inside a script tag defined below everything,
<script src="views/dashboard/dashboard.js"></script>
<script src="views/input/input.js"></script>
<script src="views/info/info.js"></script>
<script src="views/settings/settings.js"></script>
const routes = [
{ path: '/', component: Dashboard },
{ path: '/input', component: Inputpage },
{ path: '/info', component: Infopage },
{ path: '/settings', component: Settingspage },
{ path: '/index.html', redirect: '/' } //default route. Leave this as such to
];
and Dashboard/Inputpage/.. etc are .js files I import. Info.js looks like this for example
var Infopage = {
template: '<h1>This page is for information</h1>'
};
And that displays just fine. However, when I add anything else like a p or something simpler like a second heading, a paragraph or an input, nothing happens. What can I do to have it display more than just a heading?
EDIT 1: I tried
var Infopage = {
template:`<div id='info_page'>
<h1>This page is for information</h1>
</div>`
};
And now I get the error [Vue warn]: Error in nextTick: "InvalidCharacterError: String contains an invalid character".
I am developing an ecommerce application, and one major feature is that this app should have multiple themes. The total number of themes could be 100 or even more. However, these themes all have the same data (For example: all home page have same banner images, new product, feature product data.) .
I know I can use ng-template or TemplateRef to determine which piece of HTML should display. But since I have over 100 themes, both ng-template or TemplateRef methods will load a lot of extra files. So I think I need some sort of lazy load, when a component loads the data then lazy loads the correct HTML template. So how can I have this work?
Looks like it is possible, all our routes are handled by lazy loaded modules. This is our out-of-the-box route config:
const routes: Routes = [
{ path: '', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) }
];
While module lazy has this route config:
const routes: Routes = [
{ path: 'home', component: HomeComponent },
]
While HomeComponent is taken from the declarations of module lazy.
Then define another module, called for example lazy-two with the same route config, and its own HomeComponent.
Finally, you can switch between the modules by using this code:
lazyLoad() {
const routes: Routes = [
{
path: '',
loadChildren: () => import('./lazy-two/lazy-two.module')
.then(m => m.LazyTwoModule)
}
];
this.router.resetConfig(routes);
this.router.navigateByUrl('/home');
}
This will lazy load module lazy-two and refresh the route to /home - you will see the component of the new module displayed.
I couldn't create a stackblitz, some errors occurred probably because of lazy loading. So I ran it locally on my machine and pushed the code to GitHub
EDIT I managed to make a StackBlitz
I recommend used ComponentFactoryResolver to create the components that you need to render.
this.templates = [
{
id: "template-1",
component: Template1,
},
{
id: "template-2",
component: Template2,
},
];
ngOnInit() {
this.templates.forEach((element) => {
this.containerReference.createComponent(
this.factoryResolver.resolveComponentFactory(element.component)
);
});
}
in the .html you should have
<ng-container #containerReference><ng-container>
what about using the same component and styling it different when you select the template?
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' },
I'm trying to use plainroutes in order to create a react-router profile. I'm not convinced plainroutes is the most readable way to write code, but I'm trying to give it a fair shot since everyone seems excited about it. I'm having an extremely frustrating time trying to define multiple layouts for my components. Take the following working code:
Working plainroutes example
export const createRoutes = (store) => ({
path : '/',
component : CoreLayout,
childRoutes : [
LoginView(store),
SignupView(store),
Activate(store),
ForgotPw(store),
ConfirmReset(store)
]
}
)
Nothing unexpected happening here. The actual routes are built into the views using the following structure (LoginView for example):
Directory structure of childRoute objects
-/Login
--index.js
--/components
--Loginview.jsx
--Loginview.scss
The index.js files contain little route blocks looking like this:
Example childroute
export default (store) => ({
path : 'activate',
component: ActivateView
})
I'll also include the source of the Login component below, as referred to above. Please note I did try adding path: 'login' to this component but it made no difference.
Login import
export default {
component: LoginView
}
When a user visits /login they see the login component. Easy right? Yep. Now you might notice all those routes look like a group of authentication-related views. I want those views to share a layout. In this case, CoreLayout. That's also working with the above code.
Next step is that I want to add a user dashboard for after users login. This dashboard needs to use a different layout which I'm calling LoggedIn. Naturally, I expected that adding another json object with a similar pattern could accomplish this, so I produced the below code:
Broken multiple layout attempt
export const createRoutes = (store) => ({
path : '/login',
component : CoreLayout,
indexRoute : Login,
childRoutes : [
SignupView(store),
Activate(store),
ForgotPw(store),
ConfirmReset(store)
]
},
{
path : '/',
component : LoggedIn,
indexRoute : Home,
childRoutes : [
]
}
)
The above code does not work as intended. The only path that works are that paths in the second element of the set (the one with the / route). I tried moving some routes from the first element down and the do work when put in the second element... but this obviously doesn't solve my problem.
The most frustrating thing to me is that it seems to me as if I am following the SO posts which deal with this, though its a little difficult to tell for sure because they don't use plainroutes. I'm linking one here for reference.
Typing this out actually helped me work through the problem. Nothing like a good rubber duck. It looks like I misunderstood the nature of the router object. Apparently it needs to be a legitimate object, where I was under the impression it was accepting a collection. Thus, you need to define everything within the scope of a single parent. See below for how I solved it for my particular example:
export const createRoutes = (store) => (
{
path : '/',
component : CoreLayout,
indexRoute : Home,
childRoutes : [
{
path : '/',
component : AuthLayout,
childRoutes : [
LoginView(store),
SignupView(store),
Activate(store),
ForgotPw(store),
ConfirmReset(store)
]
},
{
path : '/admin',
component : LoggedIn,
indexRoute : Home,
childRoutes : [
]
}
]
}
)
I have install an amazing admin project made with angular 2.
Here is the demo of the project http://akveo.com/ng2-admin/#/pages/dashboard
I have problem to create a single new page in this project !
Here you can find what I want to do
https://akveo.github.io/ng2-admin/articles/013-create-new-page/
My error on my project is this one:
pages.component.ts?7a77:76 Uncaught ReferenceError: New is not defined
So basically I have a component problem, mys project can not find the component I am trying to used. In the page src/app/pages/pages.component.ts I have insert the following line ( as describe in the tutorial https://akveo.github.io/ng2-admin/articles/013-create-new-page/ )
{
name: 'New',
component: New, // here is the error
path: '/new',
}
If you want, you can install the project by using their tutorial:
https://akveo.github.io/ng2-admin/articles/002-installation-guidelines/
Thank you for your attention.
you need to import the New component created in pages/new into pages component
so in your src/app/pages/pages.component.ts file add this:
import {New} from './new/new.component' //<---
#RouteConfig([
// ... some routes here
{
name: 'New',
component: New,
path: '/new',
}
])
export class Pages {
}