Skip to content

Commit bbdbb61

Browse files
refactor: update directives/components to use standalone APIs (#92)
1 parent b1bff03 commit bbdbb61

17 files changed

+119
-133
lines changed

LICENSE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License (MIT)
22

3-
Copyright (c) 2020-2021 Brandon Roberts
3+
Copyright (c) 2020-2022 Brandon Roberts
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ import { ComponentRouterModule } from '@angular-component/router';
6464
export class FeatureModule {}
6565
```
6666

67+
## Usage with Standalone Features (v14+)
68+
6769
After your components are registered, use the `Router` and `Route` components to register some routes.
6870

6971
```html

angular.json

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@
2525
"scripts": []
2626
},
2727
"configurations": {
28+
"development": {
29+
"vendorChunk": true,
30+
"extractLicenses": false,
31+
"buildOptimizer": false,
32+
"sourceMap": true,
33+
"optimization": false,
34+
"namedChunks": true
35+
},
2836
"production": {
2937
"fileReplacements": [
3038
{
@@ -53,12 +61,13 @@
5361
]
5462
}
5563
},
56-
"outputs": ["{options.outputPath}"]
64+
"outputs": ["{options.outputPath}"],
65+
"defaultConfiguration": "development"
5766
},
5867
"serve": {
5968
"builder": "@angular-devkit/build-angular:dev-server",
6069
"options": {
61-
"browserTarget": "example-app:build"
70+
"browserTarget": "example-app:build:development"
6271
},
6372
"configurations": {
6473
"production": {

apps/example-app/src/app/app.module.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common';
33
import { HttpClientModule } from '@angular/common/http';
44
import { BrowserModule } from '@angular/platform-browser';
55
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
6-
import { ComponentRouterModule } from '@angular-component/router';
6+
import { provideComponentRouter } from '@angular-component/router';
77

88
import { StoreModule } from '@ngrx/store';
99
import { EffectsModule } from '@ngrx/effects';
@@ -21,7 +21,6 @@ import { AppComponent } from '@example-app/core/containers';
2121
BrowserModule,
2222
BrowserAnimationsModule,
2323
HttpClientModule,
24-
ComponentRouterModule.forRoot(),
2524

2625
/**
2726
* StoreModule.forRoot is imported once in the root module, accepting a reducer
@@ -74,5 +73,6 @@ import { AppComponent } from '@example-app/core/containers';
7473
CoreModule,
7574
],
7675
bootstrap: [AppComponent],
76+
providers: [provideComponentRouter()],
7777
})
7878
export class AppModule {}

libs/router/LICENSE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License (MIT)
22

3-
Copyright (c) 2020-2021 Brandon Roberts
3+
Copyright (c) 2020-2022 Brandon Roberts
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

libs/router/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
},
2323
"homepage": "https://github.com/angular-component/router#readme",
2424
"peerDependencies": {
25-
"@angular/common": ">=9.0.0",
26-
"@angular/core": ">=9.0.0",
27-
"rxjs": ">=7.4.0"
25+
"@angular/common": ">=14.0.0-rc.0",
26+
"@angular/core": ">=14.0.0-rc.0",
27+
"rxjs": ">=7.5.0"
2828
},
2929
"sideEffects": false
3030
}

libs/router/src/lib/link-active.directive.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export const LINK_ACTIVE_OPTIONS: LinkActiveOptions = {
3535
* </li>
3636
* </ol>
3737
*/
38-
@Directive({ selector: '[linkActive]' })
38+
@Directive({ selector: '[linkActive]', standalone: true })
3939
export class LinkActive implements AfterContentInit, OnDestroy, OnChanges {
4040
@ContentChildren(LinkTo, { descendants: true })
4141
public links: QueryList<LinkTo>;

libs/router/src/lib/link-to.directive.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const DEFAULT_TARGET = '_self';
2020
* <a linkTo="/home/page" [queryParams]="{ id: 123 }">Home Page</a>
2121
* <a [linkTo]="'/pages' + page.id">Page 1</a>
2222
*/
23-
@Directive({ selector: 'a[linkTo]' })
23+
@Directive({ selector: 'a[linkTo]', standalone: true })
2424
export class LinkTo {
2525
@Input() target = DEFAULT_TARGET;
2626
@HostBinding('href') linkHref?: string | null;

libs/router/src/lib/route-component.directive.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Directive, Input } from '@angular/core';
22

33
@Directive({
44
selector: '[routeComponent]',
5+
standalone: true,
56
})
67
export class RouteComponentTemplate {
78
@Input() routeComponent: any;

libs/router/src/lib/route.component.ts

Lines changed: 31 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1+
import { CommonModule } from '@angular/common';
12
import {
23
Component,
34
OnInit,
45
Input,
56
Type,
67
ViewContainerRef,
7-
ComponentFactoryResolver,
88
ContentChild,
99
TemplateRef,
1010
ChangeDetectionStrategy,
1111
Self,
12-
NgModuleFactory,
13-
Compiler,
1412
OnDestroy,
13+
NgModuleRef,
14+
createNgModuleRef,
1515
} from '@angular/core';
1616

1717
import { Subject, BehaviorSubject, of, from } from 'rxjs';
@@ -24,7 +24,7 @@ import {
2424
map,
2525
} from 'rxjs/operators';
2626

27-
import { Load, Route, RouteOptions } from './route';
27+
import { Load, ModuleWithRoute, Route, RouteOptions } from './route';
2828
import { Params, RouteParams, RoutePath } from './route-params.service';
2929
import { RouterComponent } from './router.component';
3030
import { Router } from './router.service';
@@ -46,6 +46,8 @@ interface State {
4646
@Component({
4747
// tslint:disable-next-line:component-selector
4848
selector: 'route',
49+
standalone: true,
50+
imports: [CommonModule],
4951
template: `
5052
<ng-container
5153
*ngIf="(shouldRender$ | async) && template"
@@ -110,9 +112,7 @@ export class RouteComponent implements OnInit, OnDestroy {
110112
constructor(
111113
private router: Router,
112114
private routerComponent: RouterComponent,
113-
private resolver: ComponentFactoryResolver,
114-
private viewContainerRef: ViewContainerRef,
115-
private compiler: Compiler
115+
private viewContainerRef: ViewContainerRef
116116
) {}
117117

118118
ngOnInit(): void {
@@ -176,32 +176,26 @@ export class RouteComponent implements OnInit, OnDestroy {
176176
private loadAndRender(route: Route) {
177177
if (route.load) {
178178
return from(
179-
route.load().then((componentOrModule) => {
180-
if (componentOrModule instanceof NgModuleFactory) {
181-
const moduleRef = componentOrModule.create(
182-
this.viewContainerRef.injector
183-
);
184-
const component = moduleRef.instance.routeComponent;
185-
186-
this.renderComponent(component);
187-
} else if (componentOrModule.ɵmod) {
188-
return this.compiler
189-
.compileModuleAsync(componentOrModule as Type<any>)
190-
.then((moduleFactory) => {
191-
const moduleRef = moduleFactory.create(
192-
this.viewContainerRef.injector
193-
);
194-
const component = moduleRef.instance.routeComponent;
195-
this.renderComponent(component);
196-
197-
return true;
198-
});
199-
} else {
200-
this.renderComponent(componentOrModule);
201-
}
179+
route
180+
.load()
181+
.then(
182+
(componentOrModule: NgModuleRef<ModuleWithRoute> | Type<any>) => {
183+
let component: Type<any>;
184+
185+
if ((componentOrModule as any).ɵmod) {
186+
const moduleRef: NgModuleRef<ModuleWithRoute> =
187+
createNgModuleRef(
188+
componentOrModule as Type<any>,
189+
this.viewContainerRef.injector
190+
);
191+
component = moduleRef.instance.routeComponent;
192+
} else {
193+
component = componentOrModule as Type<any>;
194+
}
202195

203-
return true;
204-
})
196+
this.renderComponent(component);
197+
}
198+
)
205199
);
206200
} else {
207201
this.showTemplate();
@@ -210,14 +204,12 @@ export class RouteComponent implements OnInit, OnDestroy {
210204
}
211205

212206
private renderComponent(component: Type<any>) {
213-
const componentFactory = this.resolver.resolveComponentFactory(component);
214-
215207
this.showTemplate();
216-
this.viewContainerRef.createComponent(
217-
componentFactory,
218-
this.viewContainerRef.length,
219-
this.viewContainerRef.injector
220-
);
208+
209+
this.viewContainerRef.createComponent(component, {
210+
index: this.viewContainerRef.length,
211+
injector: this.viewContainerRef.injector,
212+
});
221213
}
222214

223215
private clearComponent() {

0 commit comments

Comments
 (0)