A structural directive can specify a template guard for an input, such that
the type of that input's binding can be narrowed based on the guard's return
type. Previously, such template guards could only be methods, of which an
invocation would be inserted into the type-check block (TCB). For `NgIf`,
the template guard narrowed the type of its expression to be `NonNullable`
using the following declaration:
```typescript
export declare class NgIf {
static ngTemplateGuard_ngIf<E>(dir: NgIf, expr: E): expr is NonNullable<E>
}
```
This works fine for usages such as `*ngIf="person"` but starts to introduce
false-positives when e.g. an explicit non-null check like
`*ngIf="person !== null"` is used, as the method invocation in the TCB
would not have the desired effect of narrowing `person` to become
non-nullable:
```typescript
if (NgIf.ngTemplateGuard_ngIf(directive, ctx.person !== null)) {
// Usages of `ctx.person` within this block would
// not have been narrowed to be non-nullable.
}
```
This commit introduces a new strategy for template guards to allow for the
binding expression itself to be used as template guard in the TCB. Now,
the TCB generated for `*ngIf="person !== null"` would look as follows:
```typescript
if (ctx.person !== null) {
// This time `ctx.person` will successfully have
// been narrowed to be non-nullable.
}
```
This strategy can be activated by declaring the template guard as a
property declaration with `'binding'` as literal return type.
See #30235 for an example where this led to a false positive.
PR Close#30248
The LocationShim (replacement for `$location`) was added to centralize dealing with the browser URL. Additionally, an `onUrlChange` method was added to Angular's Location service. This PR adds a corresponding method to the LocationShim so updates from AngularJS can be tracked in Angular.
PR Close#30466
Currently in Ivy `NgModule` registration happens when the class is declared, however this is inconsistent with ViewEngine and requires extra generated code. These changes remove the generated code for `registerModuleFactory`, pass the id through to the `ngModuleDef` and do the module registration inside `NgModuleFactory.create`.
This PR resolves FW-1285.
PR Close#30244
This is the final patch to migrate the Angular styling code to have a
smaller instruction set in preparation for the runtime refactor. All
styling-related instructions now work both in template and hostBindings
functions and do not use `element` as a prefix for their names:
BEFORE:
elementStyling()
elementStyleProp()
elementClassProp()
elementStyleMap()
elementClassMap()
elementStylingApply()
AFTER:
styling()
styleProp()
classProp()
styleMap()
classMap()
stylingApply()
PR Close#30318
This patch removes all host-specific styling instructions in favor of
using element-level instructions instead. Because of the previous
patches that made sure `select(n)` worked between styling calls, all
host level instructions are not needed anymore. This patch changes each
of those instruction calls to use any of the `elementStyling*`,
`elementStyle*` and `elementClass*` styling instructions instead.
PR Close#30336
This patch is one commit of many patches that will unify all styling instructions
across both template-level bindings and host-level bindings. This patch in particular
removes the `elementIndex` param because it is already set prior to each styling
instruction via the `select(n)` instruction.
PR Close#30313
This patch breaks up the existing `elementStylingMap` into
`elementClassMap` and `elementStyleMap` instructions. It also breaks
apart `hostStlyingMap` into `hostClassMap` and `hostStyleMap`
instructions. This change allows for better tree-shaking and reduces
the complexity of the styling algorithm code for `[style]` and `[class]`
bindings.
PR Close#30293
Fixes `HostBinding` and `HostListener` declarations not being inherited from base classes that don't have an Angular decorator.
This PR resolves FW-1275.
PR Close#30158
- Extracts and documents code that will be common to interpolation instructions
- Ensures that binding indices are updated at the proper time during compilation
- Adds additional tests
Related #30011
PR Close#30129
Previously, the ServiceWorker registration options should be defined as
an object literal (in order for them to be compatible with Ahead-of-Time
compilation), thus making it impossible to base the ServiceWorker
behavior on runtime conditions.
This commit allows specifying the registration options using a regular
provider, which means that it can take advantage of the `useFactory`
option to determine the config at runtime, while still remaining
compatible with AoT compilation.
PR Close#21842
The proposed ES dynamic import() is now supported by the Angular CLI and the
larger toolchain. This renders the `loadChildren: string` API largely
redundant, as import() is far more natural, is less error-prone, and is
standards compliant. This commit deprecates the `string` form of
`loadChildren` in favor of dynamic import().
DEPRECATION:
When defining lazy-loaded route, Angular previously offered two options for
configuring the module to be loaded, both via the `loadChildren` parameter
of the route. Most Angular developers are familiar withthe `string` form of
this API. For example, the following route definition configures Angular to
load a `LazyModule` NgModule from `lazy-route/lazy.module.ts`:
```
[{
path: 'lazy',
loadChildren: 'lazy-route/lazy.module#LazyModule',
}]
```
This "magic string" configuration was previously necessary as there was
no dynamic module loading standard on the web. This has changed with the
pending standardization of dynamic `import()` expressions, which are now
supported in the Angular CLI and in web tooling in general. `import()`
offers a more natural and robust solution to dynamic module loading. The
above example can be rewritten to use dynamic `import()`:
```
[{
path: 'lazy',
loadChildren: () => import('./lazy-route/lazy.module').then(mod => mod.LazyModule),
}]
```
This form of lazy loading offers significant advantages in terms of:
* type checking via TypeScript
* simplicity of generated code
* future potential to run natively in supporting browsers
(see: [caniuse: dynamic import()](https://caniuse.com/#feat=es6-module-dynamic-import))
As a result, Angular is deprecating the `loadChildren: string` syntax in
favor of ES dynamic `import()`. An automatic migration will run during
`ng upgrade` to convert your existing Angular code to the new syntax.
PR Close#30073
This commit provides a replacement for `$location`. The new service is written in Angular, and can be consumed into existing applications by using the downgraded version
of the provider.
Prior to this addition, applications upgrading from AngularJS to Angular could get into a situation where AngularJS wanted to control the URL, and would often parse or se
rialize the URL in a different way than Angular. Additionally, AngularJS was alerted to URL changes only through the `$digest` cycle. This provided a buggy feedback loop
from Angular to AngularJS.
With this new `LocationUpgradeProvider`, the `$location` methods and events are provided in Angular, and use Angular APIs to make updates to the URL. Additionally, change
s to the URL made by other parts of the Angular framework (such as the Router) will be listened for and will cause events to fire in AngularJS, but will no longer attempt
to update the URL (since it was already updated by the Angular framework).
This centralizes URL reads and writes to Angular and should help provide an easier path to upgrading AngularJS applications to Angular.
PR Close#30055
Without this change, the framework doesn't surface URL parts such as hostname, protocol, and port. This makes it difficult to rebuild a complete URL. This change provides new APIs to read these values.
PR Close#30055
Previously there wasn't a way to retrieve `history.state` from the `Location` service. The only time the framework exposed this value was in navigation events. This meant if you weren't using the Angular router, there wasn't a way to get access to this `history.state` value other than going directly to the DOM.
This PR adds an API to retrieve the value of `history.state`. This will be useful and needed to provide a backwards-compatible `Location` service that can emulate AngularJS's `$location` service since we will need to be able to read the state data in order to produce AngularJS location transition events.
This feature will additionally be useful to any application that wants to access state data through Angular rather than going directly to the DOM APIs.
PR Close#30055
Fixes view and content queries not being inherited in Ivy, if the base class hasn't been annotated with an Angular decorator (e.g. `Component` or `Directive`).
Also reworks the way the `ngBaseDef` is created so that it is added at the same point as the queries, rather than inside of the `Input` and `Output` decorators.
This PR partially resolves FW-1275. Support for host bindings will be added in a follow-up, because this PR is somewhat large as it is.
PR Close#30015
With dts bundles, `core.d.ts` will include an `EventListener` class as it's used in 303eae918d/packages/core/src/debug/debug_node.ts (L32)
This will conflict with the DOM EventListener, as anything in `core.d.ts` which is using the DOM EventListener will fallback in using the one defined in the same module and hence build will fail because their implementation is different.
With this change, we rename the local `EventListener` to `DebugEventListener`, the later one is non exported.
Fixes#29806
PR Close#29809
Plural ICU expressions depend on the locale (different languages have different plural forms). Until now the locale was hard coded as `en-US`.
For compatibility reasons, if you use ivy with AOT and bootstrap your app with `bootstrapModule` then the `LOCALE_ID` token will be set automatically for ivy, which is then used to get the correct plural form.
If you use JIT, you need to define the `LOCALE_ID` provider on the module that you bootstrap.
For `TestBed` you can use either `configureTestingModule` or `overrideProvider` to define that provider.
If you don't use the compat mode and start your app with `renderComponent` you need to call `ɵsetLocaleId` manually to define the `LOCALE_ID` before bootstrap. We expect this to change once we start adding the new i18n APIs, so don't rely on this function (there's a reason why it's a private export).
PR Close#29249
The `Δ` caused issue with other infrastructure, and we are temporarily
changing it to `ɵɵ`.
This commit also patches ts_api_guardian_test and AIO to understand `ɵɵ`.
PR Close#29850
So far using runtime i18n with ivy meant that you needed to use Closure and `goog.getMsg` (or a polyfill). This PR changes the compiler to output both closure & non-closure code, while the unused option will be tree-shaken by minifiers.
This means that if you use the Angular CLI with ivy and load a translations file, you can use i18n and the application will not throw at runtime.
For now it will not translate your application, but at least you can try ivy without having to remove all of your i18n code and configuration.
PR Close#28689
Currently in Ivy we pass both the raw and parsed selectors to the projectionDef instruction, because the parsed selectors are used to match most nodes, whereas the raw ones are used to match against nodes with the ngProjectAs attribute. The raw selectors add a fair bit of code that won't be used in most cases, because ngProjectAs is somewhat rare.
These changes rework the compiler not to output the raw selectors in the projectionDef, but to parse the selector in ngProjectAs and to store it on the TAttributes. The logic for matching has also been changed so that it matches the pre-parsed ngProjectAs selector against the list of projection selectors.
PR Close#29578
Adds an overload to TestBed.get making parameters strongly typed and
deprecated previous signature that accepted types `any`. The function
still returns `any` to prevent build breakages, but eventually stronger
type checks will be added so a future Angular version will break builds
due to additional type checks.
See previous breaking change - #13785
Issue #26491
PR Close#29290
This new interface will match classes whether they are abstract or
concrete. Casting as `AbstractType<MyConcrete>` will return a type that
isn't newable. This type will be used to match abstract classes in the
`get()` functions of `Injector` and `TestBed`.
Type isn't used yet so this isn't a breaking change.
Issue #26491
PR Close#29295
Previously we had to share code between upgrade/dynamic and upgrade/static
by symlinking the `src` folder, which allowed both packages to access
the upgrade/common files.
These symlinks are always problematic on Windows, where we had to run
a script to re-link them, and restore them.
This change uses Bazel packages to share the `upgrade/common` code,
which avoids the need for symlinking the `src` folder.
Also, the Windows specific scripts that fixup the symlinks have also
been removed as there is no more need for them.
PR Close#29466
The router loadChildren property already supports a promise that returns a NgModuleFactory, but the typings cause the compilation to fail.
PR Close#29392
Just updating comments in query-related things to make it easier for the next person that has to grok this for the first time.
Also adds a demo from @mhevery to one of the query specs
Related #29031
PR Close#29342
Just updating comments in query-related things to make it easier for the next person that has to grok this for the first time.
Also adds a demo from @mhevery to one of the query specs
Related #29031
PR Close#29342
This method is a more convenient and efficient way of removing all
components from a FormArray. Before it, we needed to loop the FormArray
removing each component until empty.
Resolves#18531
PR Close#28918
If an interface is not exported publicly from its package, then the doc-gen
does not see it, and so cannot include it in the generated documentation.
This was the case for a number of `...Decorator` interfaces, such as
`PipeDecorator` and `InputDecorator.
This commit adds these interfaces to the public export to fix this problem.
PR Close#28836
Prior to this fix, both the `NgStyle` and `NgClass` directives made use
of `Renderer2` and this dependency raised issues for future versions of
Angular that cannot inject it. This patch ensures that there are two
versions of both directives: one for the VE and another for Ivy.
Jira Issue: FW-882
PR Close#28711
The `setUpLocationSync` function in @angular/router/upgrade didn't previously let you sync hash-based navigations. With this change, you can now pass an option to `setUpLocationSync` that will make sure location changes run in Angular in hash-based apps.
Fixes#24429#21995
PR Close#28609
Prior to this commit, the timing of `ViewChild`/`ContentChild` query
resolution depended on the results of each query. If any results
for a particular query were nested inside embedded views (e.g.
*ngIfs), that query would be resolved after change detection ran.
Otherwise, the query would be resolved as soon as nodes were created.
This inconsistency in resolution timing had the potential to cause
confusion because query results would sometimes be available in
ngOnInit, but sometimes wouldn't be available until ngAfterContentInit
or ngAfterViewInit. Code depending on a query result could suddenly
stop working as soon as an *ngIf or an *ngFor was added to the template.
With this commit, users can dictate when they want a particular
`ViewChild` or `ContentChild` query to be resolved with the `static`
flag. For example, one can mark a particular query as `static: false`
to ensure change detection always runs before its results are set:
```ts
@ContentChild('foo', {static: false}) foo !: ElementRef;
```
This means that even if there isn't a query result wrapped in an
*ngIf or an *ngFor now, adding one to the template later won't change
the timing of the query resolution and potentially break your component.
Similarly, if you know that your query needs to be resolved earlier
(e.g. you need results in an ngOnInit hook), you can mark it as
`static: true`.
```ts
@ViewChild(TemplateRef, {static: true}) foo !: TemplateRef;
```
Note: this means that your component will not support *ngIf results.
If you do not supply a `static` option when creating your `ViewChild` or
`ContentChild` query, the default query resolution timing will kick in.
Note: This new option only applies to `ViewChild` and `ContentChild`
queries, not `ViewChildren` or `ContentChildren` queries, as those types
already resolve after CD runs.
PR Close#28810