Skip to content

Commit 55308f2

Browse files
AndrewKushnirthePunderWoman
authored andcommitted
feat(animations): add provideAnimations() and provideNoopAnimations() functions (#46793)
This commit adds the following functions to the public API: - provideAnimations - provideNoopAnimations The goal of those functions is to return a set of providers required to setup animations in an application. The functions are useful when the `bootstrapApplication` function is used to bootstrap an app. The functions allow to avoid the need to import `BrowserAnimationsModule` and `BrowserNoopAnimationsModule` NgModules. PR Close #46793
1 parent c0ca3fc commit 55308f2

File tree

5 files changed

+130
-4
lines changed

5 files changed

+130
-4
lines changed

goldens/public-api/platform-browser/animations/index.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { ANIMATION_MODULE_TYPE } from '@angular/core';
88
import * as i0 from '@angular/core';
99
import * as i1 from '@angular/platform-browser';
1010
import { ModuleWithProviders } from '@angular/core';
11+
import { Provider } from '@angular/core';
1112

1213
export { ANIMATION_MODULE_TYPE }
1314

@@ -37,6 +38,12 @@ export class NoopAnimationsModule {
3738
static ɵmod: i0.ɵɵNgModuleDeclaration<NoopAnimationsModule, never, never, [typeof i1.BrowserModule]>;
3839
}
3940

41+
// @public
42+
export function provideAnimations(): Provider[];
43+
44+
// @public
45+
export function provideNoopAnimations(): Provider[];
46+
4047
// (No @packageDocumentation comment for this package)
4148

4249
```

packages/platform-browser/animations/src/animations.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
* Entry point for all animation APIs of the animation browser package.
1313
*/
1414
export {ANIMATION_MODULE_TYPE} from '@angular/core';
15-
export {BrowserAnimationsModule, BrowserAnimationsModuleConfig, NoopAnimationsModule} from './module';
15+
export {BrowserAnimationsModule, BrowserAnimationsModuleConfig, NoopAnimationsModule, provideAnimations, provideNoopAnimations} from './module';
1616

1717
export * from './private_export';

packages/platform-browser/animations/src/module.ts

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import {ModuleWithProviders, NgModule} from '@angular/core';
8+
import {ModuleWithProviders, NgModule, Provider} from '@angular/core';
99
import {BrowserModule} from '@angular/platform-browser';
1010

1111
import {BROWSER_ANIMATIONS_PROVIDERS, BROWSER_NOOP_ANIMATIONS_PROVIDERS} from './providers';
@@ -58,6 +58,35 @@ export class BrowserAnimationsModule {
5858
}
5959
}
6060

61+
/**
62+
* Returns the set of [dependency-injection providers](guide/glossary#provider)
63+
* to enable animations in an application. See [animations guide](guide/animations)
64+
* to learn more about animations in Angular.
65+
*
66+
* @usageNotes
67+
*
68+
* The function is useful when you want to enable animations in an application
69+
* bootstrapped using the `bootstrapApplication` function. In this scenario there
70+
* is no need to import the `BrowserAnimationsModule` NgModule at all, just add
71+
* providers returned by this function to the `providers` list as show below.
72+
*
73+
* ```typescript
74+
* bootstrapApplication(RootComponent, {
75+
* providers: [
76+
* provideAnimations()
77+
* ]
78+
* });
79+
* ```
80+
*
81+
* @publicApi
82+
* @developerPreview
83+
*/
84+
export function provideAnimations(): Provider[] {
85+
// Return a copy to prevent changes to the original array in case any in-place
86+
// alterations are performed to the `provideAnimations` call results in app code.
87+
return [...BROWSER_ANIMATIONS_PROVIDERS];
88+
}
89+
6190
/**
6291
* A null player that must be imported to allow disabling of animations.
6392
* @publicApi
@@ -68,3 +97,31 @@ export class BrowserAnimationsModule {
6897
})
6998
export class NoopAnimationsModule {
7099
}
100+
101+
/**
102+
* Returns the set of [dependency-injection providers](guide/glossary#provider)
103+
* to disable animations in an application. See [animations guide](guide/animations)
104+
* to learn more about animations in Angular.
105+
*
106+
* @usageNotes
107+
*
108+
* The function is useful when you want to bootstrap an application using
109+
* the `bootstrapApplication` function, but you need to disable animations
110+
* (for example, when running tests).
111+
*
112+
* ```typescript
113+
* bootstrapApplication(RootComponent, {
114+
* providers: [
115+
* provideNoopAnimations()
116+
* ]
117+
* });
118+
* ```
119+
*
120+
* @publicApi
121+
* @developerPreview
122+
*/
123+
export function provideNoopAnimations(): Provider[] {
124+
// Return a copy to prevent changes to the original array in case any in-place
125+
// alterations are performed to the `provideNoopAnimations` call results in app code.
126+
return [...BROWSER_NOOP_ANIMATIONS_PROVIDERS];
127+
}

packages/platform-browser/animations/test/noop_animations_module_spec.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {animate, style, transition, trigger} from '@angular/animations';
99
import {ɵAnimationEngine} from '@angular/animations/browser';
1010
import {Component} from '@angular/core';
1111
import {TestBed} from '@angular/core/testing';
12-
import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations';
12+
import {BrowserAnimationsModule, NoopAnimationsModule, provideNoopAnimations} from '@angular/platform-browser/animations';
1313

1414
describe('NoopAnimationsModule', () => {
1515
beforeEach(() => {
@@ -28,6 +28,14 @@ describe('BrowserAnimationsModule with disableAnimations = true', () => {
2828
noopAnimationTests();
2929
});
3030

31+
describe('provideNoopAnimations()', () => {
32+
beforeEach(() => {
33+
TestBed.configureTestingModule({providers: [provideNoopAnimations()]});
34+
});
35+
36+
noopAnimationTests();
37+
});
38+
3139

3240
function noopAnimationTests() {
3341
it('should flush and fire callbacks when the zone becomes stable', (async) => {

packages/platform-browser/test/browser/bootstrap_spec.ts

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9+
import {animate, state, style, transition, trigger} from '@angular/animations';
910
import {DOCUMENT, isPlatformBrowser, ɵgetDOM as getDOM} from '@angular/common';
10-
import {APP_INITIALIZER, Compiler, Component, createPlatformFactory, CUSTOM_ELEMENTS_SCHEMA, Directive, ErrorHandler, Inject, InjectionToken, Injector, Input, LOCALE_ID, NgModule, NgModuleRef, OnDestroy, Pipe, PLATFORM_ID, PLATFORM_INITIALIZER, Provider, Sanitizer, StaticProvider, Testability, TestabilityRegistry, Type, VERSION} from '@angular/core';
11+
import {ANIMATION_MODULE_TYPE, APP_INITIALIZER, Compiler, Component, createPlatformFactory, CUSTOM_ELEMENTS_SCHEMA, Directive, ErrorHandler, Inject, inject as _inject, InjectionToken, Injector, Input, LOCALE_ID, NgModule, NgModuleRef, OnDestroy, Pipe, PLATFORM_ID, PLATFORM_INITIALIZER, Provider, Sanitizer, StaticProvider, Testability, TestabilityRegistry, Type, VERSION} from '@angular/core';
1112
import {ApplicationRef, destroyPlatform} from '@angular/core/src/application_ref';
1213
import {Console} from '@angular/core/src/console';
1314
import {ComponentRef} from '@angular/core/src/linker/component_factory';
1415
import {inject, TestBed} from '@angular/core/testing';
1516
import {Log} from '@angular/core/testing/src/testing_internal';
1617
import {BrowserModule} from '@angular/platform-browser';
1718
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
19+
import {provideAnimations, provideNoopAnimations} from '@angular/platform-browser/animations';
1820
import {expect} from '@angular/platform-browser/testing/src/matchers';
1921

2022
import {bootstrapApplication} from '../../src/browser';
@@ -314,6 +316,58 @@ function bootstrap(
314316
'make sure it has the `@Component` decorator.';
315317
expect(() => bootstrapApplication(NonAnnotatedClass)).toThrowError(msg);
316318
});
319+
320+
describe('with animations', () => {
321+
@Component({
322+
standalone: true,
323+
selector: 'hello-app',
324+
template: `
325+
<div
326+
@myAnimation
327+
(@myAnimation.start)="onStart($event)">Hello from AnimationCmp!</div>`,
328+
animations: [trigger(
329+
'myAnimation', [transition('void => *', [style({opacity: 1}), animate(5)])])],
330+
})
331+
class AnimationCmp {
332+
renderer = _inject(ANIMATION_MODULE_TYPE, {optional: true}) ?? 'not found';
333+
startEvent?: {};
334+
onStart(event: {}) {
335+
this.startEvent = event;
336+
}
337+
}
338+
339+
it('should enable animations when using provideAnimations()', async () => {
340+
const appRef = await bootstrapApplication(AnimationCmp, {
341+
providers: [provideAnimations()],
342+
});
343+
const cmp = appRef.components[0].instance;
344+
345+
// Wait until animation is completed.
346+
await new Promise(resolve => setTimeout(resolve, 10));
347+
348+
expect(cmp.renderer).toBe('BrowserAnimations');
349+
expect(cmp.startEvent.triggerName).toEqual('myAnimation');
350+
expect(cmp.startEvent.phaseName).toEqual('start');
351+
352+
expect(el.innerText).toBe('Hello from AnimationCmp!');
353+
});
354+
355+
it('should use noop animations renderer when using provideNoopAnimations()', async () => {
356+
const appRef = await bootstrapApplication(AnimationCmp, {
357+
providers: [provideNoopAnimations()],
358+
});
359+
const cmp = appRef.components[0].instance;
360+
361+
// Wait until animation is completed.
362+
await new Promise(resolve => setTimeout(resolve, 10));
363+
364+
expect(cmp.renderer).toBe('NoopAnimations');
365+
expect(cmp.startEvent.triggerName).toEqual('myAnimation');
366+
expect(cmp.startEvent.phaseName).toEqual('start');
367+
368+
expect(el.innerText).toBe('Hello from AnimationCmp!');
369+
});
370+
});
317371
});
318372

319373
it('should throw if bootstrapped Directive is not a Component', done => {

0 commit comments

Comments
 (0)