feature
When open or close dialog,animation should define by developer.
I found that open and close dialog <mat-dialog-container></mat-dialog-container>
will add class ng-animating
,well open will add once and remove within a short time period(less than 0.5s),but in my case,open and close will use different animation,so it doesn't work for me to overwrite .ng-animating
Add different animation in open and close dialog.
Angular: 5.0.0,
Material: 5.0.0-rc0,
OS: win10,
TypeScript: 2.6.1,
Browsers: [email protected]
This should actually be implemented to all components that use animations.
A consistent way to override animations: by default provide animations that comply with material spec, but let developers override those with custom ones.
This is a very useful feature , it will be great if we can add the support.
This would be an extremely nice feature. I've hit a fork in the road with a project because I need much more flexibility out of material for simple things such as which direction a dialog flys out from. I am reading about the CDK which is pretty light right now, but it seems to offer something. I am just not sure yet (heavily lacking in documentation). The other option I see is to use the NoopAnimationsModule which kills the animation completely but that doesn't seem to get me anywhere either. It's an all or nothing thing. It doesn't look like you can do it on a per-component-basis.
We are looking forward to have this feature available.
This would be very helpful.
Thanks
Since there is no way (yet) to override animations officially, there is always dirty hack that will allow you to do that (example is for MatMenu, but works for other elements):
import { MatMenu } from '@angular/material';
import {
animate,
state,
style,
transition,
trigger
} from '@angular/animations';
MatMenu['decorators'][0].args[0].animations[0] = trigger('transformMenu', [
state('void', style({
opacity: 0,
transform: 'scale(0, 0)'
})),
state('enter-start', style({
opacity: 0,
transform: 'scale(0, 0)'
})),
state('enter', style({
opacity: 1,
transform: 'scale(1, 1)'
})),
transition('void => enter-start', animate('0ms ease-in-out')),
transition('enter-start => enter', animate('300ms ease-in-out')),
transition('* => void', animate('300ms ease-in-out', style({ opacity: 0 })))
]);
This code for example, replaces one of two angular-animations of MatMenu element, dropdown show/hide animation.
It has some limitations - animation name should be the same as original one (transformMenu
) as well as states...
But coupled with property checks it can be quite long-living solution.
To find needed animation's name and its states, you can to go to the source (in my case node_modules/@angular/material/esm2015/menu.js
) and search for animations
there.
I also need the ability to edit the animations on a dialog. Please make this configurable.
@omieliekh I tried your code but couldn't get it to work for MatDialog. I see what you referenced in node_modules/@angular/material/esm2015/dialog.js
on line 94 but I don't follow how I can edit those state transitions for a single instance of a dialog?
Can you share how you did that?
@chipallen2 sorry for frustration caused, unfortunately my code is not working on production 🙁
I'm relying on fact that animations
property should exist, but somehow it doesn't exists for minified object. At the end of the day I didn't find a way to override the animation...
You can try to override material classes.
This slides down the dialog.
@keyframes slideDown{
0%{ }
100%{
transform: translateY(20%);
}
}
.cdk-overlay-pane{
transform: translateY(-250%);
animation: slideDown 0.5s forwards 0s ease-in;
}
.cdk-overlay-container > * {
transition: none;
}
You can see it in action here: https://angular-je6ade.stackblitz.io
@carvarr it works great to customize the _show_ animation, but how can we customize the _hide_ animation?
so custom animation working on dialogs? i dont see it yet working. can anyone pplease clarify final status of this issue?
Upvoting this feature.
@carvarr 's suggestion works nicely for animating dialog entry. @omieliekh 's solution allows full customization of the dialog animations, however this always applies globally to all dialogs and I could not get this solution to work only on one instance of a material dialog.
Any news on that one? Will that become available?
@omieliekh 's solution doesn't work on --prod, or did i miss something?
My work around based on solution of @omieliekh, no error on build --prod, it is working for the wait of the feature release.
`export interface AnimationDefination {
keyframes: ɵStyleData[],
duration: number,
delay: number,
easing: string
}
export type RedefinedAnimationCallback = (AnimationDefination) => AnimationDefination;
export class ComponentDependentAnimationDriver extends ɵWebAnimationsDriver {
private redefindAnimations: { [key: string]: RedefinedAnimationCallback } = {};
/**
* Override ɵWebAnimationsDriver with animation by component
*/
public animate(
element: any,
keyframes: ɵStyleData[],
duration: number,
delay: number,
easing: string,
previousPlayers: AnimationPlayer[] = []
): any {
const defination = this.getRedefindAnimationByTagName(
element.tagName,
{
keyframes,
duration,
delay,
easing
}
);
return super.animate(element, defination.keyframes, defination.duration, defination.delay, defination.easing, previousPlayers);
}
/**
* Register callback to redefine animation by component
*/
public registerRedefinedAnimationCallback(
tagName: string,
callback: RedefinedAnimationCallback
): void {
this.redefindAnimations[tagName] = callback;
}
/**
*
* Get redefination animation by component
* @private
* @param {*} tagName
* @param {AnimationDefination} defination
* @returns {AnimationDefination}
* @memberof ComponentDependentAnimationDriver
*/
private getRedefindAnimationByTagName(
tagName: any,
defination: AnimationDefination
): AnimationDefination {
if (this.redefindAnimations[tagName]) {
defination = this.redefindAnimations[tagName](defination);
}
return defination;
}
}`
In app modules
providers: [
{ provide: AnimationDriver, useClass: ComponentDependentAnimationDriver },
{ provide: APP_INITIALIZER, useFactory: redefineDialogAnimation, deps: [ AnimationDriver ], multi: true }
]
export function redefineDialogAnimation(animationDriver: AnimationDriver): () => Promise<any> {
return () => new Promise((resolve, reject) => {
if (animationDriver && animationDriver['registerRedefinedAnimationCallback']) {
//
// Register redefine animation
//
animationDriver['registerRedefinedAnimationCallback'](
'MAT-DIALOG-CONTAINER',
(defination: AnimationDefination) => {
const keyframes = defination.keyframes;
if (keyframes && keyframes.length === 2) {
//
// Valid animation to redefine
//
if (keyframes[0].opacity === '0') {
/* Active */
keyframes[0] = {
easing,
...deactiveStyle
};
keyframes[1] = activeStyle;
} else if (keyframes[0].opacity === '1') {
/* Deactive */
keyframes[0] = {
easing,
...activeStyle
};
keyframes[1] = deactiveStyle;
}
}
defination.duration = 200;
return defination;
}
); // End Register
}
resolve();
});
}
This repo is flooded with hacks (bad) from creative people (good) and the time to market on feature requests, or any kind of feedback to the users, is extremely sluggish. It's been over one year since this was reported and has a fair amount of attention among the users. Can you please update us on this?
@danielheddelin @hughanderson4
disclaimer: I'm not related with Google in anyway and this is only pure speculation and guessing by me.
I would say that there are multiple things going on here - first of all, they have internal projects going on that we can't see, and the sheer size of google and their projects makes things slow. On the other hand, moving slowly is not a bad thing if you think support and that we can rely that things work the same way for long periods of time.
The other thing I could imagine is that it does not make sense for Google to allow a lot of customizations to be done: this project could actually be a way to get a lot of software for free in the hands of people and force the look and feel so that their web- and Android ecosystems are more familiar and friendly for new users to hop on. It just does not benefit them to allow customization beyond certain level. For this reason it may never happen, and certainly it's not a priority for them.
To be fair, this library _is_ the implementation of _Material Desing_, which, by nature, is specced by them. In the end, if material design is not your cup of tea, there are plenty of choices out there to play with. (Both Material designish and completely different.)
I definitely do not underestimate the huge effort it takes to have this thing rolling. I also do not expect them to let go of everything to fix whatever anyone wants.
But I DO expect a living github repo to keep track of its issues, and leave feedback to the thousands of people waiting. At least if it's alive and well.
Yeah, more open communication from Google would be my wish number 1, but that has been shot down in multiple repos and multiple discussion and multiple issues and multiple products - Google does not share it's future plans with us, and I think it's something one either accepts or uses other products. In our experience (using a lot of Firebase related products), it's a dead end to ask any of these questions:
The best I've managed to get as an answer is "Your request have been internally forwarded" or "When it's ready" or something else along those lines. The best indicator if (Google backed up) repo is alive and well is to monitor the frequency of commits. Really.
You can get that open communication and future plans from other vendors, but so far we've decided to swallow the pill as the overall experience has been so good. (And cheap 😄)
And if my past experience holds, the silence in this thread will be so loud that it makes my ears hurt: no Googler nor Firebaser will give any meaningful comment to these comments even if they wanted to, but I'm more than happy to be wrong. Please please prove me wrong! 🙏
The plan for this particular feature is that it will be part of CdkDialog, which we hope to finish release in 2019. There are hundreds of things like this issue where we recognize that it's nice-to-have, but other work ends up being higher priority. Right now a lot of that "other work" has been helping the framework team with work on the new Ivy renderer, especially WRT projects inside Google.
Yay, I'm wrong! And as always, thank you for the hard work!
(The quality of Angular and Angular Material is superb if you ask me, the reason for my nagging is that for us the visibility what you guys do and plan to do could be better.)
Thanks jelbourn.
Again it's fully understandable there are lots of things going on, but input like the one you just gave, is crucial when you have a thriving community trying to use your stuff that unfortunately in many cases are lacking all the bits and pieces needed to build really good solutions.
It frustrates me that the Angular framework is so full of hacks and workarounds due to this, and people still claim it's the framework to use, refering to the big forces behind it - but you almost don't hear from them. I guess I'm just spoilt rotten by the fantastic and almost instant feedback you get from the Aurelia core team members.
Thanks again for the feedback and your hard work. It's appreciated.
@carvarr I need your help, how can we customize the hide animation?
Since there is no way (yet) to override animations officially, there is always dirty hack that will allow you to do that (example is for MatMenu, but works for other elements):
import { MatMenu } from '@angular/material'; import { animate, state, style, transition, trigger } from '@angular/animations'; MatMenu['decorators'][0].args[0].animations[0] = trigger('transformMenu', [ state('void', style({ opacity: 0, transform: 'scale(0, 0)' })), state('enter-start', style({ opacity: 0, transform: 'scale(0, 0)' })), state('enter', style({ opacity: 1, transform: 'scale(1, 1)' })), transition('void => enter-start', animate('0ms ease-in-out')), transition('enter-start => enter', animate('300ms ease-in-out')), transition('* => void', animate('300ms ease-in-out', style({ opacity: 0 }))) ]);
This code for example, replaces one of two angular-animations of MatMenu element, dropdown show/hide animation.
It has some limitations - animation name should be the same as original one (transformMenu
) as well as states...But coupled with property checks it can be quite long-living solution.
To find needed animation's name and its states, you can to go to the source (in my case
node_modules/@angular/material/esm2015/menu.js
) and search foranimations
there.
it doest work to dialog.
@chipallen2 sorry for frustration caused, unfortunately my code is not working on production 🙁
I'm relying on fact thatanimations
property should exist, but somehow it doesn't exists for minified object. At the end of the day I didn't find a way to override the animation...
I think the issue with it not working in --prod is because of the string literally reference ['decorators']
When the code gets minified referencing a property via string literal will no longer work. MatMenu
doesn't have the decorators
property, so @omieliekh how did you know to reference that property?
Upvoting this feature.
@carvarr 's suggestion works nicely for animating dialog entry. @omieliekh 's solution allows full customization of the dialog animations, however this always applies globally to all dialogs and I could not get this solution to work only on one instance of a material dialog.
@Jiish were you able to get this working with --prod
?
Since there is no way (yet) to override animations officially, there is always dirty hack that will allow you to do that (example is for MatMenu, but works for other elements):
import { MatMenu } from '@angular/material'; import { animate, state, style, transition, trigger } from '@angular/animations'; MatMenu['decorators'][0].args[0].animations[0] = trigger('transformMenu', [ state('void', style({ opacity: 0, transform: 'scale(0, 0)' })), state('enter-start', style({ opacity: 0, transform: 'scale(0, 0)' })), state('enter', style({ opacity: 1, transform: 'scale(1, 1)' })), transition('void => enter-start', animate('0ms ease-in-out')), transition('enter-start => enter', animate('300ms ease-in-out')), transition('* => void', animate('300ms ease-in-out', style({ opacity: 0 }))) ]);
This code for example, replaces one of two angular-animations of MatMenu element, dropdown show/hide animation.
It has some limitations - animation name should be the same as original one (transformMenu
) as well as states...
But coupled with property checks it can be quite long-living solution.
To find needed animation's name and its states, you can to go to the source (in my casenode_modules/@angular/material/esm2015/menu.js
) and search foranimations
there.it doest work to dialog.
sorry, but could you fix your typo in doest
? tnx
Upvoting this feature.
@carvarr 's suggestion works nicely for animating dialog entry. @omieliekh 's solution allows full customization of the dialog animations, however this always applies globally to all dialogs and I could not get this solution to work only on one instance of a material dialog.@Jiish were you able to get this working with
--prod
?
Unfortunately this solution never got past ”ng serve”, so I can’t say whether it would work with minified code or not. Still waiting for official solution, before applying custom animations to production code.
would be nice to have this
Upvote
Any updates on this?
Angular material is super slow. Tried all workarounds but none is working.
For MatDialog it's in here:
MatDialogContainer['decorators'][0].args[0].animations[0];
I changed it within main.ts to have effect.
My custom dialog service, with animation and more.
When will the CDKDialog be released?
You can try to override material classes.
This slides down the dialog.
@Keyframes slideDown{
0%{ }
100%{
transform: translateY(20%);
}
}.cdk-overlay-pane{
transform: translateY(-250%);
animation: slideDown 0.5s forwards 0s ease-in;
}
.cdk-overlay-container > * {
transition: none;
}You can see it in action here: https://angular-je6ade.stackblitz.io
My custom dialog service, with animation and more.
works in chrome and firefox but does not work in safari
So the way I worked around this was to add a panel-class to the dialog then set up custom animation for that dialog.
global scss file
//--------------------------------------------
// DIALOG SIDE PANEL
//--------------------------------------------
@keyframes slide {
100% { right: 0; }
}
.dialog-side-panel {
position: fixed !important;
bottom: 0;
top: 0;
right: -100vw;
width: 100vw;
height: 100%;
animation: slide 0.1s forwards;
animation-delay: 0.1s;
.mat-dialog-container {
border-radius: 0;
}
}
custom dialog button component
import { Component, Input, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { Overlay } from '@angular/cdk/overlay';
import { SidePanelRadioFilterComponent } from '@enterprise/prod/shared/filters/side-panel-radio-filter/side-panel-radio-filter.component';
import { SelectOption } from '@enterprise/prod/shared/filters/select/select-options';
@Component({
selector: 'senet-button-filter',
templateUrl: './button-filter.component.html',
styleUrls: ['./button-filter.component.scss']
})
export class ButtonFilterComponent implements OnInit {
@Input() filters?: SelectOption<any>[];
hover = false;
constructor(public dialog: MatDialog, public overlay: Overlay) {}
ngOnInit(): void {}
openSidePanel(): void {
this.dialog.open(SidePanelRadioFilterComponent, {
panelClass: 'dialog-side-panel',
width: '95vw',
maxWidth: '100vw',
height: '100%',
data: this.filters ? this.filters : {} // send in what we know
});
}
}
Can someone advise what is a good way to disable background page refresh animation while doing a retry on an open mat dialog component?
Ok, the question is that when the open()
method of the MatDialog is called, the Angular Material Component itself animates the opening of the dialog overlay. So, in my situation, I have created a typescript function file under shared called dialog-animator.ts
which looks as follows:
/**
* Animates an overlaid mat dialog on close.
*/
export function fadeOut() {
const overlays = document.getElementsByClassName('my-overlay');
for (let i = 0; i < overlays.length; i++) {
overlays[overlays.length - 1].animate([
{ transform: 'scale(1, 1)' },
{ transform: 'scale(0, 0)' }
], { duration: 400, iterations: 1 });
}
}
This function is imported and called when I click on x
to close the mat dialog to the dialog.component.ts
file.
Maybe this is one of the worst ways to solve the issue but I didn't want to install the ng-dialog-animation
package.
In Angular latest version I was able to with keyframeAnimationOptions.
set the animation property something like this.
animation: {
to: 'aside',
incomingOptions: {
keyframeAnimationOptions: { duration: 300 }
},
outgoingOptions: {
keyframeAnimationOptions: { duration: 300 }
}
},
@rajesh05c4 where in the angular project did you use these keyframeAnimationOptions? In which class?
@omaracrystal
Your solution works, thanks.
However, the original animation still runs - any idea how to disable that, making it possible to also remove the animation delay?
Our solution to this is to use NoopAnimationsModule
, then implement custom animations using custom panel/backdrop classes, and global CSS. Similar to this solution. This also works for other components like MatMenu and MatDatePicker.
.custom-mat-dialog-panel {
.mat-dialog-container {
animation: dialog-animation;
}
}
// If you want to customise the backdrop animation
.custom-mat-dialog-backdrop {
transition: none;
animation: backdrop-animation;
}
However this caused another problem - because no angular animations were playing, if a dialog was opened from MatMenu, then MatMenu would steal focus away from the dialog (focussing the trigger element). I believe this is because when using angular animations, the dialog doesn't capture focus until after the animations finish, which is also after MatMenu has set focus. We managed to work around this by telling the dialog to recapture focus:
const ref = this.dialog.open(...);
ref.afterOpened().subscribe(() => {
setTimeout(() => {
ref._containerInstance._recaptureFocus();
});
});
If you abstract opening of dialogs into a service then this only needs to be done once. Another workaround is to call dialog.open()
in setTimeout()
, however that would need to be implemented everywhere that you open a dialog, and therefore isn't as great.
Most helpful comment
Since there is no way (yet) to override animations officially, there is always dirty hack that will allow you to do that (example is for MatMenu, but works for other elements):
This code for example, replaces one of two angular-animations of MatMenu element, dropdown show/hide animation.
It has some limitations - animation name should be the same as original one (
transformMenu
) as well as states...But coupled with property checks it can be quite long-living solution.
To find needed animation's name and its states, you can to go to the source (in my case
node_modules/@angular/material/esm2015/menu.js
) and search foranimations
there.