Material-ui: [Dialog] Incorrect paddingTop when opening Dialog with dynamic content

Created on 18 Sep 2015  路  30Comments  路  Source: mui-org/material-ui

When I have structure like that

<Dialog ref="mediaModal" actions={standardActions} title="Multimedia Browser" autoDetectWindowHeight={true} autoScrollBodyContent={false} contentClassName="media-modal" contentStyle={{ width: '90%', maxWidth: 'auto', height: '100%' }} contentInnerStyle={{ maxHeight: '100%' }}>
    <div className="media-modal__menu">
      <List subheader="Media types">
        <ListItem primaryText="Images" leftIcon={<FontIcon className="material-icons">image</FontIcon>} />
        <ListItem primaryText="Audio" leftIcon={<FontIcon className="material-icons">library_music</FontIcon>} />
        <ListItem primaryText="Videos" leftIcon={<FontIcon className="material-icons">video_library</FontIcon>} />
        <ListItem primaryText="3D" leftIcon={<FontIcon className="material-icons">blur_on</FontIcon>} />
      </List>
    </div>
    <div className="media-modal__content">
      <MediaList items={items}/>
    </div>
</Dialog>

Where MediaList contain grid of images. It gets paddingTop calculated incorrectly Padding on first opening

But, on second _positionUpdate() call it have proper positioning. On update

I suppose that images get calculated their dimensions later than modal (I've set width and height properties on <img> tag)

I'll try to work on PR on that, but maybe someone is smarter than me :)

bug 馃悰

Most helpful comment

Forking @echenley's ideas:

import React, {
  Component,
} from "react";

import Dialog from "material-ui/Dialog";

const styles = {
  dialogRoot: {
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    paddingTop: 0
  },
  dialogContent: {
    position: "relative",
    width: "80vw",
    transform: "",
  },
  dialogBody: {
    paddingBottom: 0
  }
};

export default class CustomDialog extends Component {
  render () {
    const { ...props } = this.props;
    return (
      <Dialog
        {...props}
        contentStyle={ styles.dialogContent }
        bodyStyle={ styles.dialogBody }
        style={ styles.dialogRoot }
        repositionOnUpdate={ false }
      />
    );
  }
}

I'm not sure why this is not the default.

All 30 comments

I'm experiencing a similar issue. The first time I render a Dialog paddingTop is correct, but if the component update, paddingTop is incorrect.

I'm facing the same issue. You can use window.dispatchEvent(new Event('resize')) as a workaround (call it after appending the content). It triggers window resize event and forces dialog position/size to be recalculated. Hope it will be helpful.

@aslauris your solution is nice,but when I show images in a dialog,I don't know when to call the dispatchEvent function because of load time of image.has any idea?

@Ben07 you can probably set call window.dispatchEvent from inside the 'componentWillUpdate' lifecycle callback. i assume that gets called as the image loads, but I'm not sure.

@rhythnic thanks,I set call window.dispatchEvent inside the 'componentDidUpdate' and use DIV tag which has Immutability height to wrap these images.It's works.

Any advice on solving this? I'd be happy to submit a PR if given direction.

@morenoh149 you can fix it by overriding the dialog styles: https://github.com/callemall/material-ui/issues/2322#issuecomment-163433242.

There's not really a perfect solution at the moment. You could also try something like this:

<Dialog
  contentStyle={ styles.dialogContent }
  bodyStyle={ styles.dialogBody }
  style={ styles.dialogRoot }
  repositionOnUpdate={ false }
/>

var styles = {
  dialogRoot: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    paddingTop: 0
  },
  dialogContent: {
    position: 'relative',
    width: '90%',
    maxWidth: 500
  },
  dialogBody: {
    paddingBottom: 0
  }
};

@morenoh149 : were you able to solve the issue with the above suggestion? Let me know if that works

@grimor : was this issue resolved for you?

haven't had a chance. sorry.

@tintin1343 I'm still experiencing a similaire issue with dialog and dynamic content.

@oliviertassinari : I can look into it. Could you post your findings here? I can take it over. I actually made a change in the dialog PaddingTop attribute in the DatePicker PR i told you about.

@oliviertassinari @tintin1343 FYI guys I am currently experimenting with some 0.16.0 dialog updates.

