Expected spy navigate to have been called - javascript

I have created a route after user logged-in in my angular app (Angular 8). now am trying to write a test case. But its giving below error.
route (/profile) page was not able to call.
Expected spy navigate to have been called with:
[ [ '/profile' ] ]
but it was never called.
login.component.js
import { Component, OnInit } from '#angular/core';
import { UserService } from '../../services/user.service';
import { User } from '../../models/user';
import { Router } from '#angular/router';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
user: User = new User();
errorMessage: string;
constructor(private userService: UserService, private router: Router){ }
ngOnInit(): void {
if(this.userService.currentUserValue){
this.router.navigate(['/home']);
return;
}
}
login() {
this.userService.login(this.user).subscribe(data => {
this.router.navigate(['/profile']);
}, err => {
this.errorMessage = "Username or password is incorrect.";
});
}
}
login.component.spec.ts
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '#angular/common/http/testing';
import { LoginComponent } from './login.component';
import { UserService } from 'src/app/services/user.service';
import { Router } from '#angular/router';
import { FormsModule } from '#angular/forms';
import { ExpectedConditions } from 'protractor';
import { DebugElement } from '#angular/core';
import { RouterTestingModule } from '#angular/router/testing';
import { HomeComponent } from '../home/home.component';
import { ProfileComponent } from '../profile/profile.component';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
let debugElement: DebugElement;
let location, router: Router;
let mockRouter;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ HttpClientTestingModule, FormsModule ],
declarations: [ LoginComponent, ProfileComponent ],
providers: [UserService]
})
.compileComponents();
}));
beforeEach(() => {
mockRouter = { navigate: jasmine.createSpy('navigate') };
TestBed.configureTestingModule({
imports: [RouterTestingModule.withRoutes([
{ path: 'profile', component: ProfileComponent }
])],
declarations: [LoginComponent, ProfileComponent],
providers: [
{ provide: Router, useValue: mockRouter},
]
});
});
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
debugElement = fixture.debugElement;
});
it('should go profile ', async(() => {
fixture.detectChanges();
component.login();
expect(mockRouter.navigate).toHaveBeenCalledWith(['/profile']);
}));
});

Why are you configuringTestingModule twice?
You should mock userService.
Try:
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '#angular/common/http/testing';
import { LoginComponent } from './login.component';
import { UserService } from 'src/app/services/user.service';
import { Router } from '#angular/router';
import { FormsModule } from '#angular/forms';
import { ExpectedConditions } from 'protractor';
import { DebugElement } from '#angular/core';
import { RouterTestingModule } from '#angular/router/testing';
import { HomeComponent } from '../home/home.component';
import { ProfileComponent } from '../profile/profile.component';
import { of } from 'rxjs'; // import of from rxjs
import { throwError } from 'rxjs'; // import throwError
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
let debugElement: DebugElement;
let mockUserService = jasmine.createSpyObj('userService', ['login']);
mockUserService.currentUserValue = /* mock currentUserValue to what it should be */
let router: Router;
beforeEach(async(() => {
// I don't think you need HttpClientTestingModule or maybe FormsModule
TestBed.configureTestingModule({
imports: [ HttpClientTestingModule, FormsModule, RouterTestingModule.withRoutes([
{ path: 'profile', component: ProfileComponent }
])],
declarations: [LoginComponent, ProfileComponent],
providers: [{ provide: UserService, useValue: mockUserService }]
})
.compileComponents();
}));
beforeEach(() => {
router = TestBed.get(Router); // remove the let here !!!!
spyOn(router, 'navigate'); // spy on router navigate
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
debugElement = fixture.debugElement;
});
it('should go profile ', async(() => {
fixture.detectChanges();
mockUserService.login.and.returnValue(of({})); // mock login method on userService when it is called
component.login();
expect(router.navigate).toHaveBeenCalledWith(['/profile']);
}));
it('should set error message on error ', async(() => {
fixture.detectChanges();
mockUserService.login.and.returnValue(throwError('Error')); // mock login method on userService when it is called
component.login();
expect(component.errorMessage).toBe('Username or password is incorrect.');
}));
});

