Fast and productive web framework provided by Dart
Added ComponentRef.update()
. This method should be used to apply changes
to a component and then trigger change detection. Before this, change
detection and lifecycles would not always follow Angular's specifications
when imperatively loading a component, especialy for those using the OnPush
change detection strategy.
final componentRef = componentFactory();
componentRef.update((component) {
component.input = newValue;
});
Added @changeDetectionLink
to package:angular/experimental.dart
.
This annotation allows a component that imperatively loads another component from a user-provided factory to adopt the OnPush change detection strategy, without dictacting the change detection strategy of the component created from the factory. This allows such a component to be used in both Default and OnPush apps.
An annotated component will serve as a link between an ancestor and an imperatively loaded descendant that both use the Default change detection strategy. This link is used to change detect the descendant anytime the ancestor is change detected, thus honoring its Default change detection contract. Without this annotation, the descendant would be skipped anytime the annotated OnPush component had not been marked to be checked.
For more details, see this annotation's documentation.
Added an optional named parameter, maxIterations
, to
FakeTimeNgZoneStabilizer
's constructor. If not specified 10 maximum loops
are attempted to elapse
pending timers. In advanced use cases, a test may
configure a higher threshold:
NgZoneStabilizer allow100InsteadOf10() {
return FakeTimeNgZoneStabilizer(timerZone, ngZone, maxIterations: 100);
}
NgTestFixture.update()
now delegates to ComponentRef.update()
, which
automatically calls markForCheck()
. Previously, an OnPush
component
under test might not have been properly updated.The InjectorReader now fails with an explicit error if types are used inside a ValueProvider object. Previously, using types in ValueProviders would crash the AngularDart compiler.
Instead of a ValueProvider, use a FactoryProvider for complicated objects, such as those that contain types.
Removed the i18n
compiler flag that was previously used to opt-in to
internationalization in templates before the feature had stabilized.
Added support for a command-line flag, allowed_typedefs_as_di_token
. This
is intended to be used as a transitional flag to ban using a typedef
as a
DI token (which has non-predictable properties in Dart 2).
Added $ChangeDetectionLink
, a type checker for matching the experimental
@changeDetectionLink
annotation.
The OnChanges
lifecycle has been completely removed. Use AfterChanges
instead.
ExceptionHandler
is no longer exported via angular/di.dart
. Import this
symbol via angular/angular.dart
instead.
Directives no longer support extending, implementing, or mixing in
ComponentState
.
The /deep/
and >>>
combinators are no longer supported in style sheets
of components with style encapsulation enabled. The special ::ng-deep
pseudo-element should be used in their stead to pierce style encapsulation
when necessary.
ChangeDetectorRef.checkNoChanges()
has been removed from the public API.
ChangeDetectorRef.detach()
and ChangeDetectorRef.reattach()
.
Components that rely on these methods should use changeDetection: ChangeDetectionStrategy.OnPush
instead.Navigation requests triggered by popstate
events that redirect back to the
active route will now correctly update the browser location to match the
active route. Prior to this fix, the browser location would be left in the
state changed by the popstate
event.
The history stack prior to the current entry is now preserved when preventing a navigation triggered by the back button. Previously, preventing such a navigation would erase the previous history entry, causing subsequent history manipulations to have unexpected results.
analyzer
.ThrowingTemplateAstVisitor
which throws by default in each visit
method.The template compiler issues a warning if a component that does not project content has children. Previously, these nodes were created and never attached. Now the nodes are not created at all.
Specialized interpolation functions for Strings.
Optimization: Removes toString() calls of interpolated strings bound to properties.
The compiler now uses superclass information to determine immutability.
Added Injector.provideTypeOptional
and Injector.provideTokenOptional
.
The compiler now optimizes string bindings inside NgFor
loops.
The compiler now adds type information to local variables in nested NgFor
loops.
The compiler now includes source locations to errors in annotations on class members.
The compiler now optimizes change detection for HTML Text nodes.
Disabled an optimization around pure-HTML DOM nodes wrapped in a *ngIf
. In
practice this optimization only kicked in for a few views per application
and had a high runtime cost as well as a high overhead for the framework
team. We have added and expect to add additional optimizations around the
size of generated views.
The template compiler now outputs the full path to a template file when it reports an error.
#1694: Composite keyup
and keydown
event bindings now ignore
synthetic events (e.g. those triggered by a mouse click) instead of throwing
a TypeError
.
#1669: Fixed a regression which prevented a pipe invoked with more than two arguments from being passed as an argument to a function.
The compiler emits source locations for errors in Dart files when using an
AnalysisDriver
.
Internationalized attribute, property, and input bindings will now properly
escape characters in the message that would invalidate the generated string
(such as \n
, $
, and '
). This behavior is now consistent with
internationalized text and HTML.
The template compiler no longer crashes on HTML attributes ending in ":"
When querying for a directive present in multiple embedded views (portions
of the template controlled by a structural directive such as *ngIf
) with
@ViewChildren()
, the directives in the resulting list are now in the same
order as they appear in the template. Prior to this fix, directives in
nested embedded views would occur before those in their parent view.
The template compiler now properly updates class statements for "literal
attributes". Previously, we did not shim these classes correctly. This
includes both raw attributes (e.g. class="foo"
) and host bindings (e.g.
@HostBinding('class')
).
The presence of a query (e.g. @ContentChild(TemplateRef)
) no longer causes
any matching <template>
references to become available for dynamic
injection (i.e. injector.provideType(TemplateRef)
).
The template compiler now properly updates class bindings on SVG elements. Previously, we did not shim these classes correctly.
When using runAppAsync
, beforeComponentCreated
now runs within NgZone
which previously surfaced bugs when services created and initialized in this
callback did not trigger change detection.
The style sheet compiler will no longer emit invalid Dart code when a style sheet is placed within a directory whose name is not a valid Dart identifier.
The template compiler will now report a helpful error message when an
@i18n.skip
annotation has no corresponding @i18n
description, instead of
throwing an unhandled error.
Removed castCallback2ForDirective
from meta.dart
. In practice this was
not used. We also deprecated castCallback1ForDirective
now that the
directiveTypes: [ ... ]
feature is live.
Removed deprecated AppViewUtils.resetChangeDetection()
. This method was
never intended to be used in the public API, and is no longer used by our
own infra.
Using anything but ChangeDetectionStrategy.{Default|OnPush}
is considered
deprecated, as they were not intended to be publicly accessible states.
See the deprecation messages for details.
ViewContainerRef.get()
now returns a ViewRef
instead of an
EmbeddedViewRef
.
For context, ViewContainerRef
supports inserting both host views (created
via ComponentFactory
) and embedded views (created via TemplateRef
).
Today, EmbeddedViewRef
can reference either kind of view, but in the
future it will only reference the latter, for which its methods are actually
relevant (for example setting locals has no purpose on host views). This
change is in preperation for when a host view reference may not implement
EmbeddedViewRef
.
OnChanges
is now officially deprecated. Please use AfterChanges
instead.
changes
map at all, just remove the parameter and
you're good to go.valueChanged
, which can be set in the value
setter and
then checked in ngAfterChanges
.changes
map, then consider
recreating the map manually.FakeTimeNgZoneStabilizer
.RouteDefinition.defer
now supports an optional prefetcher
parameter
which can be defined to prefetch additional resources that are dependent on
the matched RouterState
.
The RouteDefinition
subclasses DeferredRouteDefinition
,
RedirectRouteDefinition
, and ComponentRouteDefinition
are now exported
from package:angular_router/testing.dart
.
Deferred route loaders and prefetchers are no longer called a second time when matched during route resolution.
Navigation requests triggered by popstate
events will now update the
browser location if the resulting navigation matches a redirecting route or
is transformed by a RouterHook
implementation.
FormatExceptions thrown while parsing modules in InjectorReader are now rethrown as BuildErrors with source information.
The InjectorReader will fail earlier in the compile process on parse errors.
Unhandled errors from InjectorReader are now caught and reported with source information.
BuildError now has factory constructors to create errors for annotations and elements.
*ngFor
) are now
reported to the registered ExceptionHandler
rather than thrown.The template parser no longer supports styles defined inside the template itself.
Previously, the following two snippets would have been parsed and shimmed in the same way.
<style> .my-class {padding: 10px;} </style>
@Component(
styles: ['.other-class {padding: 10px;}'],
)
class ExampleComponent{}
Now, only the latter will be parsed and shimmed. The former will be ignored.
The template parser no longer supports loading stylesheets defined in an
<link>
tag in the template itself.
Previously, the following two snippets would have loaded the exact same stylesheet.
<link href="my-styles.css" rel="stylesheet" />
@Component(
styleUrls: ['my-styles.css'],
)
class ExampleComponent {}
Now, only the latter will actually be loaded. The former will be ignored.
The deprecated field, ComponentRef.componentType
, which always threw, has
now been completely removed. This was a legacy field for older clients of
AngularDart.
Better error messages in the compiler by failing fast on all analyzer errors in element annotations (@Component, etc) and passing the analyzer error messages to the user.
Added runAfterChangesObserved
to NgZone
. This API is intended to be a
more precise way to execute code after AngularDart would have run change
detection (instead of relying on scheduleMicrotask
or Timer.run
).
Added new type-safe ways to use the Injector
API without dynamic calls:
void example(Injector injector) {
// Injecting "SomeType".
// Before:
var someType1 = injector.get(SomeType) as SomeType;
// After:
var someType2 = injector.provide<SomeType>();
// Injecting "OpaqueToken<SomeType>(...)".
// Before:
var someToken1 = injector.get(someToken) as SomeType;
// After:
var someToken2 = injector.provideToken(someToken);
}
The code in generated AppView
no longer performs null safety ?.
checks
when calling child views .destroy()
or .destroyNestedViews()
. This means
that misbehaving code could have slightly more confusing stack traces
(new null errors), at the benefit of reduced code-size across the board.
It's now a build error for @Component()
to include an entry in
directiveTypes
that types a directive not present in directives
.
#1653: AppView.lastRootNode
now correctly returns the last root node
when multiple ViewContainer
s are directly nested.
When using the @deferred
annotation in a template file, ensure that the
constructed component class uses the deferred import. For example, we now
emit deflib1.ComponentName(...)
instead of lib1.ComponentName(...)
. This
should ensure Dart2JS properly defer loads the entire component.
Typing a generic directive with a private type argument is now a build
error. Directive type arguments must be public so that they can be
referenced by the generated library that instantiates the directive.
Previously, this would build successfully but emit code that instantiated
the directive with dynamic
in place of the private type.
#1665: @Optional()
dependencies of pipes are now correctly treated as
optional. Previously the annotation was ignored, and attempting to
instantiate the pipe with a missing optional dependency would throw an error
for the missing dependency.
#1666: Properly emit calls from event bindings in templates where the tear-off function has one or more named arguments. Previously we would consider named arguments in the same vane as positional, and it would generate invalid code causing Dart2JS or DDC to fail compilation.
The @deferred
annotation now also defers the annotated component's
defining library, rather than just its generated template's library.
Changed NgTestStabilizer
initialization from originating from a
List<NgTestStabilizerFactory>
to a single NgTestStabilizerFactory
. The
new top-level function composeStabilizers
may be used to create a
composite factory from multiple factories:
composeStabilizers([
(_) => stabilizer1,
(_) => stabilizer2,
])
This helps disambiguate the order of stabilizers running, which in turn will allow additional new stabilizers and features to be added in a non-breaking fashion. This change does not impact users that were not augmenting or creating their own stabilizers (i.e. most users/most tests).
Removed NgTestStabilizer.all
. See composeStabilizers
instead.
Removed NgZoneStabilizer
. The new class is RealTimeNgZoneStabilizer
,
though most users should not be impacted NgTestBed
now uses the new
stabilizer by default.
NgTestStabilizer.alwaysStable
, which does what it sounds like
and always reports stability. This handles making composition easier as the
root stabilizer can effectively be a no-op.RealTimeNgZoneStabilizer
, do not try to stabilize timers that
run outside of Angular zone.Updates the messages.unresolvedSource
API to support different error
messages for each SourceSpan
affected.
Update failure message to include an asset id when collecting type parameters.
TypedReader
now throws a build error when reading a private type argument.
Added support for generic components and directives.
Type arguments can now be specified for any generic components and
directives via Typed
instances passed to the Component
annotation's
directiveTypes
parameter.
@Component(
selector: 'generic',
template: '{{value}}',
)
class GenericComponent<T> {
@Input()
T value;
}
@Component(
selector: 'example',
template: '''
<generic [value]="value"></generic>
''',
directives: [
GenericComponent,
],
directiveTypes: [
Typed<GenericComponent<String>>(),
],
)
class ExampleComponent {
var value = 'Hello generics!';
}
The Typed
class also has support for typing specific component and
directive instances by #
-reference, and flowing generic type parameters
from the annotated component as type arguments to its children. See its
documentation for details.
#930: Added @visibleForTemplate
to package:angular/meta.dart
. This
is an optional annotation that may be used to annotate elements that
should only be used from within generated code (i.e. a .template.dart
).
It is a compile-time hint, which may be treated as a failing build, to use
annotated elements outside of the component or template.
This annotation is intended to give component authors more control in
specifying the public API of their component(s), especially coupled with the
fact that AngularDart requires all members to be public to be reachable from
generated code. For example, c
and ngAfterChanges
are only accessible
from CalculatorComponent
(or its template) in the following:
import 'package:angular/angular.dart';
import 'package:angular/meta.dart';
@Component(
selector: 'calculator-comp',
template: '{{a}} + {{b}} = {{c}}',
)
class CalculatorComponent implements AfterChanges {
@Input()
num a = 0;
@Input()
num b = 0;
@visibleForTemplate
num c = 0;
@override
@visibleForTemplate
void ngAfterChanges() {
c = a + b;
}
}
NOTE: This feature is only enforced in SDK: >=2.1.0-dev.3.1
.
Added support for internationalization in templates.
The @i18n
annotation marks content in document fragments or attributes for
internationalization via integration with package:intl
.
A document fragment can be internationalized by applying the @i18n
annotation to its parent element:
<div @i18n="A description of the message.">
A message to be <i>translated</i>!
</div>
An attribute, property, or input <name>
can be internationalized by
applying the @i18n:<name>
annotation to its host element:
<input
placeholder="A message to be translated"
@i18n:placeholder="A description of the message.">
Note that internationalization in templates currently only supports messages with static text and HTML. See the example for more details.
#1538: A compile-time error is reported if the @deferred
template
annotation is present on a <template>
element or is a sibling to a
structural directive (such as *ngIf
). Before we would silently drop/ignore
the annotation, so this might be considered a breaking change of an
incorrect program. The fix is just to move the annotation, such as:
<!-- Before (Both are identical) -->
<template @deferred [ngIf]="showArea">
<expensive-comp></expensive-comp>
</template>
<expensive-comp *ngIf="showArea" @deferred></expensive-comp>
<!-- After (Both are identical) -->
<template [ngIf]="showArea">
<expensive-comp @deferred></expensive-comp>
</template>
<ng-container *ngIf="showArea">
<expensive-comp @deferred></expensive-comp>
</ng-container>
#1558: When importing a library.dart
that has two or more components
(i.e. Comp1
and Comp2
), and at least one component is used @deferred
and at least one component is used without @deferred
, the compiler would
generate invalid Dart code that would fail analysis/compilation to JS.
Correct code is now emitted, allowing the described scenario to work.
#1539: Fixed a bug where components that were @deferred
as the direct
child of another <template>
tag had phantom DOM left behind even after the
parent template was destroyed. For example:
<template [ngIf]="showComponent">
<expensive-comp @deferred></expensive-comp>
</template>
... additionally, a check for a race condition of the deferred component
being loaded after the parent view was already destroyed was added. As
a result, #1540 has also been fixed (view and content queries were not
getting reset as the @deferred
node was destroyed).
#880: Fixed a bug where an extraneous space in *ngFor
micro expression
caused the directive to no longer be functional
(*ngFor="let x; let i = $index "
, for example).
#1570: When a provider's token
for @GeneratedInjector(...)
is read
as null
(either intentionally, or due to analysis errors/imports missing)
a better error message is now thrown with the context of the error.
#434: In development mode, creating a component or service C
that
attempts to inject a missing dynamic dependency D
will now throw an error
message containing Could not find provider for D: C -> D
. Previously the
message was only Could not find provider for D
in these cases, which was
often not enough information to debug easily.
#1502: When parsing an invalid template micro expression (i.e.
*ngFor="let item of items;"
- note the trailing ;
), throws a proper
unexpected token error instead of a confusing type error during recovery.
#1500: Configuring a provider with FactoryProvider(Foo, null)
is now
a compile-time error, instead of a misleading runtime error.
#1591: Using @GenerateInjector
with a ValueProvider
bound to a
String
instance that expects a raw string (i.e r'$5.00'
) no longer
generates invalid code. Now all strings are emitted as raw.
#1598: Using @GenerateInjector
with a ValueProvider
whose value
is created as a const
object with named arguments is now created
correctly. Before, all named arguments were skipped (left to default values,
which was often null
).
@GenerateInjector(...)
now correctly solves duplicate tokens by having
the last, not first, provider win. This aligns the semantics with how
the other injector implementations work. For MultiToken
, the order stays
the same.
Clarified that Injector.map({...})
doesn't support null
as values.
Named arguments are now supported for function calls in templates where the
function is an exported symbol (Component(exports: [someFunction])
).
#1625: Named arguments in function calls in templates that collide with
an exported symbol (Component(exports: [someExport])
) no longer cause a
parsing error.
Whitespace in internationalized message descriptions and meanings is now normalized so they're no longer affected by formatting changes. Identical messages with meanings that are formatted differently will now properly be treated as the same message.
#1633: Using a function type or any non-class Type
inside of the
@GenerateInjector([...])
annotation would cause a non-ideal error to be
produced. It now includes more information where available.
Error messages for misconfigured pipes now display their source location.
Assertion added for ensuring different SanitizationServices aren't used when calling runApp multiple times. SanitizationService is a static resource so different instances would not work as expected.
AppViewUtils.resetChangeDetection()
is now deprecated and will be removed
in the next major release.
PatternValidator
now has a pattern
input. This allows the pattern
property to be set dynamically. Previously, this could only be specified
statically at compile time.Supported beforeComponentCreated(Injector)
when creating fixture to allow
using injector
to set up prerequisite data for testing from DI.
This is useful when an object (that is already injected to the app) is difficult to create otherwise. For example:
// ComplexDataLayer is difficult to instantiate in test, but it is needed
// to set up some fake data before the component is loaded and used.
final fixture = await testBed.create(
beforeComponentCreated: (i) {
var dataLayer = i.get(ComplexDataLayer) as ComplexDataLayer;
dataLayer.setUpMockDataForTesting();
},
);
RouterLinkDirective
, and
the browser location to which it would navigate upon being clicked when
using routerProvidersHash
.Catches an (invalid) null
token of a provider and throws a better error.
Catches an (invalid) null
value of the function for FactoryProvider
.
Emits all strings for @GeneratedInjector
as raw (r'$5.00'
).
Supports named arguments for ValueProvider
and @GeneratedInjector
.
Prevents InjectorReader.accept()
from crashing when given a dependency
with no type or token.
Annotations may now have compound names (for example @foo.bar
).
It is now an error to use @deferred
on a <template>
tag or combined with
a structural (i.e. *ngIf
) directive.
Ignores right-trailing spaces when parsing micro expression let-assignments.
When parsing a failed micro expression (i.e. *ngFor
), avoids a type error.
vellip
is now a recognized char.
Whitespace inside preformatted text (<pre>
tags) is now always preserved.
Welcome to AngularDart v5.0.0, with full support for Dart 2. Please note that this release is not compatible with older versions of Dart 1.XX. Additionally:
More details of changes to Dart 2 for web users are available on our webiste.
Thanks, and enjoy AngularDart!
Dependency injection was enhanced greatly for 5.0.0, primarily around using proper types (for Dart 2), and paths to enable much smaller code size (for everyone).
Provider
(and provide
) are soft deprecated, and in their place are
four new classes with more precise type signatures. Additionally, Provider
now supports an optional type argument <T>
, making it Provider<T>
.
ValueProvider(Type, T)
and ValueProvider.forToken(OpaqueToken<T>, T)
instead of Provider(typeOrToken, useValue: ...)
.
FactoryProvider(Type, T)
and FactoryProvider.forToken(OpaqueToken<T>, T)
instead of Provider(typeOrToken, useFactory: ...)
.
ClassProvider(Type, useClass: T)
and
ClassProvider.forToken(OpaqueToken<T>, useClass: T)
instead of
Provider(typeOrToken, useClass: ...)
or an implicit Type
.
ExistingProvider(Type, T)
and
ExistingProvider.forToken(OpaqueToken<T>, T)
instead of
Provider(typeOrToken, useExisting: ...)
.
OpaqueToken
is now much more useful. Previously, it could be used to
define a custom, non-Type
to refer to something to be injected; commonly
instead of types like String
. For example, you might use an OpaqueToken
to refer to the a URL to download a file from:
const downloadUrl = OpaqueToken('downloadUrl');
@Component(
providers: [
Provider(downloadUrl, useValue: 'https://a-site.com/file.zip'),
],
)
class Example {
Example(@Inject(downloadUrl) String url) {
// url == 'https://a-site.com/file.zip'
}
}
First, OpaqueToken
adds an optional type argument, making
OpaqueToken<T>
. The type argument, T
, should be used to refer to the
Type
of the object this token should be bound to:
const downloadUrl = OpaqueToken<String>('downloadUrl');
Coupled with the new named Provider
classes and their .forToken
named
constructor (see below), you now also have a way to specify the type of
providers using type inference:
@Component(
providers: [
// This is now a Provider<String>.
ValueProvider.forToken(downloadUrl, 'https://a-site.com/file.zip'),
],
)
Second, MultiToken<T>
has been added, and it extends
OpaqueToken<List<T>>
. This is an idiomatic replacement for the now
deprecated multi: true
argument to the Provider
constructor:
const usPresidents = MultiToken<String>('usPresidents');
@Component(
providers: [
ValueProvider.forToken(usPresidents, 'George'),
ValueProvider.forToken(usPresidents, 'Abe'),
],
)
class Example {
Example(@Inject(usPresidents) List<String> names) {
// names == ['George', 'Abe']
}
}
Third, we heard feedback that the String
-based name of tokens was
insufficient for larger teams because the names could collide. Imagine 2
different tokens being registered with a name of 'importantThing'
! It is
now possible (but optional) to extend
either OpaqueToken
or MultiToken
to create scoped custom token names:
class DownloadUrl extends OpaqueToken<String> {
const DownloadUrl();
}
class UsPresidents extends MultiToken<String> {
const UsPresidents();
}
class Example {
providers: const [
ValueProvider.forToken(DownloadUrl(), 'https://a-site.com/file.zip'),
ValueProvider.forToken(UsPresidents(), 'George'),
ValueProvider.forToken(UsPresidents(), 'Abe'),
],
}
Fourth, and finally, we'd like to repurpose @Inject
in the future, and let
you write less to inject tokens. So, OpaqueToken
and MultiToken
instances may now be used directly as annotations:
class Example {
Example(@DownloadUrl() String url, @UsPresidents() List<String> names) {
// url == 'https://a-site.com/file.zip'
// names == ['George', 'Abe']
}
}
InjectorFactory
, a function type definition of Injector Function([Injector parent])
, was added and started to be used across the
framework. It normally indicates the ability to create a new Injector
instance with an optional parent.
A new annotation, @GenerateInjector
, was added. It is now posibble to
generate, at compile-time, a standalone InjectorFactory
method for
providers, without explicitly wrapping in an @Component
:
// example.dart
import 'example.template.dart' as ng;
@GenerateInjector([
ClassProvider(HelloService),
])
final InjectorFactory rootInjector = ng.rootInjector$Injector;
Module
has been added as a new, more-typed way to encapsulate a collection
of Provider
instances. This is an optional feature to use instead of
nested const
lists to represent shared providers. For example:
const httpModule = [ /* Other providers and/or modules. */ ];
const commonModule = [
httpModule,
ClassProvider(AuthService, useClass: OAuthService),
FactoryProvider.forToken(xsrfToken, useFactory: readXsrfToken),
];
... you can represent this with the new typed Module
syntax:
const httpModule = Module( /* ... Configuration ... */);
const commonModule = Module(
include: [httpModule],
provide: [
ClassProvider(AuthService, useClass: OAuthService),
FactoryProvider.forToken(xsrfToken, useFactory: readXsrfToken),
],
);
The advantages here are numerous:
Less ambiguity around ordering of providers. Engineers would tend to try
and sort providers alphabetically, would of course, would lead to
problems. Module
specifically outlines that order is significant,
and that include
is processed before provide
.
Module
rejects using a Type
implicitly as a ClassProvider
. This
removes additional ambiguity around supporting List<dynamic>
, and
while more verbose, should lead to more correct use.
Module
tends to be more understandable by users of other dependency
injection systems such as Guice or Dagger, and reads better than a
const
List
(which is a very Dart-only idiom).
NOTE: It is also possible to use Module
in @GenerateInjector
:
@GenerateInjector.fromModules([
commonModule,
])
final InjectorFactory exampleFromModule = ng.exampleFromModule$Injector;
NOTE: It is also possible to use Module
in ReflectiveInjector
:
// Using ReflectiveInjector is strongly not recommended for new code
// due to adverse effects on code-size and runtime performance.
final injector = ReflectiveInjector.resolveAndCreate([
commonModule,
]);
OpaqueToken
no longer overrides operator==
or hashCode
. In practice
this should have no effect for most programs, but it does mean that
effectively that only const
instances of OpaqueToken
(or MultiToken
)
are valid.
It is no longer valid to provide a token type of anything other than Type
or an OpaqueToken
(or MultiToken
). In the past anything from aribtrary
literals (such as a string - 'iAmAToken'
) or a custom const
instance of
a class were supported.
For defining whether a component or directive should provide itself for
injection, Visibility.none
has been renamed Visibility.local
to make it
more clear that it is accessable locally (within providers
for example).
Classes annotated with @Component
or @Directive
are no longer treated
like services annotated with @Injectable
, and not accessible (by default)
to ReflectiveInjector
. @Injectable
can always be added to these classes
in order to return to the old behavior.
Fixed a bug where calling get
on an Injector
injected in the context of
an @Component
or @Directive
-annotated class and passing a second
argument always returned null
(instead of that second argument) if the
token was not found.
Setting @Component(visibility: Visibility.none
) no longer applies to
providers
, if any. Note that Visibility.none
was always renamed
Visibility.local
in breaking changes above.
Fixed a bug where Provider(SomeType)
was not parsed correctly as an
implicit use of Provider(SomeType, useClass: SomeType
).
Fixed a bug where <ReflectiveInjector>.get(X)
would throw with a message
of no provider found for X, even when the acutal cause was a missing
downstream dependency Y
. We now emit the correct message.
Some injection failures will display the chain of dependencies that were
attempted before a token was not found ('X -> Y -> Z'
) in development
mode. We are working on making sure this better error message shows up
always but it is likely to slip until after the v5 release.
It is no longer a build warning to have an @Injectable
-annotated service
with more than one constructor. This was originally meant to keep injection
from being too ambiguous, but there are understood patterns now (first
constructor), and there is no alternative present yet. We may re-add this as
a warning if there ends up being a mechanism to pick a constructor in the
future.
It is no longer a build warning to have @Injectable
-annotated services
with named constructor parameters. While they are still not supported for
injected, they were always successfully ignored in the past, and showing a
warning to the user on every build served no purpose.
If a private class is annotated with @Injectable()
the compiler fails. In
practice this caused a compilation error later in DDC/Dart2JS, but now the
AngularDart compiler will not emit invalid code.
Removed spurious/incorrect warnings about classes that are used as
interfaces needing @Injectable
(or needing to be non-abstract), which are
wrong and confusing.
The compiler behind initReflector()
has changed implementations and now
uses fully-scoped import statements instead of trying to figure out the
original scope (including import prefixes) of your source code. This was not
intended to be a breaking change.
NgTemplateOutlet
added ngTemplateOutletContext
for setting local
variables in an embedded view. These variables are assignable to template
input variables declared using let
, which can be bound within the
template. See the NgTemplateOutlet
documentation for examples.
Added a lifecycle event AfterChanges
, which is similar to OnChanges
, but
with a much lower performance cost - it does not take any parameters and is
suitable when you have multiple fields and you want to be notified when any
of them change:
class Comp implements AfterChanges {
@Input()
String field1;
@Input()
String field2;
@override
void ngAfterChanges() {
print('Field1: $field1, Field2: $field2');
}
}
It is possible to directly request Element
or HtmlElement
types from
content or view children instead of ElementRef
(which is deprecated). For
example:
@Component(
selector: 'uses-element',
template: '<div #div>1</div>'
)
class UsesElement {
@ViewChild('div')
// Could also be HtmlElement.
Element div;
}
Additionally, List<Element>
and List<HtmlElement>
for @ViewChildren
and @ContentChildren
no longer require read: Element
, and the type is
correctly inferred the same as a single child is.
Static properties and methods of a component may now be referenced without a receiver in the component's own template. For example:
Before: ExampleComponent
as receiver is necessary.
@Component(
selector: 'example',
template: '<h1>{{ExampleComponent.title}}</h1>',
)
class ExampleComponent {
static String title;
}
After: No receiver is necessary.
@Component(
selector: 'example',
template: '<h1>{{title}}</h1>',
)
class ExampleComponent {
static String title;
}
@HostListener()
can now automatically infer the const ['$event']
parameter when it is omitted but the bound method has a single argument:
class Comp {
@HostListener('click')
void onClick(MouseEvent e) {}
}
Added <ng-container>
, an element for logical grouping that has no effect
on layout. This enables use of the *-syntax for structural directives,
without requiring the cost an HTML element.
Before
<ul>
<template ngFor let-user [ngForOf]="users">
<li *ngIf="user.visible">{{user.name}}</li>
</template>
</ul>
After
<ul>
<ng-container *ngFor="let user of users">
<li *ngIf="user.visible">{{user.name}}</li>
</ng-container>
</ul>
In dev mode only, an attribute named from
is now added to each <style>
tag whose value identifies the source file URL and name of the component
from which the styles originate.
Support for the suffix .if
for attribute bindings, both in a template and
in a @HostBinding()
. Accepts an expression of type bool
, and adds an
attribute if true
, and removes it if false
and closes
https://github.com/dart-lang/angular/issues/1058:
<!-- These are identical -->
<button [attr.disabled]="isDisabled ? '' : null"></button>
<button [attr.disabled.if]="isDisabled"></button>
Add support for tear-offs in event handlers in the templates.
BEFORE: <button (onClick)="clickHandler($event)">
AFTER: <button (onClick)="clickHandler">
It is now possible to annotate parts of a template with
@preserveWhitespace
instead of opting into preserving whitespace for the
entire template. [Closes #1295][#1295]:
<div>
<div class="whitespace-sensitive" @preserveWhitespace>
Hello
World!
</div>
</div>
A warning is produced if the compiler removes any elements (such as
<script>
) from your template. This may become an error in future versions
of AngularDart.
A warning is produced if the selector provided to a query (such as
@ViewChildren(...)
) is invalid and will not produce any elements at
runtime. NOTE: any unknown type is just ignored (it may still be
invalid), and any invalid value throws a build error. For example:
class A {
// Might not be valid, but no warning.
@ViewChildren(SomeArbitraryType)
List<SomeArbitraryType> someTypes;
// We throw a build error.
@ViewChildren(1234)
List thisDoesNotWork;
}
Added support for named arguments in function calls in templates:
<span>Hello {{getName(includeExclamationPoint: true)}}</span>
NOTE: Because of the collision of syntax for both named arguments and
pipes, any pipes used as the value of a named argument need to be wrapped
in parentheses: func(namedArg: (pipeName | pipeVar:pipeVarValue))
.
We now have a new, more stricter template parser, which strictly requires
double quotes ("..."
) versus single quotes, and in general enforces a
stricter HTML-like syntax. It does produce better error messages than
before.
We removed support for ngNonBindable
in the new template syntax.
The fields inputs:
, outputs:
, and host:
have been removed from
@Directive(...)
and @Component(...
). It is expected to use the member
annotations (@Input()
, @Output()
, @HostBinding()
, @HostListener()
)
instead.
The default for @Component(preserveWhitespace: ...)
is now true
. Many
improvements were put into the whitespace optimziation in order to make the
results easier to understand and work around.
<AsyncPipe>.transform
no longer returns the (now removed) WrappedValue
when a transformed result changes, and relies on regular change detection.
Pipes no longer support private types in their transform
method signature.
This method's type is now used to generate a type annotation in the
generated code, which can't import private types from another library.
Using @deferred
no longer supports the legacy bootstrap processes. You
must use runApp
(or runAppAsync
) to bootstrap the application without
relying on initReflector()
.
<ComponentRef>.componentType
always throws UnsupportedError
, and will be
removed in a later minor release. This removes our last invocation of
.runtimeType
, which has potentially severe code-size implications for some
apps.
QueryList
for @ViewChildren
and @ContentChildren
has been removed, in
favor of just a plain List
that is replaced with a new instance when the
children change (instead of requiring a custom collection and listener):
class Comp {
@ViewChildren(ChildComponent)
set viewChildren(List<ChildComponent> viewChildren) {
// ...
}
// Can also be a simple field.
@ContentChildren(ChildComponent)
List<ChildComponent> contentChildren;
}
EventEmitter
was removed in favor using Stream
and StreamController
.
COMMON_DIRECTIVES
was renamed commonDirectives
.
CORE_DIRECTIVES
was renamed coreDirectives
.
COMMON_PIPES
was renamed commonPipes
.
Private types can't be used in template collection literals bound to an input. This is a consequence of fixing a cast warning that is soon to be an error caused by the code generated for change detecting collection literals in templates. See https://github.com/dart-lang/angular/issues/844 for more information.
SafeInnerHtmlDirective
is no longer injectable.
The following types were never intended for external use and are no longer
exported by package:angular/security.dart
:
SafeHtmlImpl
SafeScriptImpl
SafeStyleImpl
SafeResourceUrlImpl
SafeUrlImpl
SafeValueImpl
To mark a value as safe, users should inject DomSanitizationService
and
invoke the corresponding bypassSecurityTrust*()
method, instead of
constructing these types directly.
ComponentResolver
was removed, and SlowComponentLoader
was deprecated.
Methods in lifecycle hooks have void
return type. This is breaking change
if the override doesn't specify return type and uses return
without any
value. To fix add a void
or Future<void>
return type to the override:
class MyComp implements OnInit {
@override
void ngOnInit() {
// ...
}
}
Removed the rarely used template
attribute syntax. Uses can be replaced
with either the *
micro-syntax, or a <template>
element.
Before
<div template="ngFor let item of items; trackBy: trackById; let i=index">
{{i}}: {{item}}
</div>
After
<!-- * micro-syntax -->
<div *ngFor="let item of items; trackBy: trackById; let i=index">
{{i}}: {{item}}
</div>
<!-- <template> element -->
<template
ngFor
let-item
[ngForOf]="items"
[ngForTrackBy]="trackById"
let-i="index">
<div>
{{i}}: {{item}}
</div>
</template>
It is now a compile error to implement both the DoCheck
and OnChanges
lifecycle interfaces. DoCheck
will never fill in values for the Map
in
OnChanges
, so this compile-error helps avoid bugs and directs the user to
use DoCheck
and AfterChanges
instead.
Using a suffix/unit for the [attr.name.*]
syntax other than the newly
introduced [attr.name.if]
is now a compile-error. These binding suffixes
were silently ignored (users were likely confused with [style.name.px]
,
which is supported).
Fixed a bug where an @deferred
components were still being linked to in
initReflector()
.
Fixed a bug where errors thrown in event listeners were sometimes uncaught
by the framework and never forwarded to the ExceptionHandler
.
Fixed a bug where DatePipe
didn't format millisecondsSinceEpoch
in the
local time zone (consistent with how it formats DateTime
).
Testability now includes ComponentState
updates. Due to prior use of
animationFrame
callback, NgTestBed
was not able to detect a stable
state.
String literals bound in templates now support Unicode escapes of the form
\u{?-??????}
. This enables support for Unicode supplementary planes, which
includes emojis!
Inheriting from a class that defines a @HostBinding()
on a static member
no longer causes the web compiler (Dartdevc or Dart2JS) to fail. We
previously inherited these bindings and generated invalid Dart code. Given
that static members are not inherited in the Dart language, it made sense to
give a similar treatment to these annotations. Instance-level members are
still inherited:
class Base {
@HostBinding('title')
static const hostTitle = 'Hello';
@HostBinding('class')
final hostClass = 'fancy';
}
// Will have DOM of <fancy-button class="fancy"> but *not* title="Hello".
@Component(
selector: 'fancy-button',
template: '...',
)
class FancyButton extends Base {}
Fixed a bug where a recursive type signature on a component or directive
would cause a stack overflow. We don't support generic type arguments yet
(the reified type is always dynamic
), but the compiler no longer crashes.
Fails the build immediately if an element in a component's pipes
list is
unresolved.
Fixed a bug where [attr.name.if]
did not work on a static @HostBinding
.
Implicit static tear-offs and field invocations are now supported:
@Component(
selector: 'example',
template: '''
<!-- Invoking an implicit static field. -->
<div>{{field()}}</div>
<!-- Binding an implicit static tear-off. -->
<div [invoke]="tearOff"></div>
''',
)
class ExampleComponent {
static String Function() field = () => 'Hello world';
static String tearOff() => 'Hello world';
}
Types bound from generics are now properly resolved in a component when inheriting from a class with a generic type. For example, the following used to be untyped in the generated code:
class Container<T> {
@Input()
T value;
}
class StringContainerComponent implements Container<String> {}
Both ComponentFactory
and ComponentRef
now have a generic type parameter
<T>
, which is properly reified where T
is the type of the component
class.
The $implicit
(iterable) value in *ngFor
is now properly typed whenever
possible. It was previously always typed as dynamic
, which caused dynamic
lookups/calls at runtime, and hid compilation errors.
The type of <EmbeddedViewRef>.rootNodes
and <ViewRefImpl>.rootNodes
has
been tightened from List<dynamic>
to List<Node>
(where Node
is from
dart:html
).
A combination of compile errors and warnings are produced when it seem that
template
, templateUrl
, style
, or styleUrls
are either incorrect or
missing when required.
The compiler now reports an actionable error when an annotation is used on a private class member. We also report errors when various annotations are used improperly (but not in all cases yet).
The compiler optimizes *ngIf
usages where the content is pure HTML.
The view compiler is able to tell when exports: [ ... ]
in an @Component
are static reads and are immutable (such as String
). This allows us to
optimize the generated code.
Some changes to how template files import 'dart:core' to accommodate analyzer changes that make 'dynamic' a member of 'dart:core'. These should not have user-visible effects.
Fixed a bug where many queries (@ViewChildren()
and the like) generated
additional runtime casts in production mode. Now in Dart2JS with
--omit-implicit-checks
the casts are removed.
Emits more optimized code when there are multiple data bindings in a row
that are checked only once (such as final
strings). Previously we
generated redundant code.
Fixed an optimization issue when @ViewChild()
or @ContentChild()
was
used on a nested element (i.e. inside a <template>
). The code that was
produced accidentally created two queries instead of one.
Improved error message for binding incorrectly typed event handlers. This moves the check from event dispatch time, to event subscription time, meaning it may be a breaking change if you had an incorrectly typed event handler bound to a output that never fired.
The process for starting your AngularDart application changed significantly:
runApp
function. Instead of starting your application by passing the Type
of
an @Component
-annotated class
, you now pass a ComponentFactory
,
the generated code for a component:import 'package:angular/angular.dart';
import 'main.template.dart' as ng;
void main() {
runApp(ng.RootComponentNgFactory);
}
@Component(
selector: 'root',
template: 'Hello World',
)
class RootComponent {}
To provide top-level services, use the createInjector
parameter, and pass
a generated InjectorFactory
for a top-level annotated with
@GenerateInjector
:
import 'package:angular/angular.dart';
import 'main.template.dart' as ng;
void main() {
runApp(ng.RootComponentNgFactory, createInjector: rootInjector);
}
class HelloService {
void sayHello() => print('Hello!');
}
@GenerateInjector([
ClassProvider(HelloService),
])
final InjectorFactory rootInjector = ng.rootInjector$Injector;
A major difference between runApp
and previous bootstrapping code is the
lack of the initReflector()
method or call, which is no longer needed.
That means using runApp
disables the use of SlowComponentLoader
and
ReflectiveInjector
, two APIs that require this extra runtime metadata.
To enable use of these classes for migration purposes, use runAppLegacy
:
import 'package:angular/angular.dart';
// ignore: uri_has_not_been_generated
import 'main.template.dart' as ng;
void main() {
runAppLegacy(
RootComponent,
createInjectorFromProviders: [
ClassProvider(HelloService),
],
initReflector: ng.initReflector,
);
}
NOTE: initReflector
and runAppLegacy
disables tree-shaking on any
class annotated with @Component
or @Injectable
. We strongly recommend
migrating to the runApp
pattern.
The top-level function bootstrap
was deleted. This function always threw a
runtime exception since 5.0.0-alpha+5
, and was a relic of when a code
transformer rewrote it automatically as bootstrapStatic
.
Dropped support for @AngularEntrypoint
and rewriting entrypoints to
automatically use initReflector()
and bootstrapStatic
. This is no longer
supported in the new build system.
RenderComponentType
is no longer part of the public API.
<ApplicationRef>
.componentFactories
, .componentTypes
, .zone
, and
.registerBootstrapListener
were removed; these were used internally by the
legacy router and not intended to be part of the public API.
PLATFORM_INITIALIZERS
was removed.
APP_INITIALIZER
was removed. A similar functionality can be accomplished
using the runAppAsync
or runAppLegacyAsync
functions with the
beforeComponentCreated
callback.
PlatformRef
and PlatformRefImpl
were removed.
package:angular/meta.dart
, a series of utilities for additional
static analysis checks and/or functions to retain semantics for migration
purposes, starting with castCallback1ForDirective
and
castCallback2ForDirective
. These methods are only intended to be used as
stop-gaps for the lack of generic support in AngularDart directives and
components.<NgZone>.onStable
has been renamed to onTurnDone
.
<NgZone>.onUnstable
has been renamed to onTurnStart
.
The context
parameter was removed from <TemplateRef>.createEmbeddedView
.
The following relatively unused fields and functions were removed:
APPLICATION_COMMON_PROVIDERS
BROWSER_APP_COMMON_PROVIDERS
BROWSER_APP_PROVIDERS
PACKAGE_ROOT_URL
ErrorHandlingFn
UrlResolver
WrappedTimer
WrappedValue
ZeroArgFunction
appIdRandomProviderFactory
coreBootstrap
coreLoadAndBootstrap
createNgZone
createPlatform
disposePlatform
getPlatform
Running within the NgZone
will no longer cause addtional turns to occur
within it's parent's zone. <NgZone>.run()
will now run inside the parent
zone's run()
function as opposed to the other way around.
The compilation mode --debug
(sparingly used externally) is now no longer
supported. Some flags and code paths in the compiler still check/support it
but it will be removed entirely by the final release and should no longer be
used. We will rely on assertion-based tree-shaking (from Dart2JS
) going
forward to emit debug-only conditional code.
<ExceptionHandler>.call
with a null
exception.Add AbstractControlGroup and AbstractNgForm to allow infrastructure to create their own form systems that can be backed by types such as a proto, or have different control group logic. Allow NgFormModel and NgControlGroup to work with abstract group.
reset
method added to AbstractControl
and AbstractControlDirective
.
RequiredValidator
now has a required
input. This allows the required
property to be toggled at runtime. Previously, this could only be set
statically at compile time.
Control.invalid
getter added.
Control.markAsPristine
added. This will clear the dirty
property.
Add ngDisabled
input to all Control directives.
Add MemorizedForm
directive. This is a form that will not remove controls
if the control is taken out of the view, for example with a [NgIf].
Add disabled
state to AbstractControl
models. Note: This is not yet
supported in the template-driven directives.
Add markAsUntouched
method to AbstractControl
.
Add a type annotation, T
, to AbstractControl
, which is tied to the type
of value
.
ControlGroup
now extends AbstractControl<Map<String, dynamic>>
.
ControlArray
now extends AbstractControl<List>
.
Use value from AbstractControl for valueChanges event instead of internal variable. Allows code to more easily subclass AbstractControl.
Remove deprecated NG_VALUE_ACCESSOR
token. Use ngValueAccessor
instead.
Abstract updateValue
method added to AbstractControl
. All subclasses of
AbstractControl
will need to implement this method.
NgControlName
will no longer initialize with null
if a value is
specified by 'ngModel'.
The touched
property of Control
s is now propagated to parents /
children.
NgControlGroup
can no longer be injected directly. It can still be
injected as a ControlContainer
.
NgControlName
and NgFormControl
can no longer be injected directly. They
can still be injected as a NgControl
.
The following directives are no longer injectable:
CheckboxControlValueAccessor
DefaultValueAccnessor
MaxLengthValidator
MinLengthValidator
NgControlStatus
NgSelectOption
NumberValueAccessor
PatternValidator
RadioControlValueAccessor
RequiredValidator
Add ControlValueAccessor.onDisabledChanged()
method. All implementations
of ControlValueAccessor
need to add this method.
Remove include
and exclude
methods from ControlGroup
. These can be
replaced with calls to markAsEnabled
and markAsDisabled
instead.
Before: controlGroup.include('foo');
After: controlGroup.controls['foo'].markAsEnabled();
CheckboxControlValueAccessor
now implements ControlValueAccessor<bool>
and RadioControlValueAccessor
now implements
ControlValueAccessor<RadioButtonState>
. Previously, they were both
ControlValueAccessor<dynamic>
.
Remove optionals
param from ControlGroup
constructor. This has been
replaced by disabled
state for all Controls
. See
https://github.com/dart-lang/angular/issues/1037 for more details.
AbstractControl.find
now only accepts a String. To supply a list, use
AbstractControl.findPath
instead. Also, for find
or findPath
,
ControlArray
index is now calling int.parse
instead of expecting a raw
number.
Properly typed the generic parameter on subclasses of
AbstractControlDirective
. Now, NgControl.control
will return a
Control
, and ControlContainer.control
will return a ControlGroup
.
There may be some unnecessary casts that can now be cleaned up.
FormBuilder
instance methods group
, control
, and array
have been
removed. For FormBuilder.control
, just call new Control(value, validator)
directly. For FormBuilder.group
and FormBuilder.array
, use
the static methods FormBuilder.controlGroup
and
FormBuilder.controlArray
, respectively. FormBuilder
is no longer
Injectable
.
Changed type of AbstractControl.statusChanges
from Stream<dynamic>
to
Stream<String>
. This now matches the type for AbstractControl.status
,
which as always been a String
.
Allow expressions for maxlength/minlength validators. Breaking change does
not support string values for maxlength/minlength anymore. minlength="12"
now should be written [minlength]="12"
Add a not selector to ngForm for memorizedForm since memorized_form is now in angular_forms. This fixes the DIRECTIVE_EXPORTED_BY_AMBIGIOUS error when using: <form #form="ngForm" memorizedForm>
Don't throw a null pointer exception in NgFormModel if a directives asks for a Control value before the form is initialized.
Supported FutureOr<void>
for beforeChangeDetection
.
NgZoneStabilizer
waits for the longest pending timer during update()
.
Added isStable
API to NgTestStabilizer
.
Made NgTestStabilizerFactory
public.
Removed throwsInAngular
. Use throwsA
.
Removed NgTestFixture#query/queryAll
, as debug-mode is being turned down.
Run DelegatingNgTestStabilizer
stabilizers one by one instead of run all
at once. update()
for each stabilizers will be run at least once. After
that, it will only be run if the current stabilizer is not stable.
pub run angular_test
was entirely removed. Similar functionality is
supported out of the box by build_runner
:
$ pub run build_runner test
Removed built-in support for package:pageloader
. The current version of
pageloader
relies on dart:mirrors
, which is being removed from the web
compilers (dart2js, dartdevc). There is a new version of pageloader
in
development that uses code generation. We'll consider re-adding support once
available or through another package (i.e. angular_pageloader
or similar).
Adding stabilizers to NgTestBed
now takes a factory function of type
NgTestStabilizer Function(Injector)
, which is aliased as
NgTestStabilizerFactory
. This allows using NgTestBed
without any dynamic
reflective factories (i.e. initReflector()
) and doesn't have impact to
most users.
Deleted an unnecessary hostElement.append(componentRef.location)
.
Fixed a bug where a WillNeverStabilizeError
was thrown whenever there was
a non-zero length Timer
being executed. This was due to a bug in how the
NgStabilizer
was executing - constantly calling the update
function
instead of calling it once and waiting for stabilization.
Fixed a bug where stabilizers are considered stable even when some of them are not.
Fixed a bug where _createDynamic
does not preserve rootInjector
.
Added NgTestBed.forComponent
, which takes a ComponentFactory<T>
, and
optionally an InjectorFactory
. This allows writing tests entirely free of
any invocations of initReflector()
.
Added TypedElement
to represent a statically parsed Typed
.
TypedReader.parse()
now returns a TypedElement
.
Added $Typed
, a TypeChecker
for Typed
.
Added TypedReader
for parsing generic directive types.
Added support for void
and Null
types to appear in tokens.
Added DirectiveVisitor
, and removed $HostBinding
and $HostListener
.
Added ModuleReader.extractProviderObjects
to use in the view compiler.
Added logFine
as a new top-level API.
Added an internal cli.dart
library. See lib/cli.dart
for details.
Added SplitDartEmitter
for internal use.
Added $QueryList
as a TypeChecker
.
Expose the $Provider
TypeChecker
.
Added typeArgumentOf
helper method.
Added support for recognizing the MultiToken
type.
CompilerFlags
now supports as a fast_boot
argument; default is true
.
ReflectorEmitter
now takes an optional deferredModules{Source}
.
Started adding experimental support for a new Module
syntax.
CompilerFlags
no longer parses and supports the 'debug'
option and
genDebugInfo
is always false
, and is deprecated pending removal in a
future version.
Removes unused APIs of ComponentReader
.
TokenReader
no longer supports arbitrary const objects or literals.
Removed use_new_template_parser
flag. The old parser was removed.
Removed $QueryList
.
Added canRead
to NgAssetReader
.
Moved CompilerFlags
and Profile
to cli.dart
.
linkToReference
now requires a second parameter, a LibraryReader
, and
treats private types (i.e. prefixed with _
) as dynamic
as the compiler
cannot point to them.
ReflectableEmitter
has been completely replaced with a new implementation.
Removed all references and use of determining a "prefix" of a type. This was
no longer used once ReflectableEmitter
was re-written.
Removed a number of internal flags that were no longer strictly required.
ModuleReader.deduplicateProviders
now returns a List
not a Set
, and
providers that are multi are not removed, as it is a feature of the DI
system to have multiple of them with the same token.
Add the TypeLink
class, and replace uses of Uri
.
@Component
and @Directive
annotated classes are no longer @Injectable
.
In practice this means they can no loger be provided as an implicit const Provider(FooComponent)
without either manually adding @Injectable
or
refactoring your code. We found this didn't really affect users, and most
uses of components and directives in these lists were accidental.
Fixed a bug where the compiler crashed after resolving a bound type failed.
Misspelled or otherwise erroneous annotations on classes now produce a more understandable error message, including the element that was annotated and the annotation that was not resolved.
Fix a bug where throwFailure
hit an NPE without a stack trace.
linkTypeOf
correctly resolves bound types (i.e. <T>
) in most cases, and
can fallback to dynamic
otherwise.
Removed all remaining (invalid) references to package:barback
.
Prevented a RangeError
that occurred when an invalid import lacked an
extension.
ReflectorEmitter
now supports MultiToken
and generic-typed tokens, with
some known limitations. See https://github.com/dart-lang/angular/issues/782.
Fix a bug in the outliner that did not the correct output extension.
dart 2.0 stable
.package:tuple
.HashLocationStrategy
no longer drops query parameters (before the #) when
pushing or replacing an empty URL.angular 5.0.0-beta+3
.Deleted an unnecessary hostElement.append(componentRef.location)
.
Supported FutureOr<void>
for beforeChangeDetection
.
TypedElement
to represent a statically parsed Typed
.TypedReader.parse()
now returns a TypedElement
.-dev.68
.We accidentally missed 5.0.0-beta+1
, but it was available on pub.
Added support for named arguments in function calls in templates:
<span>Hello {{getName(includeExclamationPoint: true)}}</span>
NOTE: Because of the collision of syntax for both named arguments and
pipes, any pipes used as the value of a named argument need to be wrapped
in parentheses: func(namedArg: (pipeName | pipeVar:pipeVarValue))
.
Changed the behavior of warnings around @ViewChildren(...)
. It was more
difficult than originally thought to warn on incorrect selector usage due to
the semantics of components and dependency injection. In many cases false
positives were flagged. Now, any unknown type is just ignored (it may still
be invalid), and any invalid value throws a build error. For example:
class A {
// Might not be valid, but we no longer warn.
@ViewChildren(SomeArbitraryType)
List<SomeArbitraryType> someTypes;
// We throw a build error.
@ViewChildren(1234)
List thisDoesNotWork;
}
Implicit static tear-offs and field invocations are now supported:
@Component(
selector: 'example',
template: '''
<!-- Invoking an implicit static field. -->
<div>{{field()}}</div>
<!-- Binding an implicit static tear-off. -->
<div [invoke]="tearOff"></div>
''',
)
class ExampleComponent {
static String Function() field = () => 'Hello world';
static String tearOff() => 'Hello world';
}
A warning is produced if the compiler removes any elements
(such as <script>
) from your template. This may become an error in future
versions of AngularDart. Closes #1280.
A warning is produced if the selector provided to a query (such as
@ViewChildren(...)
) is invalid and will not produce any elements at
runtime. This may become an error in future versions of AngularDart.
Closes #1220.
It is now possible to annotate parts of a template with
@preserveWhitespace
instead of opting into preserving whitespace for the
entire template. Closes #1295:
<div>
<div class="whitespace-sensitive" @preserveWhitespace>
Hello
World!
</div>
</div>
Added package:angular/meta.dart
, a series of utilities for additional
static analysis checks and/or functions to retain semantics for migration
purposes, starting with castCallback1ForDirective
and
castCallback2ForDirective
. These methods are only intended to be used
as stop-gaps for the lack of generic support in AngularDart directives and
components. Closes #1489.
Fails the build immediately if an element in a component's pipes
list is
unresolved.
Support inherited method tear-offs in event listeners. Previously, we only considered methods in the Component class itself. Closes #506.
Fixed a bug where [attr.name.if]
did not work on a static @HostBinding
.
Closes #1484.
Fixed a bug where many queries (@ViewChildren()
and the like) generated
additional runtime casts in production mode. Now in Dart2JS with
--omit-implicit-checks
the casts are removed.
Emits more optimized code when there are multiple data bindings in a row
that are checked only once (such as final
strings). Previously we
generated redundant code.
Fixed an optimization issue when @ViewChild()
or @ContentChild()
was
used on a nested element (i.e. inside a <template>
). The code that was
produced accidentally created two queries instead of one.
Closes #1455.
CloseElementAst
complement into ContainerAst
.<template>
.@preserveWhitespace
.$Typed
, a TypeChecker
for Typed
.TypeReader
for parsing generic directive types.sdk: ">=2.0.0-dev.64.2 <2.0.0"
.RouteDefinition.redirect
now supports forwarding route parameters.SCREAMING_CAPS
consts from dart:*
.