Skip to content

feat(animations): add support for disabling animations through BrowserAnimationsModule.withConfig#40731

Closed
crisbeto wants to merge 2 commits intoangular:masterfrom
crisbeto:browser-animations-for-root
Closed

feat(animations): add support for disabling animations through BrowserAnimationsModule.withConfig#40731
crisbeto wants to merge 2 commits intoangular:masterfrom
crisbeto:browser-animations-for-root

Conversation

@crisbeto
Copy link
Member

@crisbeto crisbeto commented Feb 6, 2021

Currently the only way to disable animations is by providing the NoopAnimationsModule which doesn't allow for it to be disabled based on runtime information. These changes add support for disabling animations based on runtime information by using BrowserAnimationsModule.withConfig({disableAnimations: true}).

@google-cla google-cla bot added the cla: yes label Feb 6, 2021
@crisbeto crisbeto force-pushed the browser-animations-for-root branch 3 times, most recently from 47c1f81 to e15f294 Compare February 6, 2021 11:04
@crisbeto crisbeto requested a review from jelbourn February 6, 2021 13:49
@crisbeto crisbeto marked this pull request as ready for review February 6, 2021 13:49
@pullapprove pullapprove bot requested a review from alxhub February 6, 2021 13:50
@crisbeto crisbeto added action: review The PR is still awaiting reviews from at least one requested reviewer area: animations target: minor This PR is targeted for the next minor release labels Feb 6, 2021
@ngbot ngbot bot modified the milestone: Backlog Feb 6, 2021
Comment on lines 47 to 48
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose this is problematic for the AOT compiler. The generic type of ModuleWithProviders has to be a simple type reference, as the compiler needs to statically know the NgModule import graph. The type union and dynamic switching as implemented here is therefore not supported.

The way I think this could work is to always return BrowserAnimationsModule here, but using the noop providers:

static forRoot(config: BrowserAnimationsModuleConfig): ModuleWithProviders<BrowserAnimationsModule> {
  return {
    ngModule: BrowserAnimationsModule,
    providers: config.disableAnimations ? BROWSER_NOOP_ANIMATIONS_PROVIDERS : BROWSER_ANIMATIONS_PROVIDERS,
  };
}

This removes the dynamic nature of the import while still providing the appropriate set of providers.

Additionally, it may be worth noting that even the above suggestion would likely not work in View Engine, as it has an additional requirement that even the providers have to be statically known. This restriction has been lifted in Ivy. This can be partially worked around by capturing the BrowserAnimationsModuleConfig as a token of its own and then have useFactory providers for the other tokens that can then inject BrowserAnimationsModuleConfig. But even then you may not be able to do e.g. this:

BrowserAnimationsModule.forRoot({
  disableAnimations: window.matchMedia('(prefers-reduced-motion: reduce)').matches,
})

as the value for disableAnimations is not known statically, which I believe it is required to be in VE. You may want to experiment with this a bit, as I'm not entirely sure if there's a way to make it work in VE.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was suspecting it could be problematic, but shouldn't it have caused some of the unit tests to fail?
And yeah, the dynamic value won't work for VE in AOT mode, but I figured that it won't be a big deal given that we're in the process of removing it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In tests only the JIT compiler is used AFAIK. There's packages/compiler-cli/integrationtest but I have never worked with these, but it looks like the tests inside the bazel folder run the AOT compiler using both VE and Ivy.

@crisbeto crisbeto force-pushed the browser-animations-for-root branch from e15f294 to 9713bf9 Compare February 6, 2021 14:56
Copy link
Contributor

@AndrewKushnir AndrewKushnir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@crisbeto thanks for creating this PR 👍

I have a couple questions/comments:

  • should we consider calling the method withConfig instead of forRoot (since the root/child semantics from Router does not really apply here)
  • Since it's possible to import the BrowserAnimationsModule for different sub-trees (and also call the forRoot now, such that one component might disabledAnimations: true and some other components might have disableAnimations: false), I'd propose to add some tests to verify that animations are properly enabled/disabled for the corresponding parts of the tree.

Thank you.

@crisbeto
Copy link
Member Author

crisbeto commented Feb 8, 2021

I'm open to renaming forRoot, but I was under the impression that it's a general convention for methods like these. From the docs:

The forRoot() static method is a convention that makes it easy for developers to configure services and providers that are intended to be singletons.

@AndrewKushnir
Copy link
Contributor

I'm open to renaming forRoot, but I was under the impression that it's a general convention for methods like these.

Yeah, I think forRoot is more common in general, I'm just not sure this is what we want to express with this API (the withConfig sounds more inline with potential API usage). I've also found withConfig usage in ReactiveFormsModule module.

May be we can get additional feedback from the public-api group reviewers on that (once this group is added to this PR)?

@jelbourn
Copy link
Contributor

This API can only be used at the root of the application though, right? If that's the case forRoot makes sense to me.

@crisbeto
Copy link
Member Author

Not necessarily. I believe that it would work on a subtree of modules as well.

@jelbourn
Copy link
Contributor

If that's the case then I think that forRoot wouldn't be the best fit since, at least in my mind, it's intended to only be used for APIs that only work at the app root NgModule

@crisbeto
Copy link
Member Author

Alright, I'll change it to withConfig.

@crisbeto crisbeto force-pushed the browser-animations-for-root branch from 9713bf9 to c570528 Compare February 21, 2021 13:18
@crisbeto
Copy link
Member Author

Changed based on the discussion @AndrewKushnir @jelbourn.

@crisbeto crisbeto changed the title feat(animations): add support for disabling animations through BrowserAnimationsModule.forRoot feat(animations): add support for disabling animations through BrowserAnimationsModule.withConfig Feb 21, 2021
@mary-poppins
Copy link

You can preview d11ede6 at https://pr40731-d11ede6.ngbuilds.io/.
You can preview 47c1f81 at https://pr40731-47c1f81.ngbuilds.io/.
You can preview e15f294 at https://pr40731-e15f294.ngbuilds.io/.
You can preview 9713bf9 at https://pr40731-9713bf9.ngbuilds.io/.
You can preview c570528 at https://pr40731-c570528.ngbuilds.io/.

Copy link
Contributor

@AndrewKushnir AndrewKushnir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates @crisbeto! I've left a few comments.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param config Object used to configure the behavior of the `BrowserAnimationsModule`.
* @param config Object with the `BrowserAnimationsModuleConfig` shape to configure the behavior of the module.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifying what the shape of the object is supposed to be feels redundant since TS already enforces it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was thinking to provide more specific info in docs, but I guess this would be derived from the function signature?

…rAnimationsModule.withConfig

Currently the only way to disable animations is by providing the `NoopAnimationsModule`
which doesn't allow for it to be disabled based on runtime information. These changes
add support for disabling animations based on runtime information by using
`BrowserAnimationsModule.withConfig({disableAnimations: true})`.
@crisbeto crisbeto force-pushed the browser-animations-for-root branch from c570528 to 6f12954 Compare February 24, 2021 16:44
This was referenced Mar 15, 2021
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Mar 27, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

action: merge The PR is ready for merge by the caretaker area: animations cla: yes feature Label used to distinguish feature request from other issues target: minor This PR is targeted for the next minor release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants