Angular2 Routing no Hash even with HashLocationStrategy - angular2-routing

This is a follow up to Angular 2.0 router not working on reloading the browser
Even if I configure the router to use the HashLocationStrategy I still get the url paths without #. I follow exactly the Angular2 docs https://angular.io/docs/ts/latest/tutorial/toh-pt5.html
and set the location strategy as described here https://angular.io/docs/ts/latest/guide/router.html
My bootstrap:
import {bootstrap} from 'angular2/platform/browser';
import {provide} from 'angular2/core';
import {
ROUTER_PROVIDERS,
LocationStrategy,
HashLocationStrategy
} from 'angular2/router';
import {AppComponent} from './app.component';
bootstrap(AppComponent, [
ROUTER_PROVIDERS,
provide(LocationStrategy, { useClass: HashLocationStrategy })
]);
And the router config:
#RouteConfig([
{
path: '/detail/:id',
name: 'HeroDetail',
component: HeroDetailComponent
},
{
path: '/heroes',
name: 'Heroes',
component: HeroesComponent
},
{
path: '/dashboard',
name: 'Dashboard',
component: DashboardComponent,
useAsDefault: true
}
])
I'd expect to see a url like http://localhost/#/dashboard in the browser, but I get http://localhost/dashboard.
What am I missing?

Try to move the ROUTER_PROVIDER and provide(..)-stuff into your app.component.ts file.
In there you should paste it into the #Component.providers-Array.
For a more detailed answer have a look at this post, it solved my problem which seems to be close to yours:
https://stackoverflow.com/a/35879541/4977476

My understanding (which might be wrong, I am just beginning with Angular2) is that the useAsDefault acts as a redirect. But this isn't needed when using hash locations, since from the server's point of view, all pages are on '/' anyway.

The problem seems to be, that the LocationStrategy has to be defined within the providers array, as pointed out by SilverJan and KochFolie. See HashLocationStrategy not working as expected

it's works for me:
...
import { RouterModule, Routes } from '#angular/router';
import {
APP_BASE_HREF,
LocationStrategy,
HashLocationStrategy
} from '#angular/common';
...
const appRoutes: Routes = [
{ path: '', loadChildren: './user-profile/user-profile.module#UserProfileModule'},
...
];
#NgModule({
...
providers: [ { provide: APP_BASE_HREF, useValue: "/core/user" }, {provide: LocationStrategy, useClass: HashLocationStrategy}],
bootstrap: [AppComponent]
})
export class AppModule { }

Related

How to split app-routing.module.ts in multiple files in Angular 2?

Considering the image, I have a component (1) + module (2) + routing (3)(in "app-routing.module.ts"). To avoid too much code in "app-routing.module.ts", I want to move the routing code (3) in other file (suppose "product.routes.ts"). How can I do this considering I'm using Angular 2? Thanks!
This would be the AppComponentRoutingModule which I use, which can be extended with further files, usually that is one routes file per nested routing (to be imported in the corresponding module). The components and routes may vary, but it generally works alike this (guards skipped for the sake of brevity):
Create src/app/routes/app.routes.ts with content alike:
import { Routes } from '#angular/router';
import { ErrorPage } from 'src/app/pages/error/error.page';
export const appRoutes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' }, // main entry point.
{ path: 'home', loadChildren: () => import('src/app/pages/home/home.module').then(m => m.HomeModule) },
{ path: 'error/:id', component: ErrorPage, pathMatch: 'full' },
{ path: '**', redirectTo: '/error/404' }
];
The nested routes don't look much different, for example src/app/routes/home.routes.ts:
export const homeRoutes: Routes = [{
path: '',
component: HomePage,
children: [
...
]
}];
Create src/app/app.component.routing.module.ts with content alike:
import { NgModule } from '#angular/core';
import { PreloadAllModules, RouterModule } from '#angular/router';
import { appRoutes } from './routes/app.routes';
#NgModule({
imports: [
RouterModule.forRoot(appRoutes,{preloadingStrategy: PreloadAllModules})
],
exports: [ RouterModule ]
})
export class AppComponentRoutingModule {}
Then import AppComponentRoutingModule in app.module.ts:
import { RouterModule } from '#angular/router';
import { AppComponent } from 'src/app/app.component';
import { AppComponentRoutingModule } from 'src/app/app.component.routing.module';
...
#NgModule({
declarations: [ AppComponent ],
imports: [
RouterModule,
AppComponentRoutingModule,
...
],
bootstrap: [ AppComponent ]
})
export class AppModule {}
In order to enable verbose logging, enableTracing: true is your friend.

AngularFireAuth: Cannot read property 'GoogleAuthProvider' of undefined

I'm trying to do authentication with AngularFire. During ng serve, any attempt to instantiate an auth provider (such as firebase.auth.GoogleAuthProvider) results in a crash. I'm doing the exact same thing as the AngularFireAuth quickstart example. Am I missing something?
My app is quite minimal:
// app.component.ts
import { Component } from "#angular/core";
import { AngularFireAuth } from '#angular/fire/auth';
import { auth } from 'firebase/app';
#Component({...})
export class AppComponent {
constructor(private afAuth: AngularFireAuth) { }
ngOnInit() {
this.afAuth.signInWithRedirect(new auth.GoogleAuthProvider());
}
}
// app.module.ts
import { AngularFireModule } from "#angular/fire";
import { AngularFireAuthModule } from '#angular/fire/auth';
...
#NgModule({
declarations: [AppComponent],
imports: [
AngularFireModule.initializeApp(environment.firebase),
AngularFireAuthModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
// package.json
"dependencies": {
"#angular/core": "~9.1.4",
"#angular/fire": "^6.0.0-rc.2",
"firebase": "7.14.3",
...
},
I have found this question with a similar problem, but they're not using AngularFire, just plain Firebase. With AngularFire I don't think I'm supposed to manually include the Firebase scripts in my index.html.
I've found the real solution. "angular-auth-firebase" must be passed to initializeApp() when importing the AngularFire module in the app module:
#NgModule({
declarations: [ ... ],
imports: [
AngularFireModule.initializeApp(environment.firebase, "angular-auth-firebase"),
AngularFireAuthModule,
...
],
...
})
export class AppModule { }
Old answer (workaround):
I have found a workaround here. If I simply add import "firebase/auth"; to app.module.ts, everything works, though I'm not sure this should be the permanent fix.

Button redirect to another page in Angular 5

Hello guys First of all i am learning angular 5 for the first time. What i want is to redirect from page to another using a button.I don't know how to make it work.I am using angular 5. This is my code:
Home.component.html
<div style="text-align:center">
<button (click)="btnClick()">Add Employee</button>
</div>
<br>
<div style="text-align:center">
<button (click)="btnClick()">Employee List</button>
</div>
<br>
Home.component.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
}
btnClick(){
this.router.navigate(['/employees']);
}
}
I don't have route.config but what i have is app.module.ts if i am doing anything wrong please tell me
app.module.ts:
...........
import { HomeComponent} from './home/home.component';
import { RouterModule, Routes } from '#angular/router';
import { EmployeesComponent } from './employees/employees.component';
#NgModule({
declarations: [
AppComponent,
EmployeesComponent,
EmployeeComponent,
EmployeeListComponent,
AppHeaderComponent,
AppFooterComponent,
HomeComponent,
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
ToastrModule.forRoot(),
],
It seems like you need to configure your application's routes first so the router outlet knows what component to load when ['/employees'] is called
there is a good explanation under : https://angular.io/tutorial/toh-pt5
First, you must configure the route
import { HomeComponent} from './home/home.component';
import { RouterModule, Routes } from '#angular/router';
import { EmployeesComponent } from './employees/employees.component';
const routes: Routes = [
{ path: 'home', component: HomeComponent }
{ path: 'employees', component: EmployeesComponent }
{ path: '', redirectTo: 'home', pathMatch: 'full' }
];
#NgModule({
declarations: [
AppComponent,
EmployeesComponent,
EmployeeComponent,
EmployeeListComponent,
AppHeaderComponent,
AppFooterComponent,
HomeComponent,
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
ToastrModule.forRoot()
RouterModule.forRoot(routes),
],
then in your in your AppComponent HTML you need to use the router outlet (assuming you want your employees to show on the app component)
<router-outlet></router-outlet>

ngModel 2-way data binding not working with Visual Studio 2017 Angular 2 Single Page Application Template

