This commit updates the `RouterLinkWithHref` class to further align with the `RouterLink` class by removing own constructor from the `RouterLinkWithHref` class.
PR Close#47619
When using `loadChildren` or `loadComponent`, a common pattern is to pass
a function that returns a `Promise` from a dynamic import:
```typescript
{
path: 'lazy',
loadComponent: () => import('./lazy-file').then(m => m.LazyCmp),
}
```
The `.then` part of the expression selects the particular exported
component symbol from the dynamically imported ES module.
ES modules can have a "default export", created with the `export default`
modifier:
```typescript
@Component({...})
export default class LazyCmp { ... }
```
This default export is made available to dynamic imports under the well-
known key of `'default'`, per the ES module spec:
https://tc39.es/ecma262/#table-export-forms-mapping-to-exportentry-records
This commit adds a feature to the router to automatically dereference such
default exports. With this logic, when `export default` is used, a `.then`
operation to select the particular exported symbol is no longer required:
```typescript
{
path: 'lazy',
loadComponent: () => import('./lazy-file'),
}
```
The above `loadComponent` operation will automatically use the `default`
export of the `lazy-file` ES module.
This functionality works for `loadChildren` as well.
PR Close#47586
This commit breaks out the code in @angular/router needed to support the
deprecated `loadChildren` signature into a separate file, which reduces the
opportunity for conflicts when patching that behavior in g3.
PR Close#47586
Adds support for host directives on the root component by calling `findHostDirectiveDefs` and passing the results to the relevant functions.
PR Close#47620
This commit updates the 'name' of `RouterOutlet` to be an `Input` rather
than an attribute. Note that this change does not affect `[attr.name]=`
because those already would not have worked. The static name was only
read in the constructor and if it wasn't available, it would use
'PRIMARY' instead.
fixes#12522
BREAKING CHANGE: Previously, the `RouterOutlet` would immediately
instantiate the component being activated during navigation. Now the
component is not instantiated until the change detection runs. This
could affect tests which do not trigger change detection after a router
navigation. In rarer cases, this can affect production code that relies
on the exact timing of component availability.
PR Close#46569
This commit updates the `RouterLink` directive to use a renderer to apply an `href` attribute value. Previously, the `RouterLinkWithHref` used a host binding for this and that prevented further merge of the `RouterLink` and `RouterLinkWithHref` directives.
PR Close#47605
- This update is needed to implement the changes in `ng add localize` https://github.com/angular/angular/pull/47569
- Add missing `root` options to all `angular.json`, this is required as otherwise the angular.json validation will fail.
- Remove `require.context` from test.ts integration test, as this is no longer needed.
- Update payloads golden files.
PR Close#47584
Previously the built-in image loaders for the optimized image directive
were tightly coupled to the preconnect checks infrastructure. This was
creating a problem when developers were trying to provide a loader on
a component level (or, more generally, deeper in the DI hierarchy):
- PreconnectLinkChecker is the application-level service, provided in root;
- it makes sense to provide loaders in different parts of the DI hierarchy;
This refactoring removes the PreconnectLinkChecker configuration from
the loaders infrastructure and makes it application-wide config. The
PRECONNECT_CHECK_BLOCKLIST is also a simple provider (it was a
multi-provider previously) which should make the overall configuration
easier.
PR Close#47565
Currently, the `RouterLink` and `RouterLinkWithHref` classes share a lot of common code (with some special logic around handling `<a>`-related scenarios). This commit unifies the logic of the mentioned directives by moving the necessary handling to the `RouterLink` directive and making it a parent one for the `RouterLinkWithHref` class (i.e. class RouterLinkWithHref extends RouterLink).
This is the first step in upcoming unification to merge both directives and just keep `RouterLink` one (it'd be done in followup PRs).
PR Close#47500
ActivatedRouteSnapshot data gets mutated in the resolve phase of the Router. The title is assigned as part of this.
As a result, the title must be a getter in order to pick up the value that was note available during the class creation.
fixes#47459
BREAKING CHANGE: The title property is now required on ActivatedRouteSnapshot
PR Close#47481
This commit applies the changes similar to the ones performed for the `inject()` function in https://github.com/angular/angular/pull/46649/commits/df246bb2358794e3aad53870f1554d84bbe390b2.
The `TestBed.inject` function is updated to use previously added object-based API for options: now the flags argument supports passing an object which configures injection flags.
DEPRECATED:
The bit field signature of `TestBed.inject()` has been deprecated, in favor of the new options object.
PR Close#46761
This commit applies the changes similar to the ones performed for the `inject()` function in https://github.com/angular/angular/pull/46649/commits/df246bb2358794e3aad53870f1554d84bbe390b2.
The `Injector.get` function is updated to use previously added object-based API for options: now the flags argument supports passing an object which configures injection flags.
DEPRECATED:
The bit field signature of `Injector.get()` has been deprecated, in favor of the new options object.
PR Close#46761
1. Remove `zone-async-tagging` implementation from zone.js and move the
implementation to `@angular/core`, so `@angular/core` can import this
package more easily for better treeshaking.
2. Add `async tagging zone` implemenation into `@angular/core` package.
So we don't need to get the `AsyncStackTaggingZoneSpec` from `global`
instance, we can import the `class` directly for better treeshaking.
3. Only load this ZoneSpec when `ngDevMode` is `true`.
PR Close#47416
`TNode`s have the `directiveStart` and `directiveEnd` properties that indicate the indexes at which directive instances (including components) have been stored. Currently there are several places throughout the codebase which assume that if a component matches a node, its index will always be `directiveStart`.
As far as I can tell, we probably ended up accumulating these assumptions, because we needed a quick way of accessing the component instance and it happened to be conventiently stored at `directiveStart`. The reason why it's always stored at `directiveStart` is likely to match the lifecycle hook execution order from ViewEngine.
With host directives these assumptions won't be valid anymore, because we want the host directives to _always_ execute before the host component that they're on so that the host has a chance to override them. To achieve this we have to insert host directives before the component.
These changes address the issue by introducing a new `TNode.componentOffset` property which indicates the offset after `TNode.directiveStart` at which the component is stored. Furthermore, I've removed the `isComponentHost` flag since it was duplicating the information from `TNode.componentOffset` and I've audited and fixed all the places where we read `directiveStart` to account for the changed data structure.
Reasons for some of the decisions I made along the way:
* In the case of host directives, I decided to go against our current convention of executing the component lifecycle hooks before the directive, because lifeycle hooks are a chance to change the component state (e.g. in `ngOnChanges`) and running the component hooks first would allow the host directives to undo any overrides made by the host.
* I decided to go with a `componentOffset`, instead of a `componentIndex` indicating the exact index the component is at, because as the runtime is set up at the moment, it would be difficult to know what index the component is going to end up at. Another problem is that we appear to have some logic that moves the entire "directive window" by incrementing both `directiveStart` and `directiveEnd`. By using an offset, we don't have to worry about the index remaining correct.
PR Close#47490
Expands the runtime to allow for basic host directives to be invoked within a template. This is achieved by making a second pass over the directives that were matched based on their selectors and producing a new array of directives that include host directives. Note that the ordering in the array is important, because it determines which host bindings and DI tokens will be overwritten.
PR Close#47430
We have some logic that generates the `InitialInputs` data structure by taking the static attributes of a node and looking them up in the `DirectiveDef.inputs` map to determine if they correspond to an input.
This works fine at the moment, but it will make it trickier to generate the correct `InitialInputs` for host directives, because the `DirectiveDef.inputs` entries might be aliased under a different name.
These changes rework the existing `generateInitialInputs` function so that it does its lookup on the remapped inputs that have accounted for the aliasing process already.
PR Close#47228
This commit updates the payload size for the Animations integration test app. The increase is likely is a result of a number of accumulated changes from various commits merged previously.
PR Close#47424
In a previous refactor, the `RootContext` was update to only contain a reference to a component. This commit perform further refactoring to get rid of the `RootContext` altogether, while storing component reference directly on the root view (without the `RootContext` wrapper).
PR Close#47056
This commit updates the `renderApplication`, `renderModule` and `renderModuleFactory` functions to append a special marker (in a form of an attribute, called `ng-server-context`) to the component host elements. This marker is needed to analyze how a page was rendered.
PR Close#47103
As an ongoing effort to stabilize the NgOptimizedImage API before existing the Developer Preview, this commit renames the `rawSrc` attribute used for the NgOptimizedImage selector matching to `ngSrc`. The `rawSrcset` is also renamed to `ngSrcset` for consistency.
The motivation for this change is to align the attribute name better with other built-in directives, such as `ngFor`, `ngIf`, `ngClass`, `ngStyle`, etc.
Note: this is technically a breaking change, but since the NgOptimizedImage directive is in the Developer Preview mode, we land the change in a patch branch.
PR Close#47362
This commit adds a re-export of the `NgForOf` class as `NgFor` to improve the DX for cases when the directive is used as standalone. Developers can import `NgFor` class, which better matches the `ngFor` attribute used in a template.
PR Close#47309
This option has no longer any effect as Ivy is the only rendering engine.
BREAKING CHANGE: Angular compiler option `enableIvy` has been removed as Ivy is the only rendering engine.
PR Close#47346
This change removed the deprecated `canParse` method from all the TranslationParsers.
BREAKING CHANGE:
- `canParse` method has been removed from all translation parsers in `@angular/localize/tools`. `analyze` should be used instead.
- the `hint` parameter in the`parse` methods is now mandatory.
PR Close#47275
This is the compile-time implementation of the `hostDirectives` feature plus a little bit of runtime code to illustrate how the newly-generated code will plug into the runtime. It works by creating a call to the new `ɵɵHostDirectivesFeature` feature whenever a directive has a `hostDirectives` field. Afterwards `ɵɵHostDirectivesFeature` will patch a new function onto the directive definition that will be invoked during directive matching.
For example, if we take the following definition:
```ts
@Directive({
hostDirectives: [HostA, {directive: HostB, inputs: ['input: alias']}]
})
class MyDir {}
```
Will compile to:
```js
MyDir.ɵdir = ɵɵdefineComponent({
features: [ɵɵHostDirectivesFeature([HostA, {
directive: HostB,
inputs: {
input: "alias"
}
}])]
});
```
The template type checking is implemented during directive matching by adding the host directives applied on the host to the array of matched directives whenever the host is matched in a template.
Relates to #8785.
PR Close#46868
The `UrlTree` is a fundamental concept in the router's API design.
Generally speaking, a `UrlTree` would be constructed via things like
`Router.createUrlTree` or `UrlSerializer#parse`. The second example here
is the core reason to make the constructor public, regardless of how
develpers generally create a `UrlTree` in an application.
Applications can provide their own `UrlSerializer` and may want to implement their
own `parse` method. This means they would also need to create a
`UrlTree` but would not be able to do so effectively because the
constructor is marked `@internal`.
In addition, the `UrlTree` constructor only has 3 parameters, all of
which are already public. There's nothing "special" about it other than
the potential desire to push developers to use other methods for
constructing a `UrlTree` (i.e. `Router.createUrlTree`).
Also see http://b/234604699#comment9 for additional context.
PR Close#47186
This commit adds a console warning in development mode
if the ultimate rendered size of the image is much
smaller than the dimensions of the requested image.
In this case, the warning recommends adjusting the
size of the source image or using the `rawSrcset`
attribute to implement responsive sizing.
PR Close#47082
This commit updates the logic of Image Loaders to throw an error in case an absolute URL is provided an an input to the loader function. The loaders can construct URLs based on image paths relative to the bas URL configured for a loader.
PR Close#47082
This commit adds an extra logic to add an ability to exclude origins from preconnect checks in NgOptimizedImage by configuring the `PRECONNECT_CHECK_BLOCKLIST` multi-provider.
PR Close#47082
This commit updates the `NgOptimizedImage` directive to add a logic to detect whether an image, marked with the "priority" attribute has a corresponding `<link rel="preconnect">` tag in the `document.head` for better performance.
PR Close#47082
This commit adds a `rawSrcset` attribute as a replacement for the
`srcset` attribute. The `srcset` attribute cannot be set statically
on the image directive because it would cause images to start
downloading before the "loading" attribute could be set to "lazy".
Changing the name to `rawSrcset` allows the directive to control
the timing of image loading. It also makes it possible to support
custom loaders for `srcset` file names. Rather than having to repeat
the image origin for each image, the existing `rawSrc` value and
image loader can be composed to generate each full URL string. The
developer must only provide the necessary widths for the `srcset`.
For example, the developer might write:
```markup
<img rawSrc="hermes.jpg" rawSrcset="100w, 200w" ... />
```
with a loader like:
```js
const loader = (config) => `path/${config.src}?w=${config.width}`;
```
and the img tag will ultimately be set up as something like:
```markup
<img src="path/hermes.jpg?w=100" srcset="path/hermes.jpg?w=100 100w, path/hermes.jpg?w=200 200w" .../>
```
PR Close#47082
This commit adds e2e tests for the LCP check logic. Those tests are needed to verify the behavior in a real browser (vs relying on a Node environment).
PR Close#47082
This commit updates the `NgOptimizeImage` directive to add asserts to make sure the `width` and `height` inputs are set and have correct values (numbers only).
PR Close#47082
This commit creates and exposes the APIs required to use the Angular Router without importing `RouterModule`.
The newly added APIs are tree-shakable and you can add features using special functions rather than using `ExtraOptions` to control the providers via an internal switch in Router code.
```
const appRoutes: Routes = [];
bootstrapApplication(AppComponent,
{
providers: [
provideRouter(appRoutes,
withDebugTracing(), // enables debug tracing feature
withInMemoryScrolling() // enables scrolling feature
]
}
);
```
This "features" pattern allows for router behavior to evolve in a backwards compatible and tree-shakable way in the future. This approach also makes features more discoverable.
The newly added APIs can be used in any application today (doesn't require an application to be bootstrapped using standalone-based APIs).
Note: APIs added in this commit are released in the "Developer Preview" mode, read more about this mode in Angular docs: https://angular.io/guide/releases#developer-preview
PR Close#47010
Add wider typings to setter of preserveFragment, skipLocationChange and replaceUrl inputs of routerLink directives and coerce them to boolean
PR Close#47101
This brings the typing of ngStyle into parity with ngClass since commit
e2ab99b95e. Should help with some strict template checking edge cases.
PR Close#47069
The current Router APIs require guards/resolvers to be present in the DI tree. This is because we want to treat all guards/resolvers equally and some may require dependencies. This requirement results in quite a lot of boilerplate for guards. Here are two examples:
```
const MY_GUARD = new InjectionToken<any>('my_guard');
…
providers: {provide: MY_GUARD, useValue: () => window.someGlobalState}
…
const route = {path: 'somePath', canActivate: [MY_GUARD]}
```
```
@Injectable({providedIn: 'root'})
export class MyGuardWithDependency {
constructor(private myDep: MyDependency) {}
canActivate() {
return myDep.canActivate();
}
}
…
const route = {path: 'somePath', canActivate: [MyGuardWithDependency]}
```
Notice that even when we want to write a simple guard that has no dependencies as in the first example, we still have to write either an InjectionToken or an Injectable class.
With this commit router guards and resolvers can be plain old functions.
For example:
```
const route = {path: 'somePath', component: EditCmp, canDeactivate: [(component: EditCmp) => !component.hasUnsavedChanges]}
```
Additionally, these functions can still use Angular DI with `inject` from `@angular/core`.
```
const route = {path: 'somePath', canActivate: [() => inject(MyDependency).canActivate()]}
```
PR Close#46684
The `RootContext` implementation contained a number of fields that were needed to support an experimental `renderComponent` function. The `renderComponent` function was removed, which allows us to cleanup the `RootContext` further.
The only field that remains on the `RootContext` is the list of bootstrapped components. This list is presumably mostly unused right now (it just contains the current component) and further refactoring can happen in a followup PR.
PR Close#46806
This commit updates the `renderModule` and `renderApplication` functions to also accept a document reference (in addition to the serialized document contents as a string). This should provide the necessary flexibility to NgUniversal (and other API consumers) to structure the logic to avoid serializing and parsing document multiple times during the SSR request.
PR Close#47032
With strict template type checking, a null/undefined value will raise an
error. However the implementation is completely fine with it, and it
would be pointless to "fix" it at the callsite and convert to e.g. an
empty string. Allow all of the "supported types" to be passed in
directly to ngClass.
Fixes#39280
PR Close#46906
This commit adds the `defaultUrlMatcher` from the Router to the public
API. `UrlMatcher` and `UrlMatchResult` are already in the public api so
the signature of the function as well as the return value are already
exposed. Any change to those or the implementation of `defaultUrlMatcher`
would already be breaking so there's no additional risk in exposing the
default matcher.
This function can be useful for developers who want to create a custom
matcher which builds on the default matcher of the Router. Currently,
the only way to do this would be to copy-paste the implementation.
fixes#35928
PR Close#46913