Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Router standalone directives #46758

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 13 additions & 5 deletions goldens/public-api/router/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ export class ChildrenOutletContexts {
onOutletDeactivated(): Map<string, OutletContext>;
// (undocumented)
onOutletReAttached(contexts: Map<string, OutletContext>): void;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<ChildrenOutletContexts, never>;
// (undocumented)
static ɵprov: i0.ɵɵInjectableDeclaration<ChildrenOutletContexts>;
}

// @public
Expand Down Expand Up @@ -666,7 +670,7 @@ export class RouterLink implements OnChanges {
// (undocumented)
get urlTree(): UrlTree | null;
// (undocumented)
static ɵdir: i0.ɵɵDirectiveDeclaration<RouterLink, ":not(a):not(area)[routerLink]", never, { "queryParams": "queryParams"; "fragment": "fragment"; "queryParamsHandling": "queryParamsHandling"; "preserveFragment": "preserveFragment"; "skipLocationChange": "skipLocationChange"; "replaceUrl": "replaceUrl"; "state": "state"; "relativeTo": "relativeTo"; "routerLink": "routerLink"; }, {}, never, never, false>;
static ɵdir: i0.ɵɵDirectiveDeclaration<RouterLink, ":not(a):not(area)[routerLink]", never, { "queryParams": "queryParams"; "fragment": "fragment"; "queryParamsHandling": "queryParamsHandling"; "preserveFragment": "preserveFragment"; "skipLocationChange": "skipLocationChange"; "replaceUrl": "replaceUrl"; "state": "state"; "relativeTo": "relativeTo"; "routerLink": "routerLink"; }, {}, never, never, true>;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<RouterLink, [null, null, { attribute: "tabindex"; }, null, null]>;
}
Expand Down Expand Up @@ -694,7 +698,7 @@ export class RouterLinkActive implements OnChanges, OnDestroy, AfterContentInit
exact: boolean;
} | IsActiveMatchOptions;
// (undocumented)
static ɵdir: i0.ɵɵDirectiveDeclaration<RouterLinkActive, "[routerLinkActive]", ["routerLinkActive"], { "routerLinkActiveOptions": "routerLinkActiveOptions"; "ariaCurrentWhenActive": "ariaCurrentWhenActive"; "routerLinkActive": "routerLinkActive"; }, { "isActiveChange": "isActiveChange"; }, ["links", "linksWithHrefs"], never, false>;
static ɵdir: i0.ɵɵDirectiveDeclaration<RouterLinkActive, "[routerLinkActive]", ["routerLinkActive"], { "routerLinkActiveOptions": "routerLinkActiveOptions"; "ariaCurrentWhenActive": "ariaCurrentWhenActive"; "routerLinkActive": "routerLinkActive"; }, { "isActiveChange": "isActiveChange"; }, ["links", "linksWithHrefs"], never, true>;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<RouterLinkActive, [null, null, null, null, { optional: true; }, { optional: true; }]>;
}
Expand Down Expand Up @@ -726,7 +730,7 @@ export class RouterLinkWithHref implements OnChanges, OnDestroy {
// (undocumented)
get urlTree(): UrlTree | null;
// (undocumented)
static ɵdir: i0.ɵɵDirectiveDeclaration<RouterLinkWithHref, "a[routerLink],area[routerLink]", never, { "target": "target"; "queryParams": "queryParams"; "fragment": "fragment"; "queryParamsHandling": "queryParamsHandling"; "preserveFragment": "preserveFragment"; "skipLocationChange": "skipLocationChange"; "replaceUrl": "replaceUrl"; "state": "state"; "relativeTo": "relativeTo"; "routerLink": "routerLink"; }, {}, never, never, false>;
static ɵdir: i0.ɵɵDirectiveDeclaration<RouterLinkWithHref, "a[routerLink],area[routerLink]", never, { "target": "target"; "queryParams": "queryParams"; "fragment": "fragment"; "queryParamsHandling": "queryParamsHandling"; "preserveFragment": "preserveFragment"; "skipLocationChange": "skipLocationChange"; "replaceUrl": "replaceUrl"; "state": "state"; "relativeTo": "relativeTo"; "routerLink": "routerLink"; }, {}, never, never, true>;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<RouterLinkWithHref, never>;
}
Expand All @@ -741,7 +745,7 @@ export class RouterModule {
// (undocumented)
static ɵinj: i0.ɵɵInjectorDeclaration<RouterModule>;
// (undocumented)
static ɵmod: i0.ɵɵNgModuleDeclaration<RouterModule, [typeof i1.RouterOutlet, typeof i2.RouterLink, typeof i2.RouterLinkWithHref, typeof i3.RouterLinkActive, typeof i4.ɵEmptyOutletComponent], never, [typeof i1.RouterOutlet, typeof i2.RouterLink, typeof i2.RouterLinkWithHref, typeof i3.RouterLinkActive, typeof i4.ɵEmptyOutletComponent]>;
static ɵmod: i0.ɵɵNgModuleDeclaration<RouterModule, never, [typeof i1.RouterOutlet, typeof i2.RouterLink, typeof i2.RouterLinkWithHref, typeof i3.RouterLinkActive, typeof i4.ɵEmptyOutletComponent], [typeof i1.RouterOutlet, typeof i2.RouterLink, typeof i2.RouterLinkWithHref, typeof i3.RouterLinkActive, typeof i4.ɵEmptyOutletComponent]>;
}

// @public
Expand Down Expand Up @@ -772,7 +776,7 @@ export class RouterOutlet implements OnDestroy, OnInit, RouterOutletContract {
// (undocumented)
ngOnInit(): void;
// (undocumented)
static ɵdir: i0.ɵɵDirectiveDeclaration<RouterOutlet, "router-outlet", ["outlet"], {}, { "activateEvents": "activate"; "deactivateEvents": "deactivate"; "attachEvents": "attach"; "detachEvents": "detach"; }, never, never, false>;
static ɵdir: i0.ɵɵDirectiveDeclaration<RouterOutlet, "router-outlet", ["outlet"], {}, { "activateEvents": "activate"; "deactivateEvents": "deactivate"; "attachEvents": "attach"; "detachEvents": "detach"; }, never, never, true>;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<RouterOutlet, [null, null, { attribute: "name"; }, null, null]>;
}
Expand Down Expand Up @@ -942,6 +946,10 @@ export class UrlSegmentGroup {
export abstract class UrlSerializer {
abstract parse(url: string): UrlTree;
abstract serialize(tree: UrlTree): string;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<UrlSerializer, never>;
// (undocumented)
static ɵprov: i0.ɵɵInjectableDeclaration<UrlSerializer>;
}

// @public
Expand Down
2 changes: 1 addition & 1 deletion goldens/size-tracking/aio-payloads.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"aio-local": {
"uncompressed": {
"runtime": 4325,
"main": 461893,
"main": 462546,
"polyfills": 33922,
"styles": 73640,
"light-theme": 78276,
Expand Down
2 changes: 1 addition & 1 deletion goldens/size-tracking/integration-payloads.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"cli-hello-world-lazy": {
"uncompressed": {
"runtime": 2835,
"main": 237313,
"main": 238214,
"polyfills": 33842,
"src_app_lazy_lazy_module_ts": 780
}
Expand Down
6 changes: 6 additions & 0 deletions packages/core/test/bundling/router/bundle.golden_symbols.json
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,9 @@
{
"name": "SkipSelf"
},
{
"name": "StandaloneService"
},
{
"name": "Subject"
},
Expand Down Expand Up @@ -1970,6 +1973,9 @@
{
"name": "ɵɵNgOnChangesFeature"
},
{
"name": "ɵɵStandaloneFeature"
},
{
"name": "ɵɵattribute"
},
Expand Down
8 changes: 7 additions & 1 deletion packages/router/src/components/empty_outlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import {Component} from '@angular/core';

import {RouterOutlet} from '../directives/router_outlet';

/**
* This component is used internally within the router to be a placeholder when an empty
* router-outlet is needed. For example, with a config such as:
Expand All @@ -17,7 +19,11 @@ import {Component} from '@angular/core';
* In order to render, there needs to be a component on this config, which will default
* to this `EmptyOutletComponent`.
*/
@Component({template: `<router-outlet></router-outlet>`})
@Component({
template: `<router-outlet></router-outlet>`,
imports: [RouterOutlet],
standalone: true,
})
export class ɵEmptyOutletComponent {
}

Expand Down
7 changes: 5 additions & 2 deletions packages/router/src/directives/router_link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,10 @@ import {UrlTree} from '../url_tree';
*
* @publicApi
*/
@Directive({selector: ':not(a):not(area)[routerLink]'})
@Directive({
selector: ':not(a):not(area)[routerLink]',
standalone: true,
})
export class RouterLink implements OnChanges {
/**
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the
Expand Down Expand Up @@ -277,7 +280,7 @@ export class RouterLink implements OnChanges {
*
* @publicApi
*/
@Directive({selector: 'a[routerLink],area[routerLink]'})
@Directive({selector: 'a[routerLink],area[routerLink]', standalone: true})
export class RouterLinkWithHref implements OnChanges, OnDestroy {
// TODO(issue/24571): remove '!'.
@HostBinding('attr.target') @Input() target!: string;
Expand Down
1 change: 1 addition & 0 deletions packages/router/src/directives/router_link_active.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ import {RouterLink, RouterLinkWithHref} from './router_link';
@Directive({
selector: '[routerLinkActive]',
exportAs: 'routerLinkActive',
standalone: true,
})
export class RouterLinkActive implements OnChanges, OnDestroy, AfterContentInit {
@ContentChildren(RouterLink, {descendants: true}) links!: QueryList<RouterLink>;
Expand Down
6 changes: 5 additions & 1 deletion packages/router/src/directives/router_outlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,11 @@ export interface RouterOutletContract {
*
* @publicApi
*/
@Directive({selector: 'router-outlet', exportAs: 'outlet'})
@Directive({
selector: 'router-outlet',
exportAs: 'outlet',
standalone: true,
})
export class RouterOutlet implements OnDestroy, OnInit, RouterOutletContract {
private activated: ComponentRef<any>|null = null;
private _activatedRoute: ActivatedRoute|null = null;
Expand Down
2 changes: 1 addition & 1 deletion packages/router/src/router_config_loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const ROUTES = new InjectionToken<Route[][]>('ROUTES');

type ComponentLoader = Observable<Type<unknown>>;

@Injectable()
@Injectable({providedIn: 'root'})
export class RouterConfigLoader {
private componentLoaders = new WeakMap<Route, ComponentLoader>();
private childrenLoaders = new WeakMap<Route, Observable<LoadedRouterConfig>>();
Expand Down
10 changes: 5 additions & 5 deletions packages/router/src/router_module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ export const ROUTER_PROVIDERS: Provider[] = [
RouterConfigLoader,
];

export function rootRoute(router: Router): ActivatedRoute {
return router.routerState.root;
}

export function routerNgProbeToken() {
return new NgProbeToken('Router', Router);
}
Expand All @@ -100,7 +104,7 @@ export function routerNgProbeToken() {
* @publicApi
*/
@NgModule({
declarations: ROUTER_DIRECTIVES,
imports: ROUTER_DIRECTIVES,
exports: ROUTER_DIRECTIVES,
})
export class RouterModule {
Expand Down Expand Up @@ -512,10 +516,6 @@ export function assignExtraOptionsToRouter(opts: ExtraOptions, router: Router):
}
}

export function rootRoute(router: Router): ActivatedRoute {
return router.routerState.root;
}

export function getBootstrapListener() {
const injector = inject(Injector);
return (bootstrappedComponentRef: ComponentRef<unknown>) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/router/src/router_outlet_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {ComponentFactoryResolver, ComponentRef, EnvironmentInjector} from '@angular/core';
import {ComponentFactoryResolver, ComponentRef, EnvironmentInjector, Injectable} from '@angular/core';

import {RouterOutletContract} from './directives/router_outlet';
import {ActivatedRoute} from './router_state';
Expand Down Expand Up @@ -35,6 +35,7 @@ export class OutletContext {
*
* @publicApi
*/
@Injectable({providedIn: 'root'})
export class ChildrenOutletContexts {
// contexts for child outlets, by name.
private contexts = new Map<string, OutletContext>();
Expand Down
2 changes: 0 additions & 2 deletions packages/router/src/router_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import {equalSegments, UrlSegment, UrlSegmentGroup, UrlTree} from './url_tree';
import {shallowEqual, shallowEqualArrays} from './utils/collection';
import {Tree, TreeNode} from './utils/tree';



/**
* Represents the state of the router as a tree of activated routes.
*
Expand Down
3 changes: 2 additions & 1 deletion packages/router/src/url_tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {ɵRuntimeError as RuntimeError} from '@angular/core';
import {Injectable, ɵRuntimeError as RuntimeError} from '@angular/core';

import {RuntimeErrorCode} from './errors';
import {convertToParamMap, ParamMap, Params, PRIMARY_OUTLET} from './shared';
Expand Down Expand Up @@ -356,6 +356,7 @@ export function mapChildrenIntoArray<T>(
*
* @publicApi
*/
@Injectable({providedIn: 'root', useFactory: () => new DefaultUrlSerializer()})
export abstract class UrlSerializer {
/** Parse a url into a `UrlTree` */
abstract parse(url: string): UrlTree;
Expand Down