How to use ActivatedRoute in angular while using Hybrid routing? - angular-hybrid

I am trying to get data from a route(/item/{id:[^/]*}/') in angular component for a hybrid app using upgrade module
I have tried ActivatedRoute to get hold off router state but it keeps complaining about invalid route configuration.
AppModule
const itemState = {
name: 'item',
url: '/details/item:{id:[^/]*}/',
title: 'Item detail',
component: ItemContainerComponent
};
#NgModule({
entryComponents: [],
declarations: [],
imports: [
BrowserModule,
RouterModule.forRoot([]),
UpgradeModule,
UIRouterUpgradeModule.forRoot({ states: [itemState] }),
],
providers: [
{ provide: LocationStrategy, useClass: HashLocationStrategy }
]
})
ItemContainerComponent
ngOnInit() {
this.route.params.subscribe(params => {
console.log(params['id']);
});
}
Invalid configuration of route '': routes must have either a path or a matcher specified ; Zone: ; Task: Promise.then ; Value: Error: Invalid configuration of route '': routes must have either a path or a matcher specified

Seems like solution is to use transition from '#uirouter/core' and do something like below.
constructor(private transition: Transition) {}
ngOnInit() {
this.itemId = this.transition.params().id;
}

Related

NestJs provider isn't injected and says this.iGalleryRepository.addImage is not a function

I am trying to make a nestjs typescript backend application which uses mysql as database using clean architecture. I implemented JWT and Authorization but it doesn't see my function and i think the problem is with the dependency injection therefore i will share related files but if you need to see other files just let me know. I've been trying to solve this for 3-4 days. :/
Full Error :
ERROR Method: POST; Path: /images/add; Error: this.iGalleryRepository.addImage is not a function
My "AppModule" is named .RootModule (where i pack my app):
#Module({
imports: [
InfraModule,
AuthModule,
UserModule,
ImageModule
]
})
export class RootModule { }
Image Module:
const persistenceProviders: Provider[] = [
{
provide: DITokens.ImageDITokens.ImageRepository,
useFactory: (dataSource: DataSource) => dataSource.getRepository(TypeOrmImage).extend(TypeOrmImageRepositoryAdapter),
inject: [DITokens.CoreDITokens.DataSource]
}
];
#Module({
controllers: [
ImageController
],
providers: [
...persistenceProviders,
ImageService,
ImageHandler
]
})
export class ImageModule { }
You may ask where & how i define db (idk why 🤷‍♂️) :
export const databaseProviders = [
{
provide: DITokens.CoreDITokens.DataSource,
useFactory: async () => {
return AppDataSource.initialize();
}
}
];
.
.
.
#Global()
#Module({
imports: [
CqrsModule,
],
providers: [
...providers,
...databaseProviders
],
exports: [
DITokens.CoreDITokens.CommandBus,
DITokens.CoreDITokens.QueryBus,
DITokens.CoreDITokens.EventBus,
...databaseProviders
]
})
export class InfraModule implements OnApplicationBootstrap {
onApplicationBootstrap(): void {
initializeTransactionalContext();
}
}
Image Controller :
I should mention that Logger.log(adapter, "CreateImageDTO"); works, i can see the output but can't see the line Logger.log(createdImage, "createdImage")
#Controller('images')
#ApiTags('images')
export class ImageController {
constructor(
private readonly imageService: ImageService,
private readonly imageHandler: ImageHandler,
) { }
#Post("add")
#HttpCode(HttpStatus.OK)
#ApiBody({ type: HttpRestApiModelCreateImageBody })
#ApiResponse({ status: HttpStatus.OK, type: HttpRestApiResponseImage })
public async createImage(
#Body() body: HttpRestApiModelCreateImageBody
): Promise<CoreApiResponse<ImageUseCaseDTO>> {
const adapter: ICreateImageDTO = await CreateImageDTO.new({
parentId: body.parentId,
title: body.title,
imageUrl: body.imageUrl,
type: body.type
});
Logger.log(adapter, "CreateImageDTO")
const createdImage: ImageUseCaseDTO = await this.imageService.createImage(adapter);
Logger.log(createdImage, "createdImage")
return CoreApiResponse.success(createdImage);
}
}
Image Service
#Injectable()
export class ImageService {
/**
* #param {IGalleryRepository} iGalleryRepository
*/
constructor(
#Inject(DITokens.ImageDITokens.ImageRepository)
private readonly iGalleryRepository: IGalleryRepository
) { }
public async createImage(payload: ICreateImageDTO): Promise<ImageUseCaseDTO> {
const image: Image = await Image.new({
title: payload.title,
type: payload.type,
parentId: payload.parentId,
imageUrl: payload.imageUrl
})
await this.iGalleryRepository.addImage(image);
return ImageUseCaseDTO.newFromImage(image);
}
}
the line throws error is in the above snippet fyi
When i try to log this.iGalleryRepository using console.log() it gives the following:
Repository {
target: [class TypeOrmImage],
manager: <ref *1> EntityManager {
'#instanceof': Symbol(EntityManager),
repositories: [ [Repository], [Repository] ],
treeRepositories: [],
plainObjectToEntityTransformer: PlainObjectToNewEntityTransformer {},
connection: DataSource {
'#instanceof': Symbol(DataSource),
migrations: [],
subscribers: [],
entityMetadatas: [Array],
name: 'default',
options: [Object],
logger: [AdvancedConsoleLogger],
driver: [MysqlDriver],
manager: [Circular *1],
namingStrategy: [DefaultNamingStrategy],
metadataTableName: 'typeorm_metadata',
queryResultCache: undefined,
relationLoader: [RelationLoader],
relationIdLoader: [RelationIdLoader],
isInitialized: true
}
},
queryRunner: undefined
}
Thank you in advance.
Here we are, i solved.
dataSource.getRepository(TypeOrmImage).extend(TypeOrmImageRepositoryAdapter)
supposed to work but for some reason which i really dont know it didnt. .extend wasnt working as i expected so i would dare to say that either extend is not working properly or the way i implemented was wrong. Which means if you have this error check your implementation and if it seems right then do what i did.
I just changed
provide: DITokens.ImageDITokens.ImageRepository,
useFactory: (dataSource: DataSource) => dataSource.getRepository(TypeOrmImage).extend(TypeOrmImageRepositoryAdapter),
inject: [DITokens.CoreDITokens.DataSource]
into
provide: DITokens.ImageDITokens.ImageRepository,
useClass: TypeOrmImageRepositoryAdapter
and it indeed worked. Since i sue repository in the signiture of the class probably it generates typeorm repo.
Hope this helped!

