`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
In #41106, code was added in angular.io to print info that would help us
investigate and debug a ServiceWorker issue (#28114). Since the fix for
the issue was deployed on October 6th, 2021, the related error rate has
dropped dramatically:

Additionally, there have been no known occurrences or reports of the
issue in the last several months.
The remaining occurrences could be attributed to older versions still
being around on people's devices (due to the ServiceWorker caching) and
other circumstances not related to the ServiceWorker, for which there is
not much we can do. For example, a user could keep a tab open with an
older version of the app, which requests hashed files that no longer
exist on the server. If the ServiceWorker is not activated on such a tab
(either because the browser does not support it or because the user has
disabled it, for example), then it is expected that these requests would
fail.
This commit removes the code that prints ServiceWorker-related debug
info to reduce the payload size of the app.
Fixes#41117
PR Close#46987
This commit adds the `isEmpty` method to the `TransferState` class to make it possible to check whether the state is empty or not. This is helpful in situations when the `TransferState` should be serialized and the content is transferred to the client (if the state is empty - certain operations can be omitted).
PR Close#46915
This commit updates the code to include the TransferState providers (used for serialization) into the `ServerModule` instead of having the need to import the `ServerTransferStateModule` separately.
The list of providers in the `ServerTransferStateModule` is now empty and importing it is a noop. This is not a breaking change, since the `ServerModule` must be included anyways to make server rendering work correctly.
PR Close#46899
This commit updates the `TransferState` to make it `providedIn: 'root'`. This makes the entire `BrowserTransferStateModule` module unnecessary, so it got deprecated as well.
The `ServerTransferStateModule` is still retained, but the `renderApplication` function now also includes the necessary tokens to serialize the `TransferState` automatically, so when using the `renderApplication` function, there is no need to include `ServerTransferStateModule` as well.
This change is a part of the ongoing efforts to update the shape of the FW APIs to make them standalone-friendly (so there is no need to import any NgModules).
PR Close#46879
The implementation of the `DefaultTitleStrategy` was modeled after the
existing strategy patterns in the Router. These patterns were developed
before the `providedIn` syntax for injectables. We can simplify the
model a lot by providing the default in the factory of the abstract
class.
Note that the other strategy patterns aren't touched in this PR due to
how long they've existed. Because they have been there for such a long
time, it's possible there will need to be some adjustments to code
if/when they are refactored to do the same.
PR Close#46876
The `createApplication` function makes it possible to create an
application instance (represented by the `ApplicationRef`)
without bootstrapping any components. It is useful in the
situations where ones wants to decouple and delay components
rendering and / or render multiple root components in one
application. Angular elements can use this API to create
custom element types with an environment linked to a
created application.
PR Close#46475
On MacOS, pressing the alt key and another key turns into symbols, and
doesn't match the intended behavior. For example, `keydown.alt.s`
reports instead as `keydown.alt.ß`. We rely on the `key` field and not
the `code` field, which properly reports the code for S in this case.
This change adds support to allow users to specify they want to look at
the `code` field instead of the `key` field within their event string.
Example: `keydown.code.alt.leftshift` would only match the LeftShift and
not the right shift based on code values. It would also allow the user
to specify `keydown.code.alt.keys` to match S instead of ß when alt /
option is pressed on MacOS and would also work on Windows.
Fixes#45992
PR Close#46030
convert the select for the docs versions into a proper navigation to
make it more clear for users and also to improve its accessibility
resolves#44339
PR Close#46674
The new `FormRecord` entity introduced in Angular v14 does not have its builder method.
This commit adds it, allowing to write:
```
const fb = new FormBuilder();
fb.record({ a: 'one' });
```
This works for both the `FormBuilder` and the `NonNullableFormBuilder`
PR Close#46485
This commit makes the router directives standalone and refactors some of
the Router injectables to be `providedIn: 'root'` along with factory
functions for initialization.
PR Close#46758
This commit refactors the code to move some functions around to avoid circular dependencies in TS imports. The newly added functions are now located in the `packages/core/src/render3/component.ts` file (instead of `packages/core/src/render3/component_ref.ts`), which is a better place for them anyway.
PR Close#46685