I have started a Visual Studio Community 2017 project using the Angular Single Page Application (SPA) template, as described in the .NET Web Development and Tools Blog:
https://blogs.msdn.microsoft.com/webdev/2017/02/14/building-single-page-applications-on-asp-net-core-with-javascriptservices/
2-way data binding using [(ngModel)] is not working.
For example:
In login.component.html:
<input [(ngModel)]="x" name="x"/>
<h1>{{x}}</h1>
In login.component.ts:
export class LoginComponent {
x = 5;
}
Result:
When I change the value in the input box, the text in the h1 tag should change as well. But it doesn't change.
I have already tried importing the FormsModule from #angular/forms and adding FormsModule to the imports for the #NgModule decorator in app.module.ts as noted here: Angular 2 two way binding using ngModel is not working.
More info (added 2017-06-12):
Note that the app module is divided up into three separate files
app.module.shared.ts:
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { AppComponent } from './components/app/app.component'
import { NavMenuComponent } from './components/navmenu/navmenu.component';
import { HomeComponent } from './components/home/home.component';
import { FetchDataComponent } from
'./components/fetchdata/fetchdata.component';
import { CounterComponent } from './components/counter/counter.component';
import { LoginComponent } from './components/login/login.component';
//dcowan: for login page
import { TimeEntryComponent } from
'./components/timeentry/timeentry.component'; //dcowan: for time entry page
export const sharedConfig: NgModule = {
bootstrap: [ AppComponent ],
declarations: [
AppComponent,
NavMenuComponent,
CounterComponent,
FetchDataComponent,
HomeComponent,
LoginComponent, //dcowan: for login page
TimeEntryComponent //dcowan: for time entry page
],
imports: [
RouterModule.forRoot([
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'login', component: LoginComponent }, //dcowan: for login page
{ path: 'timeentry', component: TimeEntryComponent }, //dcowan: for time entry page
{ path: 'counter', component: CounterComponent },
{ path: 'fetch-data', component: FetchDataComponent },
{ path: '**', redirectTo: 'home' }
])
]
};
app.module.client.ts:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
//import { FormsModule } from '#angular/forms';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { sharedConfig } from './app.module.shared';
// dcowan: Imports for loading & configuring the in-memory web api
//import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
//import { InMemoryDataService } from './in-memory-data.service';
import { DemoDbService } from './demo-db.service';
#NgModule({
bootstrap: sharedConfig.bootstrap,
declarations: sharedConfig.declarations,
imports: [
BrowserModule,
//FormsModule,
FormsModule,
HttpModule,
...sharedConfig.imports
],
providers: [DemoDbService,//dcowan: Dovico Web API
{ provide: 'ORIGIN_URL', useValue: location.origin }
]
})
export class AppModule {
}
app.module.server.ts:
import { NgModule } from '#angular/core';
import { ServerModule } from '#angular/platform-server';
import { sharedConfig } from './app.module.shared';
import { FormsModule } from '#angular/forms';
#NgModule({
bootstrap: sharedConfig.bootstrap,
declarations: sharedConfig.declarations,
imports: [
FormsModule,
ServerModule,
...sharedConfig.imports
]
})
export class AppModule {
}
I am experiencing the same. Temporarily, I am breaking up 2 way binding into attribute and event binding.
<input [value]="x" (input)="x=$event.target.value">
<h1>{{x}}</h1>
I have this error too. Try to import your FormsModule in the app.module.shared instead of app.module.server and app.module.client
I fixed it like this using (keyup) and [ngModel]
(keyup)="onKey($event)"
[ngModel]="model.input"
in keyup we update model.input
public onKey(event: any) {
this.model.input = event.target.value;
}
If ngModel is used within a form tag, either the name attribute must be set or the form control must be defined as 'standalone' in ngModelOptions.
this code with property name:
<input name="nome" [(ngModel)]="nome" />
this code without property name:
<input [(ngModel)]="nome" [ngModelOptions]="{standalone: true}" />

Angular 2 Universal, unit test fails with an error, No provider for Http

I'm usung Angular 2 Universal:
I have a service:
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { Page } from './page';
#Injectable()
export class MyService {
constructor(private http: Http) { }
getPage(id: number): Observable<Page> {
return null;
}
}
Unit test:
import { TestBed, async, inject } from '#angular/core/testing';
import { PageService } from './workflow.service';
describe('Service: Workflow', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [WorkflowService]
});
});
it('should ...', inject([PageService], (service: PageService) => {
expect(service).toBeTruthy();
}));
});
My app module:
#NgModule({
bootstrap: [AppComponent],
declarations: [
AppComponent,
HomeComponent,
WorkflowComponent
],
imports: [
HttpModule,
UniversalModule, // Must be first import. This automatically imports BrowserModule, HttpModule, and JsonpModule too.
RouterModule.forRoot([
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'workflow/:id', component: WorkflowComponent }
])
]
})
export class AppModule {
}
When I run unit test I get: Error: No provider for Http!
UniversalModule in app.module should import http module already as indicated in the comments.
I'm using the latest Angular universal.
Should I add http in the test?
This article gave me an idea how to fix it:
http://chariotsolutions.com/blog/post/testing-angular-2-0-x-services-http-jasmine-karma/

Resources