Material-ui: [Dialog] position not updated when changing contents

Created on 15 Dec 2016  路  12Comments  路  Source: mui-org/material-ui

v0.15.4

Steps to reproduce:

  1. create a dialog with arbitrary children
  2. hide/show the children

Expected: the dialog should reposition

Actual: the dialog does not reposition.

In my case, the children are being shown/hidden outside of the React renderer (stateful DOM).

bug 馃悰 Dialog v0.x

Most helpful comment

This is still an issue. It is made much worse by the fact that a lot of the data fetching in modern React applications is asynchronous, as is the mounting/rendering, hence you don't have a synchronous single location to do trigger a resize event.

For now, I've done something like:

setTimeout(() => { window.dispatchEvent(new Event('resize')); }, 0);

All 12 comments

@OliverJAsh: can you please provide a running code to reproduce your issue?

had the same issue, no luck with repositionOnUpdate as the content doesnt really change. would be great if we can trigger this manually.

Or the dialog could just use CSS to position itself in the centre, instead of JS. Flexbox would enable this

@lucasbento

The issue occurs when the elements being render change size.

The below code example has the variable ANIMATEFLAG when this variable is set totrue the repositioning fails whereas if it set to false and does not animate it works correctly.

````javascript
const ANIMATEFLAG = true;

import React from 'react';
import {
Step,
Stepper,
StepLabel,
} from 'material-ui/Stepper';
import Dialog from 'material-ui/Dialog';
import RaisedButton from 'material-ui/RaisedButton';
import FlatButton from 'material-ui/FlatButton';
import ExpandTransition from 'material-ui/internal/ExpandTransition';
import TextField from 'material-ui/TextField';

/**

  • A contrived example using a transition between steps
    */
    class HorizontalTransition extends React.Component {

state = {
loading : false,
finished : false,
stepIndex : 0,
open : true,
};

dummyAsync = (cb) => {
if (ANIMATEFLAG) {
this.setState({ loading: true }, () => {
this.asyncTimer = setTimeout(cb, 500);
});
} else {
cb();
}
};

handleNext = () => {
const { stepIndex } = this.state;
if (!this.state.loading) {
this.dummyAsync(() => this.setState({
loading : false,
stepIndex : stepIndex + 1,
finished : stepIndex >= 2,
}));
}
};

handlePrev = () => {
const { stepIndex } = this.state;
if (!this.state.loading) {
this.dummyAsync(() => this.setState({
loading : false,
stepIndex : stepIndex - 1,
}));
}
};

getStepContent(stepIndex) {
switch (stepIndex) {
case 0:
return (


Select campaign settings. Campaign settings can include your budget, network, bidding
options and adjustments, location targeting, campaign end date, and other settings that
affect an entire campaign.


);
case 1:
return (



Ad group status is different than the statuses for campaigns, ads, and keywords, though the
statuses can affect each other. Ad groups are contained within a campaign, and each campaign can
have one or more ad groups. Within each ad group are ads, keywords, and bids.








Something something whatever cool



);
case 2:
return (


Try out different ad text to see what brings in the most customers, and learn how to
enhance your ads using features like ad extensions. If you run into any problems with your
ads, find out how to tell if they're running and how to resolve approval issues.


);
default:
return 'You're a long way from home sonny jim!';
}
}

renderContent() {
const { finished, stepIndex } = this.state;
const contentStyle = { margin: '0 16px', overflow: 'hidden' };

if (finished) {
  return (
    <div style={contentStyle}>
      <p>
        <a
          href="#"
          onClick={(event) => {
            event.preventDefault();
            this.setState({ stepIndex: 0, finished: false });
          }}
        >
          Click here
        </a> to reset the example.
      </p>
    </div>
  );
}

return (
  <div style={contentStyle}>
    <div>{this.getStepContent(stepIndex)}</div>
    <div style={{ marginTop: 24, marginBottom: 12 }}>
      <FlatButton
        label="Back"
        disabled={stepIndex === 0}
        onTouchTap={this.handlePrev}
        style={{ marginRight: 12 }}
      />
      <RaisedButton
        label={stepIndex === 2 ? 'Finish' : 'Next'}
        primary
        onTouchTap={this.handleNext}
      />
    </div>
  </div>
);

}

handleClose = () => {
this.setState({ open: false });
}

render() {
const { open, loading, stepIndex } = this.state;

return (
  <Dialog
    modal={false}
    open={open}
    onRequestClose={this.handleClose}
    autoScrollBodyContent
  >
    <Stepper activeStep={stepIndex}>
      <Step>
        <StepLabel>Select campaign settings</StepLabel>
      </Step>
      <Step>
        <StepLabel>Create an ad group</StepLabel>
      </Step>
      <Step>
        <StepLabel>Create an ad</StepLabel>
      </Step>
    </Stepper>
    <ExpandTransition loading={loading} open>
      {this.renderContent()}
    </ExpandTransition>
  </Dialog>
);

}
}

export default HorizontalTransition;
````

Hey @OliverJAsh, could you manage to fix this issue and implement a decent centering?

@mlukaszczyk Nope, I just had to put a hardcoded height on the content container and make it scrollable.

my workaround is to call
window.dispatchEvent(new Event('resize'))
after the content has changed

This is still an issue. It is made much worse by the fact that a lot of the data fetching in modern React applications is asynchronous, as is the mounting/rendering, hence you don't have a synchronous single location to do trigger a resize event.

For now, I've done something like:

setTimeout(() => { window.dispatchEvent(new Event('resize')); }, 0);

We have been porting the component on the next branch. We reimplemented it from the ground-up. While we haven't tested it, I think that the issue is most likely fixed on that branch. Hence, I'm closing it.

I know this is a year old thread, and the issue is seemingly resolved in the latest release which I'm thrilled about and would love to adopt... but it kind of sucks that such a glaring UI bug in a dynamic environment was never resolved even more so when you consider that this was closed nearly a year prior to the release of v1.

I don't have the luxury at this time to adopt the latest version and the conversion is looking like an entire rewrite at this point. So I am stuck working with the alpha implementation still. These little quirks that exist make it more enticing to look at alternative frameworks as I worry that v1 will have issues that will receive the same treatment.

If there is a reasonable solution that is less of a hack than what I've seen I'd love to know about it.

@scotmatson Sorry, I can't help.

This is still an issue. It is made much worse by the fact that a lot of the data fetching in modern React applications is asynchronous, as is the mounting/rendering, hence you don't have a synchronous single location to do trigger a resize event.

For now, I've done something like:

setTimeout(() => { window.dispatchEvent(new Event('resize')); }, 0);

For those still at older version and trying to fix the issue >> This works like a charm

Was this page helpful?
0 / 5 - 0 ratings

Related issues

FranBran picture FranBran  路  3Comments

anthony-dandrea picture anthony-dandrea  路  3Comments

ryanflorence picture ryanflorence  路  3Comments

ghost picture ghost  路  3Comments

rbozan picture rbozan  路  3Comments