Material-ui: [FlatButton] A entrada do arquivo não funciona com o botão.

Criado em 15 mai. 2015  ·  27Comentários  ·  Fonte: mui-org/material-ui

Com isso...

<FlatButton primary={true} label="Choose an Image">
  <input type="file" id="imageButton"></input>
</FlatButton>

Eu acabo com um botão que na verdade não renderiza um campo de entrada de arquivo no dom (clicar no botão não abre a caixa de diálogo do arquivo).

Comentários muito úteis

Se alguém mais se deparar com esse problema, descobri que você pode definir containerElement no RaisedButton para ser algo mais adequado para ter um elemento de entrada como filho. Por exemplo, um rótulo ;-)

<RaisedButton
  containerElement='label' // <-- Just add me!
  label='My Label'>
    <input type="file" />
</RaisedButton>

Todos 27 comentários

Na versão 0.7.5.

@nschaubeck O botão no site de documentos funciona para você?

@hai-cea Sim, tem. Parecia que não havia um elemento <input> _in_ DOM, como se o elemento botão não estivesse renderizando seus filhos.

Estou com esse problema também. @nschaubeck Você já encontrou uma solução?

@e-monson Na verdade, não consegui encontrar uma solução.

isso funciona!
deixe estilos = {
exemploImageInput: {
cursor: 'ponteiro',
posição: 'absoluta',
topo: '0',
inferior: '0',
à direita: '0',
esquerda: '0',
largura: '100%',
opacidade: '0'
}
}

      <FlatButton label="Choose an Image" primary={true}>
        <input id="imageButton" style={styles.exampleImageInput} type="file"></input>
      </FlatButton>

@nikhildaga Isso só funciona no Chrome, pois colocar campos de entrada em botões não faz parte das especificações do W3C.

Uma solução diferente é fazer com que o botão apenas dispare o evento de clique de um campo de entrada oculto.

handleChange: function(e){
  console.log(e.target.value)
},
_openFileDialog: function(){
  var fileUploadDom = React.findDOMNode(this.refs.fileUpload);
  fileUploadDom.click();
},
render: function() {
  return (
    <FlatButton
      label="Upload file"
      onClick={this._openFileDialog}/>
    <input
      ref="fileUpload"
      type="file" 
      style={{"display" : "none"}}
      onChange={this._handleChange}/>
  );
}

Vejo que este problema ainda não foi corrigido corretamente ...
A solução proposta no doc só funciona no Chrome como disse @Wofiel . (ainda é o caso na versão beta 15-0.2)

Não seria melhor poder definir como htmlFor para o <FlatButton> (ou <RaisedButton> ), definir um Id para o arquivo de entrada e isso é tudo? Você não precisaria acionar o clique manualmente...
Eu tentei envolver o botão no rótulo, infelizmente, isso não funciona :(

Neste momento @Wofiel parece ser a melhor solução.

Por que fechar isso quando não há uma solução nativa

oi @Wofiel como você sugere usar essa técnica sem refs em um componente sem estado

@excalliburbd Você pode usar id e Jquery, isso deve funcionar

@Birssan manipulação dom em reagir? tudo bem?

Eu não recomendaria normalmente, mas acho que acionar um evento de clique que deve estar ok neste caso

@Wofiel Como pode ser feito com a versão 15 reagir?

@Wofiel com esta solução console.log(e.target.value) um recebe
C:\fakepath\imagefilename.png
Melhores soluções é
e.target.files[0]

Se alguém mais se deparar com esse problema, descobri que você pode definir containerElement no RaisedButton para ser algo mais adequado para ter um elemento de entrada como filho. Por exemplo, um rótulo ;-)

<RaisedButton
  containerElement='label' // <-- Just add me!
  label='My Label'>
    <input type="file" />
</RaisedButton>

@Thomas101 Obrigado! Acabei de encontrar esse problema e sua solução parece funcionar.
Impressionante :)

@Thomas101 Obrigado pela dica. Isso resolveu meu problema também. O real

Apenas complementando a resposta do @Thomas101 , quando declaro os componentes como seu exemplo, meu RaisedButton é renderizado com uma entrada de arquivo dentro. Para evitar isso, basta definir o estilo de entrada do arquivo para display: none . :)

<RaisedButton
  containerElement='label' // <-- Just add me!
  label='My Label'>
    <input type="file" style={{ display: 'none' }} />
</RaisedButton>

@andreyluiz em que circunstâncias isso não funciona:

<RaisedButton label='My Label'>
    <input type="file" />
</RaisedButton>

Não consegui encontrar um problema com o exemplo do site de documentos, mas claramente muitos outros têm esse problema!

É suposto que a entrada do arquivo não apareça com o código que você forneceu?

Isso é estranho. No meu caso, ele renderiza uma entrada de arquivo dentro do botão material-ui.

@andreyluiz Sim, com o exemplo do site de documentos (http://www.material-ui.com/#/components/raised-button) não há <input> visível. Com qual navegador e versão você está testando?

A versão mais recente do Chrome.

Concordo com @andreyluiz , o mostra também, mas com um style={{display: 'none'}} , funciona como um encanto!

tl; dr

<RaisedButton
  containerElement="label"
  icon={<Icons.FileUpload />} // material-ui-icons
  labelColor="white"
  primary
  style={{ minWidth: 40, width: 40 }}>
  <input
    onChange={e => this.upload(e.target.files[0])}
    style={{ display: 'none' }}
    type="file"
  />
</RaisedButton>

A solução acima parece não funcionar mais. Estou usando o novo branch beta v1 e o seguinte não funciona para mim

                        <Button dense
                                containerElement="label"
                                label="label">
                            <input
                                onChange={e => this.upload(e.target.files[0])}
                                style={{display: 'none'}}
                                type="file"
                            />
                        </Button>

Recebo o seguinte erro no console:

Warning: React does not recognize the `containerElement` prop on a DOM element.
If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `containerelement` instead.
If you accidentally passed it from a parent component, remove it from the DOM element.

Alguém conhece uma solução alternativa? De qualquer forma, um caso de uso tão comum não deveria ser suportado nativamente? (de uma forma não hackeada)

@AdityaAnand1 o código a seguir deve funcionar

<Button
            raised
            component="label" <---- use component instead of containerElement
            color="primary"
            className={buttonClassname}
            disabled={this.state.loading}
            onClick={this.handleButtonClick}
          >
            {'Upload'}
            <FileUpload className={classes.rightIcon} />
            <input
              onChange={e => console.log(e.target.files[0])}
              style={{ display: 'none' }}
              type="file"
            />
</Button>
Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

FranBran picture FranBran  ·  3Comentários

chris-hinds picture chris-hinds  ·  3Comentários

zabojad picture zabojad  ·  3Comentários

pola88 picture pola88  ·  3Comentários

finaiized picture finaiized  ·  3Comentários