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 {
}
Related
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?
I'm lazy loading an angular module and while trying to open my DatesModal I'm getting this error:
No component factory found for DatesModal. Did you add it to #NgModule.entryComponents?
My lazyModule looks like this:
declarations: [DatesModal]
entryComponents: [DatesModal]
Im definitely adding the DatesModal in the entryComponents array of the lazyModule. Anyone got any idea what I could be missing here?
Please let me know if you need more info to answer this question.
It looks like you want to get/import this module in other modules, however this module is not visible to others. Try to export your module:
exports: [DatesModal]
UPDATE:
As Angular docs says:
For production apps you want to load the smallest code possible. The
code should contain only the classes that you actually need and
exclude components that are never used. For this reason, the Angular
compiler only generates code for components which are reachable from
the entryComponents; This means that adding more references to
#NgModule.declarations does not imply that they will necessarily be
included in the final bundle.
If a component isn't an entry component and isn't found in a template,
the tree shaker will throw it away. So, it's best to add only the
components that are truly entry components to help keep your app as
trim as possible.
To make your module to be lzay loaded, you need to do in routes:
const routes: Routes = [
{
path: 'customers',
loadChildren: () => import('./customers/customers.module').then(mod => mod.CustomersModule)
},
{
path: 'orders',
loadChildren: () => import('./orders/orders.module').then(mod => mod.OrdersModule)
},
{
path: '',
redirectTo: '',
pathMatch: 'full'
}
];
Read this docs about how to make your modules to be lazy loaded.
Have you used any third-party library (or yourself) to dynamic create this component in lazy-load module?
If so, you need to add this component in the AppModule's (or up-level non-lazy-load module) entrycomponents.
More detail you can see this issue
I'm creating pluggable angular app.
I've found the following article:
Building an extensible Dynamic Pluggable Enterprise Application with Angular
Generally, everything works fine, but when I've tried to add angular router then I met some problems.
Currently, I'm not able to add the dynamically loaded component to the router.
I've tried something like this:
this.pluginLoader.load(pluginName).then(moduleFactory => {
const moduleRef = moduleFactory.create(this.injector);
const entryComponent = (moduleFactory.moduleType as any).entry;
const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(
entryComponent
);
this.router.config.push({
path: `${pluginName}`,
component: entryComponent
});
this.router.resetConfig(this.router.config);
this.router.navigate([`/${pluginName}`]);
});
But this code cause following error:
core.js:15723 ERROR Error: Uncaught (in promise): Error: No component factory found for function(){this.x=!1}. Did you add it to #NgModule.entryComponents
I've tried also use loadChildren property instead of the component property but I don't know what path should I use.
How can I add the component to the component factory, or how can I find a proper path for such components?
I've found a solution, to add the dynamically loaded module to the angular router we have to use LoadChildren property, but directly from Route object. In this case, we have to create Route object first and then add it to the router config.
loadPlugin(pluginName: string) {
this.pluginLoader.load(pluginName).then(moduleFactory => {
const route: Route = {
path: `${pluginName}`,
loadChildren: () => moduleFactory
};
this.router.config.push(route);
});
}
So in a vanilla vue.js skeleton project, there is a component called HelloWorld.
views/Home.vue is importing this component
<script>
// # is an alias to /src
import HelloWorld from "#/components/HelloWorld.vue";
export default {
name: "home",
components: {
HelloWorld
}
};
</script>
Again this is all in the skeleton project, I didn't change anything.
If I take this example and change HelloWorld to Hello (while also changing all references inside of views/Home.vue to Hello. I get the following error:
* #/components/Hello.vue in ../node_modules/babel-loader/lib??ref--12-0!../node_modules/cache-loader/dist/cjs.js??ref--0-0!../node_modules/vue-loader/lib??vue-loader-options!./views/Home.vue?vue&type=script&lang=js&
What am I missing here?
When I grep the project directory I am finding references to Hello World in node_modules directory, not sure what that is about
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).