Related

How to fix unsafe value used in a resource URL context in Angular unit test using jest

I got below error while writing the unit test in Angular using Jest. I have gone through all the similar suggestions here in stackoverflow, but none were helpful.
Error: unsafe value used in a resource URL context (see https://g.co/ng/security#xss) Jest
Below is the code from test file for your review.
import { CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
import { ComponentFixture, TestBed } from '#angular/core/testing';
import { RouterTestingModule } from '#angular/router/testing';
import { HttpClientTestingModule } from '#angular/common/http/testing';
import { DomSanitizer, SafeResourceUrl } from '#angular/platform-browser';
import { MaterialModule } from '../../Material/material.module';
import { DashboardViewComponent } from './dashboard-view.component';
describe('DashboardViewComponent', () => {
let component: DashboardViewComponent;
let fixture: ComponentFixture<DashboardViewComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
RouterTestingModule,
HttpClientTestingModule,
MaterialModule,
],
declarations: [ DashboardViewComponent ],
providers: [{
provide: DomSanitizer,
useValue: {
bypassSecurityTrustResourceUrl: (): SafeResourceUrl => ''
}
}],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(DashboardViewComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
test('should create', () => {
// expect(component).toMatchSnapshot();
expect(component).toBeTruthy();
});
});
Thanks in advance.

route navigation is not working in angular 9

I am working on a login and home component in my angular app.
Login service is validating the username and password of the user.
After successful login, it should redirect user to the home page.
But router redirect is not working properly.
login component
import { Router } from '#angular/router';
import { Component, OnInit } from '#angular/core';
import { FormControl, FormGroup, Validators } from '#angular/forms';
import { User } from 'src/app/shared/models/user';
import { AuthService } from '../services/auth.service';
#Component({
selector: 'app-login',
templateUrl: './login.component.html'
})
export class LoginComponent implements OnInit {
userName: FormControl;
password: FormControl;
loginFormGroup: FormGroup;
loginError: boolean;
errorMessage: string;
messageString: string;
constructor(private router: Router, private authService: AuthService) { }
ngOnInit() {
this.userName = new FormControl("", [Validators.required]);
this.password = new FormControl("", [Validators.required]);
this.loginFormGroup = new FormGroup({
userName: this.userName,
password: this.password
});
}
login() {
this.loginError = false;
if (this.loginFormGroup.valid) {
let user: User = new User();
user.userId = this.userName.value;
user.password = this.password.value;
this.authService.login(user)
.subscribe(res =>
{
console.log(res)
this.router.navigate(["home"])
console.log("res")
},
error =>
{
console.log(error)
});
}
}
}
and login service
import { Injectable } from "#angular/core";
import { Router } from "#angular/router";
import { Observable } from "rxjs";
import { share } from "rxjs/operators";
import { environment} from 'src/environments/environment';
import { HttpClient, HttpParams, HttpHeaders} from "#angular/common/http";
import { User } from 'src/app/shared/models/user';
#Injectable({ providedIn: "root" })
export class AuthService {
user: User;
resp=401;
get userDetail(): User {
return this.user;
}
constructor(
private router: Router,
private http: HttpClient
) {
}
login(user: User): Observable<any> {
var formData = new FormData();
formData.append("userId", user.userId);
formData.append("password", user.password);
return this.http.get<any>(url+"Validate_Login_User",{
headers: new HttpHeaders(),
params: new HttpParams().set("User_Id","user.userId")
})
}
}
routes
import { NgModule } from "#angular/core";
import { Routes, RouterModule } from "#angular/router";
import { AuthGuard } from "./authentication/services/auth.guard";
import { LoginComponent } from "./authentication/login/login.component";
import { LayoutComponent } from "./shared/components/layout/layout.component";
import { PageNotFoundComponent } from "./shared/components/page.not.found.component";
import { MenuComponent } from './menu/menu.component';
const routes: Routes = [
{ path: "login", component: LoginComponent },
{
path: "home",
component: HomeComponent,
canActivate: [AuthGuard],
children: [
{
//childroutes
},
{
//childroutes
},
],
},
{ path: "**", component: PageNotFoundComponent },
{ path: "Menu", component: MenuComponent}
];
#NgModule({
imports: [
RouterModule.forRoot(routes, {
onSameUrlNavigation: "ignore",
useHash: true,
}),
],
exports: [RouterModule],
})
export class AppRoutingModule {}
console log in login component
even though the console is printing success, route navigate is not happening and its still in login page
replace your code with the following piece of code, that should work.
this.loginError = false;
if (this.loginFormGroup.valid) {
let user: User = new User();
user.userId = this.userName.value;
user.password = this.password.value;
this.authService.login(user)
.subscribe(res =>
{
console.log(res)
this.router.navigate(["/home"])
console.log("res")
},
error =>
{
console.log(error)
});
}
}
Edited:
Please replace your ngModule with the below code:
#NgModule({
imports: [
RouterModule.forRoot(routes, {
useHash: true,
}),
],
exports: [RouterModule],
})
Try this.
this.router.navigateByUrl('/home');

