Angular 2 Component routing - angular-ui-router

I am planning to start learning angular 2 component router.
I have used Angular ui-router heavily.All my projects uses UI-router complex features like nested states and nested named views.
What will be good start to use angular 2 component router?
how can I configure nested states in Angular 2 component router?

All in all i would say routing is pretty simple and intuitive in angular 2
I would suggest reading through the router docs to get all the basics.
Keep in mind that child components can have routes too. They build from its parents routes.
app.component.ts (excerpt)
#Component({ ... })
#RouteConfig([
{path:'/crisis-center/...', name: 'CrisisCenter', component: CrisisListComponent},
{path:'/heroes', name: 'Heroes', component: HeroListComponent},
{path:'/hero/:id', name: 'HeroDetail', component: HeroDetailComponent}
])
export class AppComponent { }
crisis-center.component.ts(excerpt)
#RouteConfig([
{path:'/', name: 'CrisisCenter', component: CrisisListComponent, useAsDefault: true},
{path:'/:id', name: 'CrisisDetail', component: CrisisDetailComponent}
])
Notice that the path ends with a slash and three trailing periods (/...).
That means this is an incomplete route (AKA a non-terminal route). The finished route will be some combination of the parent /crisis-center/ route and a route from the child router that belongs to the designated component.
All is well. The parent route's designated component is the CrisisCenterComponent which is a Routing Component with its own router and routes.
From angular.io router guide

You can define a app.routing.ts like below.
export const routes: Routes = [
{
path: '',
component: SimpleLayoutComponent,
data: {
title: 'Login form'
},
children: [
{
path: '', component: LoginComponent,
}
]
},
{
path: 'dashboard',
component: FullLayoutComponent,
data: {
title: 'Home'
},
children: [
{
path: '',
component: 'mycomponent'
}
]
}
];
Then import this class to your app.module.ts file like below.
import { AppRoutingModule } from './app.routing';
#NgModule({
imports: [
BrowserModule,
HttpModule,
FormsModule,
AppRoutingModule,
],
declarations: [
AppComponent,
LoginComponent
],
providers: [
UserService, AuthGuard],
bootstrap: [ AppComponent ]
})
export class AppModule { }
app.component.ts Below: views get injected in
import { Component } from '#angular/core';
#Component({
selector: 'body',
template: '<router-outlet></router-outlet>'
})
export class AppComponent { }

#NgModule({
declarations: [AppComponent,CreateComponent,ListComponent],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpModule,
RouterModule.forRoot([
{path:"",component:ListComponent},
{path:"Create",component:CreateComponent},
])
],
bootstrap: [AppComponent]
})
Put this RouterModule in app.module file.
For this you have to import { RouterModule} ;
<router-outlet></router-outlet>
Put router-outlet element in app.component.html to render component through routing.

Related

Can't bind to 'formGroup' since it isn't a known property of 'form' whilst using SharedModule

I've had this error lots of times and I've always been able to fix it but I think I'm overlooking something this time and I can't get it too work.
As stated in the title, the error I get is Can't bind to 'formGroup' since it isn't a known property of 'form'. for the following line of code: <form [formGroup]="contactSettings">.
I already checked all stackoverflow posts but they all come down to add the ReactiveFormsModule to the module that makes use of ReactiveForms. In my case, which was also in various stackoverflow posts, I should export the ReactiveFormsModule in my SharedModule and import that SharedModule in my ContactModule that actually uses the ReactiveFormsModule. I don't see what I'm doing wrong.
contact-settings.component.html
<form [formGroup]="contactSettings">
</form>
contact-settings.component.ts
export class ContactSettingsComponent extends FormComponent {
contactSettings: FormGroup = this.fb.group({ //Moving this to constructor or onInit does not fix it
firstName: ["First name"],
lastName: ["Last name"],
emailAdress: ["email", Validators.email],
gender: ["male"],
parentCustomerId: ["Parent customer name"],
language: ["Language"],
telephone: ["Telephone number"],
mobilephone: ["Mobile phone number"],
});
constructor(private fb: FormBuilder, private contactService: ContactService) {
super();
}
}
contact.module.ts
... //imports
#NgModule({
declarations: [
ContactSettingsComponent
],
imports: [
ContactRoutingModule,
SharedMaterialModule, // <--- contains export ReactiveFormsModule and FormsModule
SharedComponentsModule
]
})
export class ContactModule { }
shared-material.module.ts
... //Angular Material imports
//CommonModule
import { CommonModule } from "#angular/common";
//Forms
import { ReactiveFormsModule, FormsModule } from "#angular/forms";
//Browser
import { BrowserAnimationsModule } from "#angular/platform-browser/animations";
import { BrowserModule } from "#angular/platform-browser";
#NgModule({
//Normally imports are here, but the template I bought does not have this and adding it doesn't fix it either. It worked normally before.
exports: [
//CommonModule
CommonModule,
//Browser animations
BrowserModule,
BrowserAnimationsModule,
//Forms
ReactiveFormsModule, // <--- clearly present here
FormsModule,
//Angular Material Modules
...
]
})
export class SharedMaterialModule {}
My imports were done perfectly. The problem was that my ContactModule was never used in any other module. I had to add load the ContactModule by adding the following code block to my app-routing.module.
{
path: 'contact',
loadChildren: () => import('./views/contact/contact.module').then(m => m.ContactModule)
}