Problem NestJS/TypeORM : [Nest] 3100 ERROR [ExceptionHandler] Nest can't resolve dependencies of the ProjetslaboService (?)

After having followed the following tutorial in full:
https://www.youtube.com/watch?v=JK5aynTxKjM&list=PL4bT56Uw3S4zIAOX1ddx8oJS6jaD43vZC
I decided to do my crud based on this:
I tested TypeORM with my category (Categorie), so just a simple table with no foreign key or anything and it worked like a charm and the program runs CRUD.
I said so I decided to make several tables including the "ProjectsLabo" table, with two foreign keys.
But problem when I incorporate in my module the three other modules I have an error:
[Nest] 3100 - 25/01/2023, 14:39:29 ERROR [ExceptionHandler] Nest can't resolve dependencies of the ProjetslaboService (?). Please make sure that the argument ProjetslaboDtoRepository at index [0] is available in the ProjetslaboMo
dule context.
Potential solutions:
Is ProjetslaboModule a valid NestJS module?
If ProjetslaboDtoRepository is a provider, is it part of the current ProjetslaboModule?
If ProjetslaboDtoRepository is exported from a separate #Module, is that module imported within ProjetslaboModule?
#Module({
imports: [ /* the Module containing ProjetslaboDtoRepository */ ]
})
Error: Nest can't resolve dependencies of the ProjetslaboService (?). Please make sure that the argument ProjetslaboDtoRepository at index [0] is available in the ProjetslaboModule context.
Potential solutions:
Is ProjetslaboModule a valid NestJS module?
If ProjetslaboDtoRepository is a provider, is it part of the current ProjetslaboModule?
If ProjetslaboDtoRepository is exported from a separate #Module, is that module imported within ProjetslaboModule?
#Module({
imports: [ /* the Module containing ProjetslaboDtoRepository */ ]
})
Here is an example of the LaboProjects module :
projetslabo.dto.ts
import { IsNotBlank } from "../../decorators/is-not-blank.decorator";
export class ProjetslaboDto {
//#IsString()
//#IsNotEmpty()
#IsNotBlank({message : 'Serveur : the name is not empty'})
nom?: string;
}
projetslabo.controller.ts
#Controller('projetslabo')
export class ProjetslaboController {
constructor(private readonly projetslaboService: ProjetslaboService) {
}
#Get()
async GetAll() {
return await this.projetslaboService.getAll();
}
#Get(':id')
async GetOne(#Param('id', ParseIntPipe) id: number) {
return await this.projetslaboService.findById(id);
}
}
projetslabo.entity.ts
#Entity({ name: 'projetslabo' })
export class ProjetslaboEntity {
#PrimaryGeneratedColumn()
idProjetsLabo: number;
#Column({ type: 'varchar', length: 40, nullable: false })
nom: string;
#ManyToOne(() => ValeurslaboEntity, (ValeurslaboEntity) => ValeurslaboEntity.idValeursLabo , {nullable : false})
FK_idValeursLabo: ValeurslaboEntity
#ManyToOne(() => AnneeslaboEntity, (AnneeslaboEntity) => AnneeslaboEntity.idAnneesLabo, {nullable : false})
FK_idAnneesLabo: AnneeslaboEntity
}
Projetslabo.module.ts
#Module({
imports: [TypeOrmModule.forFeature([ProjetslaboEntity])],
providers: [ProjetslaboService],
controllers: [ProjetslaboController],
})
export class ProjetslaboModule {}
projetslabo.repository.ts
#EntityRepository(ProjetslaboEntity)
export class ProjetslaboRepository extends Repository<ProjetslaboEntity>{}
projetslabo.service.ts
#Injectable()
export class ProjetslaboService {
constructor(
#InjectRepository(ProjetslaboDto)
private projetslaboRepository: ProjetslaboRepository,){}
async getAll(): Promise<ProjetslaboEntity[]> {
const list = await this.projetslaboRepository.find();
if (!list.length) {
throw new NotFoundException(
new MessageDto('Serveur : La liste est vide'),
);
}
return list;
}
async findById(idProjetsLabo: number): Promise<ProjetslaboEntity> {
const annees = await this.projetslaboRepository.findOneBy({
idProjetsLabo,
});
if (!annees) {
throw new NotFoundException(
new MessageDto("Serveur : Cette année n'existe pas"),
);
}
return annees;
}
app.module.ts
#Module({
imports: [
ConfigModule.forRoot({
envFilePath: '.env',
isGlobal: true,
}),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
type: 'mariadb',
host: configService.get<string>(DB_HOST),
port: +configService.get<number>(DB_PORT),
username: configService.get<string>(DB_USER),
password: configService.get<string>(DB_PASSWORD),
database: configService.get<string>(DB_DATABASE),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
logging: true,
}),
inject: [ConfigService],
}),
CategoriesModule,
/*Problem with this 3 modules
ProjetslaboModule,
ValeurslaboModule,
AnneeslaboModule,
*/
],
controllers: [AppController],
providers: [AppService]
})
export class AppModule {}
Can you help me please?
Nestjs/core : 9.0.0
Nestjs/typeorm : 9.0.1
You pass ProjetslaboDto to your #InjectRepository() when you should be passing ProjetslaboEntity as that's what you've told TypeOrmModule.forFeature() about.
#Injectable()
export class ProjetslaboService {
constructor(
- #InjectRepository(ProjetslaboDto)
+ #InjectRepository(ProjetslaboEntity)
private projetslaboRepository: ProjetslaboRepository,){}
...

Angular Pipe could not be found in Jasmine test

I'm getting an error using Jasmine to test one of my angular 6 components:
The pipe 'paginate' could not be found ("]Item of activityLogDisplay.data | paginate: config; let index = index" (click)="): ng:///DynamicTestModule/ActivitylogComponent.html#59:34
'pagination-controls' is not a known element:
I'm using NgxPaginationModule that I installed with the following command:
npm install ngx-pagination --save
So, note that I'm not using a custom pipe that I created myself, I'm using one that belongs to a package that I downloaded. My component test is failing on the use of a pipe and not on testing the pipe itself. Here's what my use of the pagination pipe looks like in my html template:
<li class="list-group-item list-group-item-action"
*ngFor="let alItem of activityLogDisplay.data | paginate: config; let index = index"
(click)="toggleALView(alItem.index)">
Here's what my spec.ts file looks like (pretty much out of the box):
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { ActivitylogComponent } from './activitylog.component';
describe('ActivitylogComponent', () => {
let component: ActivitylogComponent;
let fixture: ComponentFixture<ActivitylogComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ActivitylogComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ActivitylogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
I've tried adding the import of NgxPaginationModule to the spec.ts file:
import { NgxPaginationModule } from 'ngx-pagination';
And I've included it in the declarations area of the TestBed config:
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ActivitylogComponent, NgxPaginationModule ]
})
.compileComponents();
}));
The error message changes to:
Failed: Unexpected module 'NgxPaginationModule' declared by the module
'DynamicTestModule'. Please add a #Pipe/#Directive/#Component annotation.
In my app.module.ts file, I've got NgxPaginationModule listed in the imports array and not the declarations array:
import { NgxPaginationModule } from 'ngx-pagination';
#NgModule({
declarations: [
AppComponent,
ActivitylogComponent
],
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
NgxPaginationModule,
RouterModule.forRoot(appRoutes,{useHash:true})
],
providers: [IndexService, AdminIndexService],
bootstrap: [LandingpageComponent]
})
Any ideas what I need to do to get this test to work?
Figured out my problem. I needed to add NgxPaginationModule as an import to the test bed configureTestingModule area in my spec file:
beforeEach(async(() => {
TestBed.configureTestingModule({
imports : [
NgxPaginationModule
],
declarations: [
ActivitylogComponent
]
})
.compileComponents();
}));
FIX:
Do the following changes:
In your local module add your KeyValue pipe in declarations.
In spec file add KeyValue pipe's class name in declarations.
Add in providers as well if you get error like NullInjectorError: R3InjectorError(DynamicTestModule)[PipeName -> PipeName]: NullInjectorError: No provider for PipeName!.
Your local spec file where error came
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
CommonModule,
RouterTestingModule,
HttpClientTestingModule,
NotifierModule,
ReactiveFormsModule
],
providers: [
ConfigureDeviceComponent
],
declarations: [
// Add your pipe here
]
});
fixture = TestBed.createComponent(ConfigureDeviceComponent);
component = fixture.componentInstance;
component.ngOnInit();
});
Your local module file where your current component is running
#NgModule({
declarations: [...], Include your pipe here
imports: [...],
providers: [...],
bootstrap: [AppComponent]
})
https://stackoverflow.com/a/72787641/10373693