Error: Trying to get the AngularJS injector before it being set

I am testing an angular 7 component that uses angular js components inside.
I am using jasmine and karma for testing.
I am getting
Angular Hybrid - **Error: Trying to get the AngularJS injector before it being set.** when I am running the ng test my-app-name.
app-module-ts -
import { BrowserModule } from '#angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '#angular/core';
import { UpgradeModule, downgradeComponent } from '#angular/upgrade/static';
import { AppComponent } from './app.component';
import { BusyOverlayModule } from '../../../app-shared/src/lib/busy-overlay/busy-overlay.module';
import { L10nTranslationModule } from '../../../app-shared/src/lib/l10n-translation/l10n-translation.module';
import { LocalizationService } from '../../../app-shared/src/lib/l10n-translation/localization.service';
import { WatchlistModule } from './watchlist/watchlist.module';
import oprRtsmViewPickerModuleName
from '../../../../../../shared/shared-html/js/directives/oprRtsmViewPicker/oprRtsmViewPicker.module.js';
import oprTableFooterModuleName
from '../../../../../../shared/shared-html/js/directives/oprTableFooter/oprTableFooter.module.js';
import oprContextPanelModuleName
from '../../../../../../shared/shared-html/js/directives/oprContextPanel/oprContextPanel/oprContextPanel.module.js';
import { FilterFactory } from 'angular';
import oprPopupServiceModuleName from '../../../../../../shared/shared-html/js/services/oprPopup.service';
import ciContextDataServiceModuleName from '../../../../../../shared/shared-html/js/services/ciContextData.service';
import watchlistOptionsLauncherComponent from './watchlist/options-menu/watchlistOptionsLauncherNg1';
import oprLocalizationUtil from '../../../../../../shared/shared-html/js/utils/oprLocalizationUtil';
import appConstantsUtil from '../../../../../../shared/shared-html/js/utils/appConstantsUtil';
import { setAngularJSGlobal } from '#angular/upgrade/static';
import { oprContextPanelApiServiceProvider } from '../../../ng1-adapters/adapters/opr-conext-panel-api-provider';
import { ciContextDataServiceProvider } from '../../../ng1-adapters/adapters/opr-conext-data-api-provider';
import { Oprl10nPipe } from '../../../app-shared/src/lib/l10n-translation/oprl10n.pipe';
declare const angular: angular.IAngularStatic;
setAngularJSGlobal(angular);
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
UpgradeModule,
BusyOverlayModule,
L10nTranslationModule,
WatchlistModule
],
providers: [
{
provide: APP_INITIALIZER,
useFactory: onAppInit,
multi: true
},
oprContextPanelApiServiceProvider,
ciContextDataServiceProvider,
Oprl10nPipe
],
entryComponents: [
AppComponent
]
})
export class AppModule {
constructor(private upgrade: UpgradeModule, private localizationService: LocalizationService) { }
/**
* bootstrap hybrid AngularJS/Angular application with downgraded root Angular component
*/
ngDoBootstrap() {
const ng1L10nfilterFactory: angular.Injectable<FilterFactory> = function () {
return (key) => {
return oprLocalizationUtil.getLocalizedString(key);
};
};
const ng1RootModule = angular.module('ng1-root', [
oprPopupServiceModuleName,
oprRtsmViewPickerModuleName,
oprTableFooterModuleName,
oprContextPanelModuleName,
ciContextDataServiceModuleName
]).directive('oprRoot', downgradeComponent({component: AppComponent})).filter('oprL10n', ng1L10nfilterFactory)
.component('oprOptionsMenuLauncher', watchlistOptionsLauncherComponent);
this.localizationService.setOprLocalizeUtilObj(oprLocalizationUtil);
this.upgrade.bootstrap(document.body, [ng1RootModule.name], {strictDi: false});
}
}
export function onAppInit(): () => Promise<any> {
return (): Promise<any> => {
return new Promise((resolve, reject) => {
const appConstants = appConstantsUtil.appConstants;
/**
* For Testing, Replace this appConstants.locale.toLowerCase() code with en
*/
oprLocalizationUtil.init(appConstants.locale.toLowerCase(), appConstants.staticContext, [
'opr-watchlist',
'opr-common'
], function () {
resolve(true);
});
});
};
}
app.component.ts -
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'opr-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
showBusyOverlay:boolean = true;
ngOnInit() {
this.showBusyOverlay = false;
}
}
app.component.spec.ts -
import { TestBed, ComponentFixture, async } from '#angular/core/testing';
import * as angular from '#angular/upgrade/src/common/angular1';
import { UpgradeModule, setAngularJSGlobal } from '#angular/upgrade/static';
import { AppComponent } from './app.component';
import { AppSharedModule } from "../../../app-shared/src/lib/app-shared.module";
import { WatchlistComponent } from './watchlist/watchlist.component';
import { WatchlistFooterComponent } from './watchlist/watchlist-footer/watchlist-footer.component';
import { WatchlistHeaderComponent } from './watchlist/watchlist-header/watchlist-header.component';
import { WatchlistCardsComponent } from './watchlist/watchlist-cards/watchlist-cards.component';
import { WatchlistCardComponent } from "./watchlist/watchlist-cards/watchlist-card/watchlist-card.component";
import { WatchlistCardsModule } from './watchlist/watchlist-cards/watchlist-cards.module';
import { WatchlistModule } from './watchlist/watchlist.module';
import { ContextPanelApi } from 'shared/directives/oprContextPanel/oprContextPanel/oprContextPanelApi.service';
import { CiContextDataService } from '../../../../../../shared/shared-html/js/services/ciContextData.service';
import { CiContextMenuService } from '../../../app-shared/src/lib/ci-context-menu.service';
import { HttpClientModule, HttpClientXsrfModule } from '#angular/common/http';
import { Ng1AdaptersModule } from '../../../ng1-adapters/ng1-adapters.module';
import { FormsModule } from '#angular/forms';
import { BusyOverlayModule } from '../../../app-shared/src/lib/busy-overlay/busy-overlay.module';
import { L10nTranslationModule } from '../../../app-shared/src/lib/l10n-translation/l10n-translation.module';
import '../../../../../../shared/shared-html/test/config/index-mock.js';
import { Oprl10nPipe } from "../../../app-shared/src/lib/l10n-translation/oprl10n.pipe";
import { of } from 'rxjs';
export class MockBusyOverlayModule {
}
export class MockContextPanelApi {
}
export class MockCiContextDataService {
}
export class MockCiContextMenuService {
}
export class Oprl10nPipeStub {
public get(key: any): any {
return of(key);
}
public transform(key: any): any {
return of(key);
}
}
setAngularJSGlobal(angular);
describe('AppComponent', () => {
window['getAppConstants'] = function () {
return JSON.stringify({
topazWebContext: "",
mashupParams: { uim_sourceId: "0" },
staticContext: "/base",
locale: "en-us",
oprWebContext: ""
});
};
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
UpgradeModule,
BusyOverlayModule,
HttpClientModule,
AppSharedModule,
// appConstantsUtil,
// WatchlistModule,
Ng1AdaptersModule,
L10nTranslationModule,
// WatchlistModule
// WatchlistCardsModule
],
providers: [
{ provide: Oprl10nPipe, useClass: Oprl10nPipeStub },
// { provide: BusyOverlayModule, useClass: MockBusyOverlayModule }
{ provide: ContextPanelApi, useClass: MockContextPanelApi },
{ provide: CiContextDataService, useClass: MockCiContextDataService },
{ provide: CiContextMenuService, useClass: MockCiContextMenuService },
// { provide: appConstantsUtil }
],
declarations: [
AppComponent,
WatchlistComponent,
WatchlistFooterComponent,
WatchlistHeaderComponent,
WatchlistCardComponent,
WatchlistCardsComponent
]
// imports: [
// WatchlistModule
// ]
}).compileComponents();
}));
beforeEach(() => {
window['getAppConstants'] = function () {
return JSON.stringify({
topazWebContext: "",
mashupParams: { uim_sourceId: "0" },
staticContext: "/base",
locale: "en-us",
oprWebContext: ""
});
};
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create the app', () => {
expect(component).toBeTruthy();
});
});
My angular js version is 1.6 and Angular 7, as I said I am testing angular 7 components that use angular js components.
I found some links on web -
Angular Hybrid Error: Trying to get the AngularJS injector before it being set
https://github.com/angular/angular/issues/23141
but no help. I am not able to find anything in the angular doc as well.
Please guide.
I solved this by adding
const upgrade = TestBed.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document);
const serviceWhichReliesonInjector =
to my beforeEach Method.
afterwards i could simply access the service by
TestBed.get(ServiceWhichReliesonInjector)