Why lazyload is not working on submodules?

I have a little question , i try to customize my router for lazy load Angular CLI 8 , if i try to put loadChildren on sub modules i have some errors.
app.routing.ts
import { CommonModule, } from '#angular/common';
import { BrowserModule } from '#angular/platform-browser';
import { Routes, RouterModule } from '#angular/router';
import { LoginComponent } from './login/login.component';
import {CoreComponent} from './core/core.component';
const routes: Routes = [
{
path: '',
redirectTo: 'dashboard',
pathMatch: 'full',
},
{
path: 'login',
component: LoginComponent
},
{
path: '',
component: CoreComponent,
children: [
{
path: '',
loadChildren: () => import('./core/core.module').then(mod => mod.CoreModule)
}
]
}
];
#NgModule({
imports: [
CommonModule,
BrowserModule,
RouterModule.forRoot(routes , {
enableTracing: false
})
],
exports: [
RouterModule
],
})
export class AppRoutingModule { }
on core.module.ts -> This is working
import { RouterModule } from '#angular/router';
import { CommonModule } from '#angular/common';
import { CoreRoutes } from '../_config/route';
import { TableListComponent } from '../table-list/table-list.component';
import { TypographyComponent } from '../typography/typography.component';
import { IconsComponent } from '../icons/icons.component';
import { MapsComponent } from '../maps/maps.component';
import { NotificationsComponent } from '../notifications/notifications.component';
import { UpgradeComponent } from '../upgrade/upgrade.component';
import {UsersComponent} from '../users/user-list/users.component';
import {UserDetailsComponent} from '../users/user-details/user-details.component';
#NgModule({
imports: [
CommonModule,
RouterModule.forChild(CoreRoutes)
],
declarations: [
TableListComponent,
TypographyComponent,
IconsComponent,
MapsComponent,
NotificationsComponent,
UpgradeComponent,
UsersComponent,
UserDetailsComponent
],
providers : [
]
})
export class CoreModule {}
on route.ts - > in this case loadchildren only works if i include full path like this '../dashboard/dashboard.module#DashboardModule'
import { AuthGuard } from '../_helpers';
import {SandboxComponent, UsersComponent} from '../users/user-list/users.component';
import {UserDetailsComponent} from '../users/user-details/user-details.component';
export const CoreRoutes: Routes = [
{
path: 'dashboard',
loadChildren: () => import('../dashboard/dashboard.module').then(mod => mod.DashboardModule),
// '../dashboard/dashboard.module#DashboardModule'
canActivate: [AuthGuard],
},
{
path: 'users',
component: UsersComponent,
children: [
{ path: 'sandbox', component: SandboxComponent } // url: about/item
]
},
{
path: 'users/sandbox',
component: UsersComponent
},
{ path: 'user/:id', component: UserDetailsComponent }
];
ERROR in src\app\core\core.module.ts(18,31): Error during template compile of 'CoreModule'
Function expressions are not supported in decorators in 'CoreRoutes'
'CoreRoutes' contains the error at src\app\_config\route.ts(8,23)
Consider changing the function expression into an exported function.```
I find the problem with this.
The problem was when i started the server with --aot (Ahead Of Time) parameter and CLI version is 7.X , if i run simple like ng serve everything works (JIT - Just in time) compiler.
According there documents https://angular.io/guide/aot-compiler this is coming from 6 CLI version and something happens after update CLI to 7 / 8

Angular CLI - How to reference image paths in reusable components

Need help figuring out how to include images in a reusable component that is referenced in another app.
For example, I have an Angular App, let's call it UI-Common, that contains common components and another Angular App, let's call it Command-Center, that will use those common components.
In UI-Common, there is a component called my-control.component that is defined as follows:
[my-control.component.html]
<div>
<img src="assets/images/myImage.png"/>
<div class"username" *ngIf="user">
<p><strong>{{user.companyName}}</strong></p>
<p>{{user.firstName + ' ' + user.lastName}}</p>
</div>
[my-control.component.ts]
import { Component, Input } from '#angular/core';
import { User } from '../../models/user';
#Component({
selector: 'my-control',
templateUrl: './my-control.component.html',
styleUrls: ['./my-control.component.scss'],
})
export class MyControlComponent {
#Input() user: User;
constructor() {
}
}
In Command-Center, it adds UI-Common as a dependency in the package.json. A Command-Center component is created and uses my-control.component as follows:
[app.module.ts]
...
import { HomeComponent } from './home/home.component';
import { MyControlComponent } from 'ui-common';
#NgModule({
declarations: [
...,
HomeComponent,
MyControlComponent,
...
],
...
})
export class AppModule { }
[home.component.html]
<my-control [user]=user></my-control>
<div class="homeContent">
blah blah blah...
</div>
[home.component.ts]
import { Component } from '#angular/core';
import { User } from 'ui-common';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent {
user: User;
constructor() {
this.user = new User();
this.user.companyName = 'iHeartMedia';
this.user.firstName = 'John';
this.user.lastName = 'Smith';
}
}
The problem is the image on my-control when running from Command-Center does not load at all. This appears to be because the image path being used "assets/images/myImage.png" does not exist in Command-Center. I don't want to save a copy of the image in the Command-Center's assets folder. How do I properly handle images in the common component?
Found this Angular CLI feature request: https://github.com/angular/angular-cli/issues/3555
The Angular app can be configured to copy files from a relative file path to a folder within the app's distribution directory. This allows us to get access to images from within the node_modules folder without having to manually copy the images into the local assets folder.
After updating to the latest version of Angular CLI (1.2.1) I modified my angular-cli.json file as follows:
{
...
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": [
"assets",
"favicon.ico",
"version.txt",
{
"glob": "**/*",
"input": "../node_modules/ui-common/src/assets/images",
"output": "./assets/images"
}
],
...
}
Now all images that are in the UI-Common app are accessible to the Command-Center app.
More details about the configuration here: https://github.com/angular/angular-cli/wiki/stories-asset-configuration
import {APP_BASE_HREF} from '#angular/common';
#NgModule({
declarations: [ ... ],
imports: [ ... ],
providers: [{provide: APP_BASE_HREF, useValue : '/' }]
]);
I think you need to do something like this for the module you want to to use the image in.

ionic 3 navigation transition with push other pages

I want to make animation transition in my ionic 3 app when navigate to page.
I'm using this documentation
I declared in my app.module.ts
#NgModule({
declarations: [
MyApp,
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp,{
PageTransition: 'wp-transition'
}),
AngularFireModule.initializeApp(FIREBASE_CONFIG)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
],
providers: [
StatusBar,
SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
})
export class AppModule {}
then when I navigate to page I wrote this
NavigateToPage(pageName: string){
let opts = { animate: true, animation: "wp-transition",direction:'forward', duration: 2500}
pageName === 'TabsPage'? this.navCtrl.setRoot(pageName,opts) : this.navCtrl.push(pageName,opts);
}
}
but I don't see any transition, it looks the same as before.
any idea?
I've made it work(a push()) in one of my project by doing this:
this.navCtrl.push(pageName,{/*here stay navParams - but for this example is empty, but still need to use {}*/},opts);
So without the comment: this.navCtrl.push(pageName,{},opts);

NumericTextBox Kendo UI for Angular2 with custom IntlService

I have taken latest RC0 of Kendo UI for Angular2. It's docs mentions use of Internationalization service. I have created custom IntlService and configured it's provider in my App Module. In the component if I use the IntlService dependency then my custom service is invoked, but the NumericTextBox is not calling my service. What's wrong in the following code?
MyIntlService.ts
import { CldrIntlService } from '#progress/kendo-angular-intl';
import { Injectable } from '#angular/core';
#Injectable()
export class MyIntlService extends CldrIntlService {
constructor() {
super("en-US");
console.info('From MyIntlService ctor');
}
formatNumber(value: number, format: string| NumberFormatOptions){
const result = super.formatNumber(value,format);
console.log('In MyIntlService formatNumber');
return result;
}
}
app.module.ts
#NgModule({
imports: [ BrowserModule, InputsModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
providers: [{
provide: IntlService,
useClass: MyIntlService
}]
})
export class AppModule { }
app.component
export class AppComponent {
constructor(private intl: IntlService) {
console.log( " From AppComponent " + intl.formatNumber(42, "c"));
}
}
You can file an issue in the GitHub repository ↗. Providing a runnable example demonstrating the issue will be appreciated.

Resources