This commit introduces a new type `EnvironmentProviders` which can be used
in contexts where Angular accepted `Provider`s destined for
`EnvironmentInjector`s. This includes contexts such as `@NgModule.providers`
and `Route.providers`.
The new type is useful for preventing such providers from accidentally
ending up in `@Component.providers`. It can be used as the return type of
provider functions (such as `provideRouter`) to enforce this safety.
Because `Provider` allows `any[]` nested arrays, the compile-time safety
provided by `EnvironmentProviders` is easily circumvented. However, the
runtime shape of `EnvironmentProviders` is not compatible with component
injectors and will result in a runtime error if it leaks through (NG0207).
A new function `makeEnvironmentProviders` is used to construct this new type
from an array of providers.
The existing `importProvidersFrom` operation previously returned a very
similar type `ImportedNgModuleProviders` which had the same goal. This
machinery is switched over to use the new `EnvironmentProviders` interface
instead (in fact, `ImportedNgModuleProviders` is now just an alias to
`EnvironmentProviders`).
PR Close#47669
Enables the new directive composition API by exposing the `hostDirectives` property on the `Directive` and `Component` decorators. Also cleans up some casts that were put in place while the feature was being developed.
Fixes#8785.
PR Close#47642
Adds support for host directives on the root component by calling `findHostDirectiveDefs` and passing the results to the relevant functions.
PR Close#47620
The `NgOnChanges` feature matches some legacy ViewEngine behavior where the keys in the `SimpleChanges` object are based on the *declared* names of the inputs, not the public or minified names. This is achieved by constructing the `DirectiveDef.declaredInputs` object at the same time as when `DirectiveDef.inputs` is created.
This logic breaks down for host directives, because they can re-alias the input under a different public name which won't be present in the `declaredInputs`.
These changes add some logic to patch the directive def aliases onto the `declaredInputs`. There is some validation in place to ensure that this patching doesn't overwrite any pre-existing inputs.
PR Close#47597
Adds the logic that will filter out unexposed inputs/outputs and apply the aliases that the author specified when writing the host directives.
PR Close#47536
This commit applies the changes similar to the ones performed for the `inject()` function in df246bb235.
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 df246bb235.
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
Exposes the host directives to the host and its descendants through DI. This can be useful, because it allows the host to further configure the host directives.
PR Close#47476
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
Unify default value handling across injector and node injector: as long
as a default value is provided it has the same effect as specifying the
@Optional() flag.
Fixes#47109
PR Close#47242
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
Similarly to what has been done in #46846 for the extended diagnostics about missing control flow directive that was only mentioning that the `CommonModule` should be imported, this commit improves the validation done by the JiT compiler.
Now that the control flow directives are available as standalone, the message mentions that directive itself can be imported.
The message now also mentions which import should be used for the directive (as it can be tricky to figure out that `NgForOf` is the directive corresponding to `*ngFor`).
PR Close#46903
This commit refactors the `NgModuleRef` implementation to drop functions required by the `EnvironmentInjector` interface. Previously the idea was that the `NgModuleRef` can act as an Injector to facilitate easier transition to standalone. However, from the mental model perspective, the `NgModuleRef` has the `injector` field, which is the correct injector reference and can be used is needed as an `EnvironmentInjector`.
PR Close#46896
This commit introduces a new function that allows creating a object which exposes a number of getters to retrieve information about a given component.
Closes#44926.
PR Close#46685
This commit introduces a new function that allows creating a `ComponentRef` instance based on provided Component and a set of options. The function can be used to cover a number of use-cases where the `ComponentFactory` symbol was used previously.
Closes#45263.
PR Close#46685
Currently if the `ENVIRONMENT_INITIALIZER` token is not configured with `multi: true` flag, the code fails while trying to iterate over the value. This commit checks whether the `ENVIRONMENT_INITIALIZER` token value type is an array and throws a helpful error message.
PR Close#46829
This commit adds the `createNgModuleRef` function alias to the public API. The alias is called `createNgModule`. The `createNgModule` name is more consistent with the rest of the API surface, where functions that return `*Ref`s don't include the `Ref` into the function name, for example: `createPlatform`, `ViewContainerRef.createComponent`, etc.
DEPRECATED:
The `createNgModuleRef` is deprecated in favor of newly added `createNgModule` one.
PR Close#46789
`inject()` originated as a private API and was made public to support
`InjectionToken` factories in Ivy. For code-size and performance reasons,
when we code generate `inject()` calls we use a bit field to indicate the
various injection modes (optional, skip-self, etc). However, this doesn't
make for a very nice public API.
This commit introduces an alternative object-based API for options. All 4
flags are supported as `boolean` fields on an options object, and converted
to bit flags internally. If TypeScript can prove that `optional` injection
is not requested, it can narrow the return type and remove the `null` type.
DEPRECATED:
The bit field signature of `inject()` has been deprecated, in favor of the
new options object. Correspondingly, `InjectFlags` is deprecated as well.
Fixes#46251
PR Close#46649
This commit introduces a new API on `EnvironmentInjector` to run a function
in the context of the injector. This makes `inject()` available within the
body of the function to inject dependencies. We expect this functionality to
be very useful for designing ergonomic APIs both in and out of Angular, as
it should allow for a smaller and more functional API style.
Note that it's possible to implement nearly identical functionality in user
code already today:
```typescript
function runInContext<T>(injector: EnvironmentInjector, fn: () => T): T {
const token = new InjectionToken<T>('TOKEN');
const tmpInjector = createEnvironmentInjector([
{provide: token, useFactory: () => fn()},
], injector);
return tmpInjector.get(token);
}
```
The factory provider for `token` in this example runs in the context of the
`tmpInjector`, giving it access to `inject` that can retrieve values from
`injector` as well. This is nearly identical, although because of the child
injector `self` and `skipSelf` injection options don't function correctly.
PR Close#46653
This commit removes the `Renderer3` experiment which attempted to use the
real DOM API as Angular's renderer. As shown in the diff, having this
experiment around added real code complexity to Angular that could not be
removed by an optimizer.
Since we no longer feel this experiment is worth continuing, we're removing
the `Renderer3` concept and all supporting code.
PR Close#46605
This commit migrates any remaining Angular tests which are using some form
of Renderer3 interfaces. Instead, they're switched to Renderer2.
PR Close#46605
Remove calls to enableRenderer3 in the functional unit tests.
This effectivelly cuts code paths going through the Renderer3
in the functional tests.
PR Close#46612
The `Renderer3` abstraction in Angular was an experimental code path in Ivy
which uses direct DOM operations instead of the former `Renderer2` path. To
allow `Renderer2` to tree-shake away, `Renderer3` is the default _unless_
`Renderer2` is provided. It was only an experiment, and never meant to be a
production code path.
However, it's possible for `Renderer3` to leak into user code. This commit
prevents that possibility by causing the `Renderer3` path to throw, unless
an explicit function has been called to enable it.
PR Close#46530
This commit updates a set of tests to avoid using hand-written instructions and replace them with TestBed APIs. Some tests were moved to the `acceptance` folder to colocate them with other renderer-related tests.
PR Close#46525
During JIT compilation of standalone components the compiler did not deduplicate
declarations in the imports array, unlike the AOT compiler. This may result in
runtime errors during directive matching, when the same component is found
multiple times resulting in NG0300, for example:
> NG0300: Multiple components match node with tagname mat-form-field: MatFormField and MatFormField.
This commit fixes the issue by deduplicating imports in the JIT compiler.
Relates to https://github.com/angular/angular/issues/46109#issuecomment-1160705031Closes#46109
PR Close#46439
Fixes that the server renderer was producing an invalid `style` attribute when a null value is passed in. Also aligns the behavior with the DOM renderer by removing the attribute when it's empty.
Fixes#46385.
PR Close#46433
Previously, the `createEnvironmentInjector` function allowed creating an instance of an EnvironmentInjector without providing a parent injector. This resulted in an injector instance, which was detached from the DI tree, thus having limited value. This commit updates the types of the `createEnvironmentInjector` function to make the parent injector a required argument.
PR Close#46397
Add info to the pipe not found error message so to give some help to the developer for
resolving the problem more efficiently
(Note: this change also distinguishes the case in which the hosting component is standalone)
PR Close#46247
improve code regarding element validation by creating a new file
exporting validation functions and not exporting utils previously
globally available
PR Close#46175
This commit adds the component name into unknown element/property error message, so that it's easier to find a location of a template where the problem happened.
Closes#46080.
PR Close#46160
Prior to this commit, the error message that was produced for the unknown property situation, din't contain extra info on how the problem can be fixed. This commit adds more info to the error message and makes it similar to the one we use during the AOT compilation.
PR Close#46147
improve the error message developers get when adding a standalone
component in the TestBed.configureTestingModule's declarations array,
by making more clear the fact that this error originated from the
TestBed call
resolves#45923
PR Close#45999
Currently for cases when an unknown structural directive is applied to `<ng-template>`s, an error message thrown by the framework doesn't contain a tag name, for example:
```
NG0303: Can't bind to 'unknownDir' since it isn't a known property of 'null'.
```
The underlying reason is that the tag name for the `<ng-template>` is not produced (`null` is useed as a value) by the compiler in case of inline templates and runtime logic relies on this effect.
This commit handles this situation when an error message is thrown, as the fastest way to improve the error message. More refactoring would be needed to avoid relying on the mentioned effect at runtime.
PR Close#46068
update the error message presented during jit compilation when an unrecognized
tag/element is found in a standalone component so that it does not mention
the ngModule anymore
Note: the aot variant is present in PR #45919resolves#45818
PR Close#45920
The `inject()` function was introduced with Ivy to support imperative
injection in factory/constructor contexts, such as directive or service
constructors as well as factory functions defined in `@Injectable` or
`InjectionToken`. However, `inject()` in a component/directive constructor
did not work due to a flaw in the logic for creating the internal factory
for components/directives.
The original intention of this logic was to keep `ɵɵdirectiveInject` tree-
shakable for applications which don't use any component-level DI. However,
this breaks the `inject()` functionality for component/directive
constructors.
This commit fixes that issue and adds tests for all the various cases in
which `inject()` should function. As a result `ɵɵdirectiveInject` is no
longer tree-shakable, but that's totally acceptable as any application that
uses `*ngIf` or `*ngFor` already contains this function. It's possible to
change how `inject()` works to restore this tree-shakability if needed.
PR Close#45991
Allows to provide a TestBed option to throw on unknown properties in templates:
```ts
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(), {
errorOnUnknownProperties: true
}
);
```
The default value of `errorOnUnknownProperties` is `false`, so this is not a breaking change.
PR Close#45853
This commit narrows down acceptable argument types of the
`importProvidersFrom` function. More specifically, it rejects
standalone components as a source of imports.
PR Close#45837