I am practicing Angular by doing simple project. I see all Q&A on SO which is quite similar with my problem. Reason is that I am trying to display the async data before it initialized into articles variable, but I have tried *ngIf and async pipe.
myService
public getArticlesByCategory(): Observable<any> {
return this.request.get(this.categoryURL)
}
myComponent.ts
public articles: any[] = [];
constructor(
private articleService: ArticlesService
) { }
ngOnInit(): void {
this.articleService.getArticlesByCategory().subscribe({
next: (data) => {
this.articles = data.articles;
console.log(this.articles)
},
error: (error) => {
console.log(error);
}
})
}
template
<div *ngIf="articles">
<div *ngFor="let article of articles">
<p>{{article.title}}</p>
</div>
</div>
After Reviewing your code I found following errors:-
In app.routing.module.ts in rediretTo add pathMatch:'full'
const routes: Routes = [
{ path: '', redirectTo: 'articles', pathMatch: 'full' },
{ path: 'articles', component: ArticlesComponent },
];
In app.module.ts add ArticlesComponent in declaration
#NgModule({
declarations: [AppComponent, NavbarComponent, ArticlesComponent],
imports: [
// CommonModule,
BrowserModule,
RouterModule,
HttpClientModule,
AppRoutingModule,
],
providers: [ArticlesService],
bootstrap: [AppComponent],
})
Related
i want to show filter modal when i klik button, the modal is in My-Opportunities-Filter
but there is error "Uncaught (in promise): Error: No component factory found for MyOpportunitiesFilterPage. Did you add it to #NgModule.entryComponents?"
this is my-opportunities.module.ts
#NgModule({
declarations: [
MyOpportunitiesPage,
MyOpportunitiesFilterPage
],
imports: [
IonicPageModule.forChild(MyOpportunitiesPage),
SuperTabsModule
],
exports:[
MyOpportunitiesPage
],
entryComponents: [
MyOpportunitiesFilterPage
],
})
export class MyOpportunitiesPageModule {}
this is my-opportunities.ts
#IonicPage()
#Component({
selector: 'page-my-opportunities',
templateUrl: 'my-opportunities.html',
})
export class MyOpportunitiesPage {
#ViewChild(Content) content: Content;
private filterPage: Modal;
constructor(
public navCtrl: NavController,
public navParams: NavParams,
public dataSerrvice : DataServiceProvider,
private modalCtrl: ModalController
) {
}
ionViewDidLoad() {
console.log('ionViewDidLoad MyOpportunitiesPage');
}
openTransaction() {
this.navCtrl.push('MyOpportunitiesFilterPage');
}
private filter() {
let filterPage: Modal = this.modalCtrl.create(MyOpportunitiesFilterPage, {
});
filterPage.present();
}
this is my-opportunities-filter.module.ts
#NgModule({
declarations: [
MyOpportunitiesFilterPage,
],
imports: [
IonicPageModule.forChild(MyOpportunitiesFilterPage),
],
})
export class MyOpportunitiesFilterPageModule {}
i already add myOpportunitiesFilterPage in declaration, entrycomponets, but it still not works, can u guys help me
i change my-opportunities.module like this, and its works
#NgModule({
declarations: [
MyOpportunitiesPage
//MyOpportunitiesFilterPage
],
imports: [
IonicPageModule.forChild(MyOpportunitiesPage),
SuperTabsModule
],
exports:[
MyOpportunitiesPage
//MyOpportunitiesFilterPage
],
entryComponents: [
MyOpportunitiesPage
//MyOpportunitiesFilterPage
],
providers: [
MyOpportunitiesFilterPage
]
})
export class MyOpportunitiesPageModule {}
I've recently upgrade to Angular 9.1.0-rc.2 and everything looks to be in a working order. I'm able to get the app served locally and on a server fine, however when running jasmine unit tests I'm getting the following error on random components every test:
Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'not-found'
Error: Cannot match any routes. URL Segment: 'not-found'
at ApplyRedirects.noMatchError (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/#angular/router/fesm2015/router.js:4327:1)
at CatchSubscriber.selector (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/#angular/router/fesm2015/router.js:4291:1)
at CatchSubscriber.error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/operators/catchError.js:29:1)
at MapSubscriber._error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/Subscriber.js:75:1)
at MapSubscriber.error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/Subscriber.js:55:1)
at MapSubscriber._error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/Subscriber.js:75:1)
at MapSubscriber.error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/Subscriber.js:55:1)
at MapSubscriber._error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/Subscriber.js:75:1)
at MapSubscriber.error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/Subscriber.js:55:1)
at ThrowIfEmptySubscriber._error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/Subscriber.js:75:1)
error properties: Object({ rejection: Error: Cannot match any routes. URL Segment: 'not-found', promise: [object Promise], zone: Zone({ _parent: Zone({ _parent: Zone({ _parent: Zone({ _parent: null, _name: '<root>', _properties: Object({ }), _zoneDelegate: ZoneDelegate({ _taskCounts: Object({ microTask: 0, macroTask: 0, eventTask: 0 }), zone: <circular reference: Object>, _parentDelegate: null, _forkZS: null, _forkDlgt: null, _forkCurrZone: null, _interceptZS: null, _interceptDlgt: null, _interceptCurrZone: null, _invokeZS: null, _invokeDlgt: null, _invokeCurrZone: null, _handleErrorZS: null, _handleErrorDlgt: null, _handleErrorCurrZone: null, _scheduleTaskZS: null, _scheduleTaskDlgt: null, _scheduleTaskCurrZone: null, _invokeTaskZS: null, _invokeTaskDlgt: null, _invokeTaskCurrZone: null, _cancelTaskZS: null, _cancelTaskDlgt: null, _cancelTaskCurrZone: null, _hasTaskZS: null, _hasTaskDlgt: null, _hasTaskDlgtOwner: null, _hasTaskCurrZone: null }) }), _name: 'ProxyZone', _properties: Object({ ProxyZo ...
Here is how I've setup my routes:
app-routing.module.ts
import { MetaGuard } from '#ngx-meta/core';
import { UserModule } from './modules/user/user.module';
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { LoggedInGuard } from 'ngx-auth-firebaseui';
import { AdminGuard } from '#shared/guards/admin.guard';
import { CourseModule } from './modules/course/course.module';
import { AdminModule } from './modules/admin/admin.module';
import { PagesModule } from './pages/pages.module';
const routes: Routes = [
{
path: '',
loadChildren: async (): Promise<PagesModule> =>
import('./pages/pages.module').then((m: { PagesModule: PagesModule }) => m.PagesModule)
},
{
canActivateChild: [MetaGuard],
path: 'admin',
loadChildren: async (): Promise<AdminModule> =>
import('./modules/admin/admin.module').then((m: { AdminModule: AdminModule }) => m.AdminModule),
canActivate: [LoggedInGuard, AdminGuard]
},
{
path: 'course',
loadChildren: async (): Promise<CourseModule> =>
import('./modules/course/course.module').then((m: { CourseModule: CourseModule }) => m.CourseModule),
data: {
title: 'Course'
}
},
{
path: '**',
redirectTo: '/not-found',
data: {
title: 'Page Not Found'
}
}
];
#NgModule({
imports: [
RouterModule.forRoot(routes, {
scrollPositionRestoration: 'enabled'
})
],
exports: [RouterModule]
})
export class AppRoutingModule {}
pages-routing.module.ts
import { NotFoundComponent } from './not-found/not-found.component';
import { HomeComponent } from './home/home.component';
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
const routes: Routes = [
{
path: '',
component: HomeComponent
},
{
path: 'not-found',
component: NotFoundComponent
}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class PagesRoutingModule {}
app.module.ts
#NgModule({
declarations: [AppComponent],
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
HttpClientModule,
BrowserAnimationsModule,
MetaModule.forRoot({
provide: MetaLoader,
useFactory: metaFactory
}),
FirebaseModule,
SharedModule,
Angulartics2Module.forRoot({
gst: {
trackingIds: [environment.googleAnalytics]
}
})
],
bootstrap: [AppComponent]
})
In the components that actually call this route:
this.router.navigate(['not-found']);
Things I've tried:
Remove Async calls in Route
LazyLoad Children: loadChildren: './modules/course/course.module#CourseModule'
Set this.router.navigate(['/not-found'])
Loaded the NotFoundComponent directly in the main app-routing.module.ts
When I comment out any component that uses that route, the unit tests work fine.
Note that when I serve the app, I'm able to get to the not-found page. I'm kinda stuck on this, and would appreciate any hints on what could be causing this.
It looks like I was able to solve the issue thanks to the answer here: https://stackoverflow.com/a/45315961/1432248
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes([{ path: 'not-found', component: NotFoundComponent }]),
...,
],
declarations: [..., NotFoundComponent],
}).compileComponents();
}));
Edit your RouterTestingModule and use withRoutes and add the path and component of the route that's missing. The original answer explains in detail on why this is happening.
I have a lazy loading Angular 6 app that uses ngrx. I have an:
app.module.ts
shared.module.ts
core.module.ts
The core module has things like the footer and header. There are no store/ngrx related stuff here, but the unit tests for the header (that were working before implementing ngrx) keep failing with the following error:
StaticInjectorError(Platform: core)[StoreFeatureModule -> ReducerManager]:
NullInjectorError: No provider for ReducerManager!
The only thing I can think of is that the StoreModule is not imported into the CoreModule. But should it? Why are the tests failing when the header has nothing to do with state?
app.module.ts
#NgModule({
declarations: [
AppComponent,
LoginComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
CoreModule,
SharedModule.forRoot(),
StoreModule.forRoot({}),
EffectsModule.forRoot([]),
!environment.production ? StoreDevtoolsModule.instrument({
maxAge: 5 // retains last 5 states
}) : []
],
providers: [],
bootstrap: [ AppComponent ]
})
core.module.ts
#NgModule({
imports: [
CommonModule,
],
exports: [
CommonModule,
HeaderComponent,
FooterComponent
],
declarations: [
HeaderComponent,
FooterComponent,
]
})
shared.module.ts
#NgModule({
imports: [
CommonModule,
HttpClientModule
],
exports: [
CommonModule,
MyComponent
],
declarations: [ MyComponent]
})
export class SharedModule {
** header.component.spec.ts**
describe('HeaderComponent', () => {
let component: HeaderComponent;
let fixture: ComponentFixture<HeaderComponent>;
let debugEl: DebugElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
ProductsModule,
CustomersModule
],
declarations: [ HeaderComponent ],
providers: [
{ provide: myService, useValue: new MyService() },
],
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
debugEl = fixture.debugElement;
fixture.detectChanges();
});
Because your component uses the NgRx store, you also have to import the store inside the TestBed.
import { Store, StoreModule } from '#ngrx/store';
describe('test:', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HeldMessagesTabsPageModule,
StoreModule.forRoot(
{
messagesRoot: combineReducers(reducers.reducers)
},
{
initialState: { messagesRoot: { messagesRoot: { template: templateInitialState } } }
}
)
],
const store: Store<reducers.State>;
}
beforeEach(() => {
store = TestBed.get(Store);
spyOn(store, 'dispatch').and.callThrough();
});
I am trying to inject services in my angular 2 applications however the service is undefined when i call canactivate() in angular/router . How can i inject a service before canactivate() is called.
enter image description here
app.routing.ts
const appRoutes: Routes = [
{
path: '',
component: HomeComponent,
canActivate: ['AuthGuardService']
},
{
path: 'login',
component: LoginComponent,
outlet: 'popup'
},
// otherwise redirect to home
{path: '**', redirectTo: ''}
];
export const appRoutingProviders: any[] = [
{provide: "AuthGuardService", useValue: AuthGuardService}
];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
auth.guard.service.ts
import {Injectable, Inject} from '#angular/core';
import {AuthService} from "./auth.service";
import {Router, CanActivate} from "#angular/router";
import {Observable} from "rxjs";
#Injectable()
export class AuthGuardService implements CanActivate {
constructor(#Inject(AuthService) private auth, #Inject(Router) private router) {
}
canActivate() : Observable<boolean> | boolean{
if(this.auth.loggedIn()) {
return true;
}
this.router.navigate([{outlets: {popup: 'login'}}]);
return false;
}
}
app.module.ts
#NgModule({
declarations: [],
imports: [ routing ]
providers: [
appRoutingProviders,
...AUTH_PROVIDERS,
AuthService,
AuthGuardService,
HttpService,
{
provide: AuthHttp,
useFactory: AuthHttpServiceFactory,
deps: [Http, RequestOptions]
},
IndicesEffectsService,
DialogServiceService
],
bootstrap: [AppComponent]
})
export class AppModule {
}
you'll need to expose your routes as a module
try this:
const appRoutes: Routes =
[
{
path: '',
component: HomeComponent,
canActivate: [AuthGuardService] // <- no quotes
},
{
path: 'login',
component: LoginComponent,
outlet: 'popup'
},
// otherwise redirect to home
{path: '**', redirectTo: ''}
];
#NgModule
({
imports: [ RouterModule.forRoot(appRoutes)],
exports: [ RouterModule],
providers: [ AuthGuardService ] // <- provide guard
})
export class AppRoutingModule {}
then in your AppModule
#NgModule({
declarations: [],
imports: [ AppRoutingModule ] // <- import module here
providers: [
appRoutingProviders,
...AUTH_PROVIDERS,
AuthService,
// AuthGuardService, // <- no need for this
HttpService,
{
provide: AuthHttp,
useFactory: AuthHttpServiceFactory,
deps: [Http, RequestOptions]
},
IndicesEffectsService,
DialogServiceService
],
bootstrap: [AppComponent]
})
export class AppModule {
}
I have a simple ionic form:
<ion-header>
<ion-navbar>
<ion-title>Foo</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<form [formGroup]="fooForm">
<ion-item>
<ion-label floating>Name</ion-label>
<ion-input formControlName="name" type="text"></ion-input>
</ion-item>
</form>
<button ion-button full color="primary" (click)="save()">Save</button>
</ion-content>
and a page component:
import { Component } from '#angular/core';
import { FormBuilder, FormGroup } from '#angular/forms';
#Component({
selector: 'fo-page-foo',
templateUrl: './foo.html'
})
export class FooPage {
fooForm: FormGroup;
constructor(public formBuilder: FormBuilder) {
}
ngOnInit() {
this.fooForm = this.formBuilder.group({
name: ['']
});
}
public save() {
console.log(this.fooForm.value);
}
}
and a test:
import { FooPage } from './foo';
import { TestBed, ComponentFixture } from '#angular/core/testing';
import { CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '#angular/core';
import { FormsModule, ReactiveFormsModule } from "#angular/forms";
import { Form } from 'ionic-angular';
describe('Foo Page:', () => {
let comp: FooPage;
let fixture: ComponentFixture<FooPage>;
let de: DebugElement;
beforeEach(() => {
TestBed.configureTestingModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [FooPage],
providers: [Form],
imports: [FormsModule, ReactiveFormsModule],
});
fixture = TestBed.createComponent(FooPage);
fixture.detectChanges();
comp = fixture.componentInstance;
de = fixture.debugElement;
comp.ngOnInit();
});
describe('.constructor()', () => {
it('Should be defined', () => {
expect(comp).toBeDefined();
});
});
});
project and test structure is based on https://github.com/marcoturi/ionic-boilerplate. The test fails due to error: No value accessor for form control.
I was trying various approaches yet it seems that combination of Ionic specifics and recent Angular 4 makes it requiring some additional configuration to be added and some of the existing solutions are no longer valid due to changes in Angular.
I hit this problem two days ago and thanks to isolating it to post on SO was able to get to the solution base on slightly similar question
Main point is to add IonicModule to imports yet this triggers bunch of other Ionic imports:
import {
App, Platform, Config, Keyboard,
Form, IonicModule, DomController
} from 'ionic-angular';
import {
mockConfig, mockDomController, MockPlatform, mockPlatform
} from 'ionic-angular/util/mock-providers';
and so updated beforeEach should start with
TestBed.configureTestingModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [FooPage],
providers: [
App,
Form,
Keyboard,
{ provide: Platform, useClass: MockPlatform },
{ provide: DomController, useValue: mockDomController(mockPlatform()) },
{ provide: Config, useValue: mockConfig() },
],
imports: [
FormsModule,
IonicModule,
ReactiveFormsModule
],
});
PR with the above example got already merged to https://github.com/marcoturi/ionic-boilerplate.