Ensure json configuration is loaded in Angular2 [duplicate]

Is there a way to pass arguments rendered on the backend to angular2 bootstrap method? I want to set http header for all requests using BaseRequestOptions with value provided from the backend. My main.ts file looks like this:
import { bootstrap } from '#angular/platform-browser-dynamic';
import { AppComponent } from "./app.component.ts";
bootstrap(AppComponent);
I found how to pass this arguments to root component (https://stackoverflow.com/a/35553650/3455681), but i need it when I'm fireing bootstrap method... Any ideas?
edit:
webpack.config.js content:
module.exports = {
entry: {
app: "./Scripts/app/main.ts"
},
output: {
filename: "./Scripts/build/[name].js"
},
resolve: {
extensions: ["", ".ts", ".js"]
},
module: {
loaders: [
{
test: /\.ts$/,
loader: 'ts-loader'
}
]
}
};
update2
Plunker example
update AoT
To work with AoT the factory closure needs to be moved out
function loadContext(context: ContextService) {
return () => context.load();
}
#NgModule({
...
providers: [ ..., ContextService, { provide: APP_INITIALIZER, useFactory: loadContext, deps: [ContextService], multi: true } ],
See also https://github.com/angular/angular/issues/11262
update an RC.6 and 2.0.0 final example
function configServiceFactory (config: ConfigService) {
return () => config.load();
}
#NgModule({
declarations: [AppComponent],
imports: [BrowserModule,
routes,
FormsModule,
HttpModule],
providers: [AuthService,
Title,
appRoutingProviders,
ConfigService,
{ provide: APP_INITIALIZER,
useFactory: configServiceFactory
deps: [ConfigService],
multi: true }
],
bootstrap: [AppComponent]
})
export class AppModule { }
If there is no need to wait for the initialization to complete, the constructor of `class AppModule {} can also be used:
class AppModule {
constructor(/*inject required dependencies */) {...}
}
hint (cyclic dependency)
For example injecting the router can cause cyclic dependencies.
To work around, inject the Injector and get the dependency by
this.myDep = injector.get(MyDependency);
instead of injecting MyDependency directly like:
#Injectable()
export class ConfigService {
private router:Router;
constructor(/*private router:Router*/ injector:Injector) {
setTimeout(() => this.router = injector.get(Router));
}
}
update
This should work the same in RC.5 but instead add the provider to providers: [...] of the root module instead of bootstrap(...)
(not tested myself yet).
update
An interesting approach to do it entirely inside Angular is explained here https://github.com/angular/angular/issues/9047#issuecomment-224075188
You can use APP_INITIALIZER which will execute a function when the
app is initialized and delay what it provides if the function returns
a promise. This means the app can be initializing without quite so
much latency and you can also use the existing services and framework
features.
As an example, suppose you have a multi-tenanted solution where the
site info relies on the domain name it's being served from. This can
be [name].letterpress.com or a custom domain which is matched on the
full hostname. We can hide the fact that this is behind a promise by
using APP_INITIALIZER.
In bootstrap:
{provide: APP_INITIALIZER, useFactory: (sites:SitesService) => () => sites.load(), deps:[SitesService, HTTP_PROVIDERS], multi: true}),
sites.service.ts:
#Injectable()
export class SitesService {
public current:Site;
constructor(private http:Http, private config:Config) { }
load():Promise<Site> {
var url:string;
var pos = location.hostname.lastIndexOf(this.config.rootDomain);
var url = (pos === -1)
? this.config.apiEndpoint + '/sites?host=' + location.hostname
: this.config.apiEndpoint + '/sites/' + location.hostname.substr(0, pos);
var promise = this.http.get(url).map(res => res.json()).toPromise();
promise.then(site => this.current = site);
return promise;
}
NOTE: config is just a custom config class. rootDomain would be
'.letterpress.com' for this example and would allow things like
aptaincodeman.letterpress.com.
Any components and other services can now have Site injected into
them and use the .current property which will be a concrete
populated object with no need to wait on any promise within the app.
This approach seemed to cut the startup latency which was otherwise
quite noticeable if you were waiting for the large Angular bundle to
load and then another http request before the bootstrap even began.
original
You can pass it using Angulars dependency injection:
var headers = ... // get the headers from the server
bootstrap(AppComponent, [{provide: 'headers', useValue: headers})]);
class SomeComponentOrService {
constructor(#Inject('headers') private headers) {}
}
or provide prepared BaseRequestOptions directly like
class MyRequestOptions extends BaseRequestOptions {
constructor (private headers) {
super();
}
}
var values = ... // get the headers from the server
var headers = new MyRequestOptions(values);
bootstrap(AppComponent, [{provide: BaseRequestOptions, useValue: headers})]);
In Angular2 final release, the APP_INITIALIZER provider can be used to achieve what you want.
I wrote a Gist with a complete example: https://gist.github.com/fernandohu/122e88c3bcd210bbe41c608c36306db9
The gist example is reading from JSON files but can be easily changed to read from a REST endpoint.
What you need, is basically:
a) Set up APP_INITIALIZER in your existent module file:
import { APP_INITIALIZER } from '#angular/core';
import { BackendRequestClass } from './backend.request';
import { HttpModule } from '#angular/http';
...
#NgModule({
imports: [
...
HttpModule
],
...
providers: [
...
...
BackendRequestClass,
{ provide: APP_INITIALIZER, useFactory: (config: BackendRequestClass) => () => config.load(), deps: [BackendRequestClass], multi: true }
],
...
});
These lines will call the load() method from BackendRequestClass class before your application is started.
Make sure you set "HttpModule" in "imports" section if you want to make http calls to the backend using angular2 built in library.
b) Create a class and name the file "backend.request.ts":
import { Inject, Injectable } from '#angular/core';
import { Http } from '#angular/http';
import { Observable } from 'rxjs/Rx';
#Injectable()
export class BackendRequestClass {
private result: Object = null;
constructor(private http: Http) {
}
public getResult() {
return this.result;
}
public load() {
return new Promise((resolve, reject) => {
this.http.get('http://address/of/your/backend/endpoint').map( res => res.json() ).catch((error: any):any => {
reject(false);
return Observable.throw(error.json().error || 'Server error');
}).subscribe( (callResult) => {
this.result = callResult;
resolve(true);
});
});
}
}
c) To read the contents of the backend call, you just need to inject the BackendRequestClass into any class of you choice and call getResult(). Example:
import { BackendRequestClass } from './backend.request';
export class AnyClass {
constructor(private backendRequest: BackendRequestClass) {
// note that BackendRequestClass is injected into a private property of AnyClass
}
anyMethod() {
this.backendRequest.getResult(); // This should return the data you want
}
}
Let me know if this solves your problem.
Instead of having your entry point calling bootstrap itself, you could create and export a function that does the work:
export function doBootstrap(data: any) {
platformBrowserDynamic([{provide: Params, useValue: new Params(data)}])
.bootstrapModule(AppModule)
.catch(err => console.error(err));
}
You could also place this function on the global object, depending on your setup (webpack/SystemJS). It also is AOT-compatible.
This has the added benefit to delay the bootstrap, whenit makes sense. For instance, when you retrieve this user data as an AJAX call after the user fills out a form. Just call the exported bootstrap function with this data.
The only way to do that is to provide these values when defining your providers:
bootstrap(AppComponent, [
provide(RequestOptions, { useFactory: () => {
return new CustomRequestOptions(/* parameters here */);
});
]);
Then you can use these parameters in your CustomRequestOptions class:
export class AppRequestOptions extends BaseRequestOptions {
constructor(parameters) {
this.parameters = parameters;
}
}
If you get these parameters from an AJAX request, you need to bootstrap asynchronously this way:
var appProviders = [ HTTP_PROVIDERS ]
var app = platform(BROWSER_PROVIDERS)
.application([BROWSER_APP_PROVIDERS, appProviders]);
var http = app.injector.get(Http);
http.get('http://.../some path').flatMap((parameters) => {
return app.bootstrap(appComponentType, [
provide(RequestOptions, { useFactory: () => {
return new CustomRequestOptions(/* parameters here */);
}})
]);
}).toPromise();
See this question:
angular2 bootstrap with data from ajax call(s)
Edit
Since you have your data in the HTML you could use the following.
You can import a function and call it with parameters.
Here is a sample of the main module that bootstraps your application:
import {bootstrap} from '...';
import {provide} from '...';
import {AppComponent} from '...';
export function main(params) {
bootstrap(AppComponent, [
provide(RequestOptions, { useFactory: () => {
return new CustomRequestOptions(params);
});
]);
}
Then you can import it from your HTML main page like this:
<script>
var params = {"token": "#User.Token", "xxx": "#User.Yyy"};
System.import('app/main').then((module) => {
module.main(params);
});
</script>
See this question: Pass Constant Values to Angular from _layout.cshtml.

Ng2-table not working with latest Angular2 version

I am currently using Angular2 for my application and now I want to add ng2-table to my component.
ng2-Table on Git
I am getting this error and couldn't help but ask:
angular2-polyfills.js:487 Unhandled Promise rejection: Template parse errors:
Can't bind to 'colums' since it isn't a known property of 'ng-table'.
1. If 'ng-table' is an Angular component and it has 'colums' input, then
verify that it is part of this module.
2. If 'ng-table' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA"
to the '#NgModule.schema' of this component to suppress this message.
("
</div>-->
<ng-table [ERROR ->][colums]="columns" [rows]="rows" > </ng-table>
<div class="">
"): DeviceOverviewComponent#18:10 ;
Zone: <root> ; Task: Promise.then ; Value: Error: Template parse errors:(…)
In my html I got this:
<ng-table [columns]="columns" [rows]="rows" > </ng-table>
My Component is this:
import { Component } from '#angular/core';
import { Router } from '#angular/router';
import { DeviceService } from '../services/device.service';
#Component({
selector: 'device-overview',
templateUrl: 'dist/html/deviceoverview.component.html',
providers: [DeviceService],
})
export class DeviceOverviewComponent {
devices: any;
columns: any;
rows: any;
constructor(private deviceService: DeviceService, private router: Router) {
}
loadDevices() {
this.deviceService.getDevices()
.then((data) => {
this.devices = data
this.rows = this.devices
})
}
goToDevice(deviceName: string) {
this.router.navigateByUrl('/devices/' + deviceName)
}
ngOnInit() {
this.columns = [
{ title: "test", name: "id" }]
this.loadDevices();
}
}
And my app.module is this:
import { NgModule } from '#angular/core';
import { LocationStrategy, HashLocationStrategy } from '#angular/common';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { Ng2TableModule } from 'ng2-table/ng2-table';
import { AppComponent } from './components/app.component';
import { DeviceOverviewComponent } from './components/deviceoverview.component'
import { DeviceService } from './services/device.service';
import { routing } from './app.routing';
#NgModule({
imports: [
Ng2TableModule,
BrowserModule,
FormsModule,
HttpModule,
routing,
],
declarations: [
DeviceOverviewComponent,
AppComponent,
],
providers:
[
{provide: LocationStrategy, useClass: HashLocationStrategy},
DeviceService,
],
bootstrap: [AppComponent]
})
export class AppModule { }
Does anybody know anything about the Usage of ng2-table? Or is there a valid alternative, since the demo page/usage documentation is not available by now?
I found some alternatives, but lots of them had their last commit a long time ago, which might be a problem, since I am always using latest Angular2.
Thanks for reading and any hel is appreciated!
EDIT:
I've made it to the next step!
I needed to add
import {CUSTOM_ELEMENTS_SCHEMA} from '#angular/core'
#NgModule({ ...,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
within my app.module.ts
Now I am getting the table header with the "test" column and the ID property of my row data is displayed correctly.
Even the demo from ng2-table didn't have that import.
I guess docs and demos arent made for newbes nowadays. :/
i see a typo in your html:
[colums]="columns"
It should be
[columns]="columns"
You're missing n
Plunker Example (I also tried it on local machine and it works)
You shouldn't use CUSTOM_ELEMENTS_SCHEMA
systemjs.config.js
map: {
...
'ng2-table': 'npm:ng2-table'
},
packages: {
...
'ng2-table': {
defaultExtension: 'js'
}
}
After long time I close this issue.
In my case I have these structure:
src
--app
-- app.module
-- TravelPlan
-- travel-plan.module
-- test.component
So, I was trying put the ng2-smart-table in app.module, but I was wrong. The correct is put in travel-plan.module.