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
Related
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;
}
I am trying to convet my angular component so that it will run in both angular and non angular environment.
I have added my elements as export and added them to custom element list and entry component list so that they will be exported as custom elements.
Below is the code of my angular-liberary module exports
#NgModule({
imports: [
RouterModule,
CommonModule,
ReactiveFormsModule,
NgbModule.forRoot(),
CoreRoutingModule,
FontAwesomeModule
],
declarations: [
HeaderComponent,
FooterComponent,
AlertsComponent,
LoginComponent,
ProfileComponent,
PrivacyComponent,
ChangeLocationModelComponent,
CorouselComponent,
FilterPipe,
ContentLoadingComponent,
AutoScrollDirective,
ModelComponent
],
exports: [
HeaderComponent,
FooterComponent,
AlertsComponent,
LoginComponent,
ProfileComponent,
PrivacyComponent,
ChangeLocationModelComponent,
CorouselComponent,
ContentLoadingComponent,
AutoScrollDirective,
FontAwesomeModule
],
entryComponents: [
HeaderComponent,
FooterComponent,
AlertsComponent,
LoginComponent,
ProfileComponent,
PrivacyComponent,
ChangeLocationModelComponent,
CorouselComponent,
ContentLoadingComponent,
ModelComponent
]
})
export class CoreModule {
public static forRoot(): ModuleWithProviders {
return {
ngModule: CoreModule,
providers: [
AppService,
AlertService,
AppInitService,
AuthGuardService,
CoreService,
EncryptionService,
MapService,
NoAuthGuardService,
{
provide: WINDOW,
useFactory: windowFactory
},
UserService,
GoogleAnalyticsService
]
};
}
constructor(#Optional() #SkipSelf() parentModule: CoreModule, private injector: Injector) {
if (parentModule) {
throw new Error(
'CoreModule is already loaded. Import it in the AppModule only');
}
customElements.define('cfs-header', createCustomElement(HeaderComponent, {injector}));
customElements.define('cfs-footer', createCustomElement(FooterComponent, {injector}));
customElements.define('cfs-alert', createCustomElement(AlertsComponent, {injector}));
customElements.define('cfs-login', createCustomElement(LoginComponent, {injector}));
customElements.define('cfs-profile', createCustomElement(ProfileComponent, {injector}));
customElements.define('cfs-privacy', createCustomElement(PrivacyComponent, {injector}));
customElements.define('cfs-change-location-model', createCustomElement(ChangeLocationModelComponent, {injector}));
customElements.define('cfs-corousel', createCustomElement(CorouselComponent, {injector}));
customElements.define('cfs-content-loading', createCustomElement(ContentLoadingComponent, {injector}));
customElements.define('cfs-model', createCustomElement(ModelComponent, {injector}));
}
}
Then imported as forRoot() in app module.
When I import from npm packaged installed like below, it gives me below error
import {CoreModule} from '#candifood/core';
CoreModule.forRoot(),
// ERROR
DOMException: Failed to execute 'define' on 'CustomElementRegistry': this name has already been used with this registry
at new CoreModule (http://localhost:4200/main.js:1045:24)
at _createClass (http://localhost:4200/vendor.js:43333:20)
at _createProviderInstance$1 (http://localhost:4200/vendor.js:43303:26)
at initNgModule (http://localhost:4200/vendor.js:43239:32)
at new NgModuleRef_ (http://localhost:4200/vendor.js:43962:9)
at createNgModuleRef (http://localhost:4200/vendor.js:43951:12)
at Object.debugCreateNgModuleRef [as createNgModuleRef] (http://localhost:4200/vendor.js:45776:12)
at NgModuleFactory_.push../node_modules/#angular/core/fesm5/core.js.NgModuleFactory_.create (http://localhost:4200/vendor.js:46478:25)
at http://localhost:4200/vendor.js:39376:43
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:4200/polyfills.js:2704:26)
When I directly import them as internal module as below it gives below error.
import { CoreModule } from '../../projects/somemodule/core/src/lib/core.module';
CoreModule.forRoot(),
// ERROR
Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
at NgElementImpl.NgElement [as constructor] (elements.js:391)
at new NgElementImpl (elements.js:427)
at EmulatedEncapsulationDomRenderer2.push../node_modules/#angular/platform-browser/fesm5/platform-browser.js.DefaultDomRenderer2.createElement (platform-browser.js:1204)
at EmulatedEncapsulationDomRenderer2.push../node_modules/#angular/platform-browser/fesm5/platform-browser.js.EmulatedEncapsulationDomRenderer2.createElement (platform-browser.js:1312)
at DebugRenderer2.push../node_modules/#angular/core/fesm5/core.js.DebugRenderer2.createElement (core.js:11100)
at createElement (core.js:7823)
at createViewNodes (core.js:10062)
at callViewAction (core.js:10417)
at execComponentViewsAction (core.js:10336)
at createViewNodes (core.js:10129)
Still debugging, ay help will appreciate.
I am trying to change from a home page (ie localhost.com) to a another page (localhost.com/listing). The app builds properly but when I try to change the page, nothing happens.
I have followed mainly the tutorial, https://www.youtube.com/watch?v=L6ipgij-AUw.
Here is my full app.module.ts file:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { AppComponent } from './app.component';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { ListingsComponent } from './listings/listings.component';
#NgModule({
declarations: [
AppComponent,
ListingsComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
RouterModule.forRoot([
{
path: 'listing',
component: ListingsComponent
}
])
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
btnClick = function () {
this.router.navigate('/listing');
};
}
I am not sure whether the btnClick function is in the right place. I got the partial solution of this Q&A board but not sure its in the correct position. I have checked the listings component is working correctly by using . It says "listings works!" but still does so from the same home page (ideally this should be a blank white page with "listings works!", eg no nav-bar).
How should I route to a new page properly (ie no trace of the home page in /listing)? I cannot understand why this is happening because the listings.component.html does not include anything from the homepage.
For more information see: https://github.com/gf1721/directoryapp.
Depending on how large you are planning on making this application, you are better off with creating an routing module.
Step 1:
This will generate an app-routing module for you in your src/app folder.
ng g m app-routing
Step 2:
Open your app-routing module and import all of the components you want to be able to navigate too as well as routermodule and routes.
import { RouterModule, Routes } from '#angular/router';
import { DashboardComponent } from './dashboard/dashboard.component';
import { HomeComponent } from './home/home.component';
import { LoginComponent } from './login/login.component';
Step: 3
Add a constant with the routes setup:
const routes: Routes = [
{path: '', redirectTo: 'home', pathMatch: 'full'},
{path: 'home', component: HomeComponent},
{path: 'dashboard', component: DashboardComponent},
{path: 'login', component: LoginComponent},
];
Step 4
Add your routes to your imports and then export the router module:
#NgModule({
imports: [
CommonModule,
RouterModule.forRoot(routes)
],
exports: [RouterModule],
declarations: []
})
Step 5
Now in your template html file you can do the follow:
<button type="button" routerLink="/home">Go home</button>
<router-outlet></router-outlet>
And the content on "home" will appear where router-outlet is.
Change
From
btnClick = function () {
this.router.navigate('/listing');
};
To
btnClick () : void {
this.router.navigate('/listing');
}
Also the button should be on the component, you are placing it inside the module, which will anyway not work.
Place the button on the app component and bind the logic to navigate on the button click as mentioned above
My project is set up with Angular CLI, so it's built with webpack but the webpack config files are hidden.
I got two files, nl.json and fr.json, but get a 404 for both, even though it looks like it's going to the correct folder: http://localhost:4200/i18n/nl.json.
They have this structure:
{
"SEARCH_PAGE": {
"searchPerson": "Zoek een persoon",
"search": "Zoek"
}
}
In app.module:
...
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [Http]
}
}),
...
and
export function HttpLoaderFactory(http: Http) {
return new TranslateHttpLoader(http, "/i18n/", ".json");
}
I also include these in my sub module where I [try to] use the translation, with the difference of .forChild instead of .forRoot.
In my component:
constructor(translate: TranslateService) {
translate.addLangs(["nl", "fr"]);
translate.setDefaultLang('nl'); // this language will be used as a fallback when a translation isn't found in the current language
let browserLang: string = translate.getBrowserLang();
translate.use(browserLang.match(/nl|fr/) ? browserLang : 'nl');
}
Could it be something not linked to ngx-translate ?
When I use the pipe <h1>{{ 'SEARCH_PAGE.searchPerson' | translate}}</h1> I get nothing on the screen, when I use the directive <h1 translate]="'SEARCH_PAGE.searchPerson'"></h1> I get literally the string.
I had similar problem.
Everything worked fine locally but I was getting 404 errors when deployed app to Azure.
I tried to open /assets/i18n/.json in my browser and got the same error.
The issue was that .json files requred special MIME type configured on server.
The problem was resolved by adding web.config to the package.
1) create web.config file in app\src folder with following body:
<?xml version="1.0"?>
<configuration>
<system.webServer>
<staticContent>
<mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>
</system.webServer>
</configuration>
2) Include this file to the package by edditing angular.json
projects -> <your project> -> architect -> build -> options -> assets
Add src/web.config to the assets array
Example:
...
"assets": [
"src/favicon.ico",
"src/assets",
"src/web.config"
],
You can see more info here: https://devdays.com/2014/07/21/snippet-using-json-file-on-windows-iis-iis-express/
Just found the answer in #122 .
In angular-cli.json you have to include i18n in the assets array:
"apps": [
{
...
"assets": [
"assets",
"favicon.ico",
"i18n"
],
...
This works even if your i18n directory is not inside your assets directory.
EDIT: and now both the pipe and the directory work.
For anyone encountering a similar error where translation json files cannot be found by the HttpTranslateLoader, please see the following github issue:
https://github.com/ngx-translate/core/issues/921
In newer versions of Angular, Interceptors can interfere with the loading of the json asset files. The approach in the issue shows how to bypass interceptors for the translation files like this (quoted from the issue):
export function translateHttpLoaderFactory(httpBackend: HttpBackend): TranslateHttpLoader {
return new TranslateHttpLoader(new HttpClient(httpBackend));
}
...
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
deps: [HttpBackend],
useFactory: translateHttpLoaderFactory
}
}),
In my case I just change
export function HttpLoaderFactory(http: HttpClient){
return new TranslateHttpLoader(http, './assets/i18n/', '.json');}
For
export function HttpLoaderFactory(http: HttpClient){
return new TranslateHttpLoader(http, '../../assets/i18n/', '.json');}
it was only a rooting problem, so sometimes we should check the basics first.
Try to hoot default lang to translateService using APP_INITIALIZER:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '#angular/core';
import { FormsModule, Validators, ReactiveFormsModule } from '#angular/forms';
import { HttpClientModule, HttpClient } from '#angular/common/http';
import { TranslateModule, TranslateLoader, TranslateService } from '#ngx-translate/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { RouterInputService } from './services/router-input.service';
import { Observable } from 'rxjs/Observable';
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, '/private/lifeinsurance/assets/', '.json');
}
export function initTranslation(translate: TranslateService) {
return () => {
translate.setDefaultLang('en');
translate.use('en');
return Promise.resolve();
};
}
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateLoader),
deps: [HttpClient]
}
})
],
providers: [
{
'provide': APP_INITIALIZER,
'useFactory': initTranslation,
'deps': [TranslateService],
'multi': true
},
RouterInputService
],
bootstrap: [AppComponent]
})
export class AppModule { }
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.