@oliviertassinari : Was this fixed with the PR?

@tintin1343 No, I was referring to a related issue.

@echenley thanks for https://github.com/callemall/material-ui/issues/1676#issuecomment-201376256.

I had to do 90vw instead of 90% to get it to work though. Thank you for a great workaround.

dialogContent: {
    position: 'relative',
    width: '90vw',
    maxWidth: 500
  },

can we just have a prop to disable the vertical center?
I really don't want some of my dialogs to y offset like crazy because inner content changes.

Forking @echenley's ideas:

import React, {
  Component,
} from "react";

import Dialog from "material-ui/Dialog";

const styles = {
  dialogRoot: {
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    paddingTop: 0
  },
  dialogContent: {
    position: "relative",
    width: "80vw",
    transform: "",
  },
  dialogBody: {
    paddingBottom: 0
  }
};

export default class CustomDialog extends Component {
  render () {
    const { ...props } = this.props;
    return (
      <Dialog
        {...props}
        contentStyle={ styles.dialogContent }
        bodyStyle={ styles.dialogBody }
        style={ styles.dialogRoot }
        repositionOnUpdate={ false }
      />
    );
  }
}

I'm not sure why this is not the default.

Guys, I'm trying to pass in the "styles.dialogRoot" into the Dialog component with just a "paddingTop" of 0, and it just doesn't seem to get applied into the Dialog. I'm doing exactly the same steps as above, just applying the paddingTop. Any ideas why style isn't working?

Yeah same actually, paddingTop does not seem to get reset...
We need a simple way to "center in the middle" dynamically and without it to be handled by JS.. should be handled by CSS..

I really enjoy almost all components of material-ui but this one is really limited..

@nickbae91 my guess is you use repositionOnUpdate but you shouldn't.
i've updated my code to move the {...props} above so it's always getting set

see here: https://github.com/callemall/material-ui/blob/master/src/Dialog/Dialog.js#L218 the padding get re-set in repositionOnUpdate case

This is somehow related to animations. One can manually trigger resize event, but Dialog will repositioned after animations.

Currently, my workaround is this. But you'll notice how Dialog repositioned after animation

componentDidUpdate: function () {
        setTimeout(() => {
                window.dispatchEvent(new Event('resize'));
        }, 500);
},

I think the dialog could be centered vertically by using flexbox patterns withouth calculating padding-top. However, I fixed it with

<Dialog className: 'dialog-root' ... > ... </Dialog>
.dialog-root {
  padding-top: 0 !important;
}

Doing the same using inline styles does not work. Is it overwritten by the calculated value?

Because my dialog has so much content that it shouldn't have any top-padding, this is good enough as a workaround until this bug is fixed.

That issue has been solved on the next branch. I'm closing it.

I still have this issue on v0.17.0 could you please confirm this fix for this version? thanks.

The issue is still present on the 0.x.x releases. We don't have the resources to maintained two versions. If the master branch is affected, we close issues once they are fixed on the next branch.

You can use this props for Dialog
repositionOnUpdate={true}

@kamran-koupayi: repositionOnUpdate does not work in my case. The child (content) of the dialog is updated but the dialog does not detect it.

I've just fixed an issue with our application where this was happening.
The basic issue is that a dialog with a child control has no clue that the child has updated.

My fix is along these lines (no point in showing you the code its exceptionally specific to our situation)

in the dialog code :

in the child :
componentDidUpdate() {
if (this.state.oldData !== this.state.newData) {
this.setState({oldData: this.state.newData});
if (this.props.updated) { this.props.updated(); }
}
}

... the theory is that when the child updates its state data, it fires the callback which updates the parent, but that only happens when the specific data I need watching changes.
If you don't have some way to check your data has changed before the callback fires, you end up in an infinite loop of render, state change, callback

hope thats useful to someone....

Was this page helpful?
0 / 5 - 0 ratings

Related issues

finaiized picture finaiized  路  3Comments

anthony-dandrea picture anthony-dandrea  路  3Comments

reflog picture reflog  路  3Comments

activatedgeek picture activatedgeek  路  3Comments

iamzhouyi picture iamzhouyi  路  3Comments