Can't display a component in AngularJS

I am building a small cinema website. My issue is that I have a list, when you click the listen a button is displayed with a function, when you click that function it should give you more details on the item you have clicked. I have tried to work through the Angular Tour of Heroes again but I can't get the details to show up.
https://i.imgur.com/mzUcalv.png
The above is what is seen, some details should be shown on the page but there is no error relevant to why it is not showing.
`import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { AppComponent } from './app.component';
import { DashboardComponent } from './dashboard.component';
import { HeroDetailComponent } from './hero-detail.component';
import { HeroesComponent } from './heroes.component';
import { HeroService } from './hero.service';
import { AccordionModule } from 'primeng/primeng';
import { AppRoutingModule } from './app-routing.module';
import { RatingModule} from 'primeng/primeng';
import { GalleriaModule } from 'primeng/primeng';
import { CinemaComponent} from './cinema.component';
import { ContactComponent } from './contact.component';
import { AgmCoreModule } from 'angular2-google-maps/core';
import { ReviewsComponent } from './reviews.component';
import { TabViewModule } from 'primeng/primeng';
import { CinemaService } from './cinema.service';
import { CinemaDetailComponent } from './cinema-detail.component';
#NgModule({
imports: [
BrowserModule,
FormsModule,
AppRoutingModule,
AccordionModule,
RatingModule,
GalleriaModule,
TabViewModule,
AgmCoreModule.forRoot({
apiKey: 'AIzaSyDmQWd7DM4PcMvkzp_uopvIkbyjPMWzHeM'
})
],
declarations: [
AppComponent,
DashboardComponent,
HeroDetailComponent,
HeroesComponent,
CinemaComponent,
ContactComponent,
ReviewsComponent,
CinemaDetailComponent
],
providers: [ HeroService, CinemaService ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
`
App Module
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { DashboardComponent } from './dashboard.component';
import { HeroesComponent } from './heroes.component';
import { HeroDetailComponent } from './hero-detail.component';
import { CinemaComponent } from './cinema.component';
import { ContactComponent } from './contact.component';
import { ReviewsComponent } from './reviews.component';
import { CinemaDetailComponent } from './cinema-detail.component';
const routes: Routes = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'detail/:id', component: HeroDetailComponent },
{ path: 'heroes', component: HeroesComponent },
{ path: 'cinema', component: CinemaComponent },
{ path: 'contact', component: ContactComponent },
{ path: 'reviews', component: ReviewsComponent },
{ path: 'detail/:id', component: CinemaDetailComponent}
];
#NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule {}
Cinema Detail Component
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute, Params } from '#angular/router';
import { Location } from '#angular/common';
import { Cinema } from './cinema';
import { CinemaService } from './cinema.service';
#Component({
moduleId: module.id,
selector: 'my-cinema-detail',
templateUrl: 'cinema-detail.component.html',
styleUrls: [ 'cinema-detail.component.css' ]
})
export class CinemaDetailComponent implements OnInit {
cinema: Cinema;
constructor(
private cinemaService: CinemaService,
private route: ActivatedRoute,
private location: Location
) {}
ngOnInit(): void {
this.route.params.forEach((params: Params) => {
let id = +params['id'];
this.cinemaService.getCinema(id)
.then(Cinema => this.cinema = Cinema);
});
}
goBack(): void {
this.location.back();
}
}
The HTML that should be displayed
<
div *ngIf="cinema">
<h2>{{cinema.name}} details!</h2>
<div>
<label>id: </label>{{cinema.id}}</div>
<div>
<label>name: </label>
<input [(ngModel)]="cinema.name" placeholder="name" />
</div>
<button (click)="goBack()">Back</button>
</div>
My cinema.component.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { CinemaDetailComponent } from './cinema-detail.component';
import { Cinema } from './cinema';
import { CinemaService } from './cinema.service';
#Component({
moduleId: module.id,
selector: 'my-cinema',
templateUrl: 'cinema.component.html',
styleUrls: [ 'cinema.component.css' ]
})
export class CinemaComponent implements OnInit {
cinemas: Cinema[];
selectedCinema: Cinema;
constructor(
private router: Router,
private cinemaService: CinemaService) { }
getCinemas(): void {
this.cinemaService.getCinemas().then(cinemas => this.cinemas = cinemas);
}
ngOnInit(): void {
this.getCinemas();
}
onSelect(cinema: Cinema): void {
this.selectedCinema = cinema;
}
gotoDetail(): void {
this.router.navigate(['/detail', this.selectedCinema.id]);
}
}
cinema.service.ts file
import { Cinema } from './cinema';
import { CINEMAS } from './mock-cinema';
import { Injectable } from '#angular/core';
#Injectable()
export class CinemaService {
getCinemas(): Promise<Cinema[]> {
return Promise.resolve(CINEMAS);
}
getHeroesSlowly(): Promise<Cinema[]> {
return new Promise<Cinema[]>(resolve =>
setTimeout(resolve, 2000)) // delay 2 seconds
.then(() => this.getCinemas());
}
getCinema(id: number): Promise<Cinema> {
return this.getCinemas()
.then(cinemas => cinemas.find(cinema => cinema.id === id));
}
}
Can anybody help figure out why it isn't displayed? I haven't posted the export class for Cinema which just contains an id:number and name:string or the array which is correct (as it displays the list to click on). Thanks for reading.

angular2 cannot navigate with router

I am trying to navigate to another route after users click a login button. But I can't understand what went wrong. Below is my login component.
import { Component, OnInit } from '#angular/core';
import { AngularFire, AuthProviders, AuthMethods } from 'angularfire2';
import { Router, ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
constructor(public af: AngularFire, private router: Router) {
this.af.auth.subscribe(auth => console.log(auth));
}
login() {
this.af.auth.login({
provider: AuthProviders.Google,
method: AuthMethods.Popup,
}).then(function(res) {
console.log('login success');
console.log(res.uid);
this.router.navigateByUrl('/main') // .then(r => console.log('then: ' + r))
.then(function(resw) {
console.log('has redirect');
})
.catch(err => console.error(err)) ;
console.log('afterward');
}).catch(err => console.error(err));
}
overrideLogin() {
this.af.auth.login({
provider: AuthProviders.Anonymous,
method: AuthMethods.Anonymous,
});
}
ngOnInit() {
}
}
<p>
login works!
</p>
<button (click)="login()">Login With Google</button>
<button (click)="overrideLogin()">Login Anonymously</button>
Here is my routes:
import { LoginComponent } from './login/login.component';
import { MainComponent } from './main/main.component';
import { ModuleWithProviders } from '#angular/core';
import { Routes, RouterModule } from '#angular/router' ;
const APP_ROUTES: Routes = [
{ path: 'login', component: LoginComponent },
{ path: '', pathMatch: 'full', redirectTo: '/login'},
{ path: 'main', component: MainComponent }
];
export const appRoutingProviders: any[] = [
];
export const APP_ROUTES_PROVIDER: ModuleWithProviders = RouterModule.forRoot(APP_ROUTES);
Here is the #NgModule:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { AppComponent } from './app.component';
// import routing
import { appRoutingProviders, APP_ROUTES_PROVIDER } from './app.routes' ;
#NgModule({
declarations: [
AppComponent,
LoginComponent,
MainComponent
],
imports: [
BrowserModule,
// AngularFireModule.initializeApp(firebaseConfig, myFirebaseAuthConfig), // angularfire setup
FormsModule,
HttpModule,
APP_ROUTES_PROVIDER
],
providers: [appRoutingProviders],
bootstrap: [AppComponent]
})
export class AppModule { }
I got the following error. Can someone please help let me know how to fix this?
TypeError: this is null Stack trace:
LoginComponent</LoginComponent.prototype.login/<#http://localhost:4200/main.bundle.js:70294:13
Zone$1</ZoneDelegate</ZoneDelegate.prototype.invoke#http://localhost:4200/main.bundle.js:69125:19
NgZoneImpl/this.inner<.onInvoke#http://localhost:4200/main.bundle.js:56178:28
Zone$1</ZoneDelegate</ZoneDelegate.prototype.invoke#http://localhost:4200/main.bundle.js:69124:19
Zone$1</Zone</Zone.prototype.run#http://localhost:4200/main.bundle.js:69018:24
scheduleResolveOrReject/<#http://localhost:4200/main.bundle.js:69384:52
Zone$1</ZoneDelegate</ZoneDelegate.prototype.invokeTask#http://localhost:4200/main.bundle.js:69158:23
NgZoneImpl/this.inner<.onInvokeTask#http://localhost:4200/main.bundle.js:56169:28
Zone$1</ZoneDelegate</ZoneDelegate.prototype.invokeTask#http://localhost:4200/main.bundle.js:69157:23
Zone$1</Zone</Zone.prototype.runTask#http://localhost:4200/main.bundle.js:69058:28
drainMicroTaskQueue#http://localhost:4200/main.bundle.js:69290:25
ZoneTask/this.invoke#http://localhost:4200/main.bundle.js:69230:25
Arrow Function(()=>) will resolve issue as every configuration is correct.
login() {
this.af.auth.login({
provider: AuthProviders.Google,
method: AuthMethods.Popup,
}).then((res)=> { //<----changed this line
console.log('login success');
console.log(res.uid);
this.router.navigateByUrl('/main') // .then(r => console.log('then: ' + r))
.then((resw)=> { //<----changed this line
console.log('has redirect');
})
.catch(err => console.error(err)) ;
console.log('afterward');
}).catch(err => console.error(err));
}
this is special in javascript, it depends how the function was called see How to access the correct `this` context inside a callback?.
In type script if you use a fat arrow => it'll cache the this for you eg this.af.auth.login({}).then((res) => {})

Categories

Resources