ComboBox Dinamico React JS - CRUD

11 respostas Resolvido
reactjavascript
G

Estou com um problema com o meu comboBox Dinamico em React.js.
Minha tela de CRUD está quase completa, consigo cadastrar dados no banco, visualizar os dados cadastrados, excluir, mostrar os dados em uma tabela, e consigo editar, porém na minha tela de edição, não consigo trazer os valores já cadastrados no meu comboBox:

Segue o código:

import React, { Component } from 'react';
class Select extends Component {
  render() {
return (
      <div className="form-row">
        <label className="labelCombo">{this.props.nome}</label>
        <select id={this.props.idSelect} className="form-control" onChange={this.props.onChange}
          value={this.props.selectedValue} >
          <option >Selecione</option> {
            this.props.dados.map(
              row => <option value={row._id} key={row._id}>{row.valor}</option>
            )
          }
        </select>
      </div>
    );
  }
}
export default Select;

ComboBox:

export default class ComboBoxEndereco extends Component {
          constructor(props) {
            super(props);
            this.state = ({
              option: []
            });

            Api.ListarEndereco()
              .then((list) => {
                this.setState({
                  option: list
                });
              })
              .catch((err) => { console.log(err) }
              );
          }
          render() {
            return (
              <div >
                  <Select dados={this.state.option} nome="Endereço" idSelect="endereco"
                    onChange={this.props.onChange} selectedValue={this.props.selectedValue}
                     />
              </div>
            );
          }
        }

    Classe Edit: 
    export default class Edit extends Component {
      constructor(props) {
        super(props);
        this.state = {      
          _id_endereco: this.props._id_endereco,
          endereco: this.props.endereco,
          _id_departamento: this.props._id_departamento,
          departamento: this.props.departamento,
          _id_categoria: this.props._id_categoria,
          categoria: this.props.categoria,
          usuario: this.props.usuario,
          host: this.props.host,
          marca: this.props.marca,
          service_tag: this.props.service_tag,
          processador: this.props.processador,
          hard_disk: this.props.hard_disk,
          so: this.props.so,
          so_versao: this.props.so_versao,
          qtd_monitores: this.props.qtd_monitores,
          fim_garantia: this.props.fim_garantia,
          memoria: this.props.memoria,
          mac_address: this.props.mac_address,
          arquitetura: this.props.arquitetura,
          service_pack: this.props.service_pack,
          ip: this.props.ip,
          senha_bios: this.props.senha_bios,
          softwares: this.props.softwares,
          valor: this.props.valor,
          item: []
        }
        console.log("Params => " + this.props.arquitetura);
      }
      componentDidMount() {
        this.exibirDados();
      }

      onChangeCombo = (e) => {
        e.preventDefault();
        //this.setState({ [e.target.id]: e.target.value });
        var index = e.nativeEvent.target.selectedIndex;
        if (e.target.id === "endereco") {
          this.setState({ "_id_endereco": e.target.value,
                          "endereco": e.nativeEvent.target[index].text });      
        }
        if (e.target.id === "departamento") {
          this.setState({ "_id_departamento": e.target.value, 
                          "departamento": e.nativeEvent.target[index].text });      
       }
       if (e.target.id === "categoria") {
          this.setState({ "_id_categoria": e.target.value ,
                          "categoria": e.nativeEvent.target[index].text });      
        }
      }

      onChange = (e) => {
        e.preventDefault();
        this.setState({ [e.target.id]: e.target.value });
     }    

      onSubmit = (e) => {
        e.preventDefault();
        const { _id_endereco, endereco, _id_departamento, departamento,
          _id_categoria, categoria, usuario, host, marca, service_tag, processador, hard_disk,
          so, so_versao, qtd_monitores, fim_garantia, memoria, mac_address, arquitetura,
          service_pack, ip, senha_bios, softwares } = this.state;
        let obj = {
          "enderecos": {
            "_id": _id_endereco,
            "endereco": endereco
          },
          "departamentos": {
            "_id": _id_departamento,
            "departamento": departamento
          },
          "usuario": usuario,
          "host": host,
          "marca": marca,
          "service_tag": service_tag,
          "processador": processador,
          "categorias": {
            "_id": _id_categoria,
            "categoria": categoria
          },
          "hard_disk": hard_disk,
          "so": so,
          "so_versao": so_versao,
          "qtd_monitores": qtd_monitores,
          "fim_garantia": fim_garantia,
          "memoria": memoria,
          "mac_address": mac_address,
          "arquitetura": arquitetura,
          "service_pack": service_pack,
          "ip": ip,
        "senha_bios": senha_bios,
          "softwares": softwares,
          "valor_processador": 8,
          "valor_memoria": 9,
         "valor_hd": 5
        }

        axios.put(url + this.props.match.params.id, obj)
          .then(res => console.log(res.data));
        this.setState({
          _id_endereco: '',
          endereco: '',
          _id_departamento: '',
          departamento: '',
         _id_categoria: '',
          categoria: '',
          usuario: '',
          host: '',
          marca: '',
         service_tag: '',
         processador: '',
          hard_disk: '',
          so: '',
          so_versao: '',
          qtd_monitores: '',
         fim_garantia: '',
          memoria: '',
          mac_address: '',
          arquitetura: '',
          service_pack: '',
          ip: '',
          senha_bios: '',
          softwares: ''
        })
        this.props.history.push('/index');
        window.location.reload();
      }
      exibirDados() {
        axios.get(url + this.props.match.params.id)
          .then(response => {
            this.setState({ item: response.data });        
            console.log(response.data)
          })
          .catch(() => { console.log('Erro ao recuperar os dados'); });
      }
      render() {
        return (
          <div className="container" style={{ marginTop: 30 }}>
            <h1 align="center">Editar</h1>
            {this.state.item.map((item, _id) => {
              return (
                <form id="formulario" onSubmit={this.onSubmit} key={item._id} >
                  <hr /><br />
                  <div className="row">
                    <ComboBoxEndereco onChange={this.onChangeCombo} selectedValue={item.enderecos._id} />
                    <ComboBoxDepartamento onChange={this.onChangeCombo} selectedValue={item.departamentos._id} />
                    <ComboBoxCategoria onChange={this.onChangeCombo} selectedValue={item.categorias._id} />
                    <br /> <br /> <br />
                    <Input divClass="form-row" id="usuario" labelClass="labelUsuario"
                      label="Usuário" onChange={this.onChange} value={item.usuario} />
                    <Input divClass="form-group" id="host"
                      label="Host" onChange={this.onChange} value={item.host} />
                    <Input divClass="form-group" id="marca"
                      label="Marca" onChange={this.onChange} value={item.marca} />
                    <Input divClass="form-group" id="service_tag"
                      label="Service Tag" onChange={this.onChange} value={item.service_tag} />
                    <Input divClass="form-group" id="processador"
                      label="Processador" onChange={this.onChange} value={item.processador} />
                    <Input divClass="form-group" id="hard_disk" label="Hard disk"
                      onChange={this.onChange} value={item.hard_disk} />
                    <Input divClass="form-group" id="so"
                      label="S.O" onChange={this.onChange} value={item.so} />
                    <Input divClass="form-group" id="so_versao" label="Versão"
                      onChange={this.onChange} value={item.so_versao} />
                    <InputFormatado divClass="form-group" id="qtd_monitores"
                      label="Monitor" onChange={this.onChange} format="#" value={item.qtd_monitores} />
                    <InputFormatado divClass="form-group" id="fim_garantia" label="Garantia"
                      onChange={this.onChange} format="##/##/####" value={item.fim_garantia} />
                    <Input divClass="form-group" id="memoria"
                      label="Memória" onChange={this.onChange} value={item.memoria} />
                    <Input divClass="form-group" id="mac_address"
                      label="Mac Address" onChange={this.onChange} value={item.mac_address} />
                    <InputFormatado divClass="form-group" id="arquitetura"
                      label="arquitetura" onChange={this.onChange} format="##" value={item.arquitetura} />
                    <Input divClass="form-group" id="service_pack"
                      label="Service Pack" onChange={this.onChange} value={item.service_pack} />
                    <Input divClass="form-group" id="ip"
                      label="IP" onChange={this.onChange} value={item.ip} />
                    <Input divClass="form-group" id="senha_bios" label="Bios"
                      onChange={this.onChange} value={item.senha_bios} />
                  </div>
                  <div className="form-group">
                    <Textarea labelClass="software-class" nomeLabel="Softwares" TextClass="form-control"
                      id="softwares" onChange={this.onChange}
                      value={item.softwares} />
                    <br />
                    <Botao tipo="btn btn-secondary" texto="Atualizar" id="botao-enviar" /><br></br>
                  </div>
                </form>
              )
            }
            )}
          </div>

        )
      }
    }

Sempre que eu vou editar algo, mesmo que seja só um campo do meu input, o meu combox é enviado com o valor ‘vazio’, e tenho que voltar na tela de edição para selecionar o meu ComboBox novamente porém ele não permite que eu faça um onchange nele.
Preciso saber como faço para pegar o valor desse ComboBox e realizar o onchange correto nele.

11 Respostas

Dragoon

Um exemplo manipulando <select>:

class TodoApp extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
    	items: [
      	{ id: 1, text: "Learn JavaScript" },
        { id: 2, text: "Learn React" },
        { id: 3, text: "Play around in JSFiddle" },
        { id: 4, text: "Build something awesome" }
      ],
      selectItem: 4
    };
    this.handleSelectItem = this.handleSelectItem.bind(this);
  }
  
  handleSelectItem(e) {
  	this.setState({selectItem: e.target.value});
  };
  
  render() {
    return (
      <div>
        <h2>Todos: {this.state.selectItem}</h2>
        <select value={this.state.selectItem} onChange={this.handleSelectItem}>
          {this.state.items.map((item, index) => (
          	<option key={index} value={item.id}>{item.text}</option>
          ))}
        </select>
      </div>
    )
  }
}

ReactDOM.render(<TodoApp />, document.querySelector("#app"))

Referencia: https://pt-br.reactjs.org/docs/forms.html

Exemplo rodando ONLINE

G

Muito obrigado pela ajuda, irei testar e logo retorno com o resultado!

G

Testei porém não funcionou porque eu pego os valores dinamicamente, ele me traz os valores, porém eu não consigo mudar o valor que já vem selecionado. Se eu editar algum outro campo, os valores que já foram cadastrados retornam como null e tenho que cadastrar novamente.
Teria algum exemplo de como eu crio um comboBox dinâmico e com o onchange funcionando?

Tentei fazer isso porém ele não me permite mudar o valor:

export default class ComboBoxEndereco extends Component {
      constructor(props) {
        super(props);
        this.state = {
          option: [],
        }
        this.handleSelectItem = this.handleSelectItem.bind(this);
      }
      componentDidMount() {
        ServiceApi.ListarEndereco()
          .then((list) => {
            this.setState({
              option: list
            });
          })
          .catch((err) => { console.log(err) }
          );
      }
      render() {
        return (
          <div className="form-row">
            <label className="labelCombo">Endereço</label>
            <select id="endereco" value={this.props.selectedValue} onChange={this.props.onChange}
              className="form-control" >
              <option >Selecione</option>
              {
                this.state.option.map(
                  row => <option value={row._id} key={row._id}>{row.valor}</option>
                )
              }         
   </select>
          </div>
        );
      }
    }

Chamo ele assim no meu componente:

render() {
return (
  <div className="container" style={{ marginTop: 30 }}>
    <h1 align="center">Editar</h1>
    {this.state.item.map((item, _id) => {
      return (
        <form id="formulario" onSubmit={this.onSubmit} key={item._id} >
          <hr /><br />
          <div className="row">
            <ComboBoxEndereco selectedValue={item.enderecos._id} />

Os valores que ele me traz e que eu devo enviar é sempre assim:

let obj = {

"enderecos": {
    "_id": _id_endereco,
    "endereco": endereco
  },

  "departamentos": {
    "_id": _id_departamento,
    "departamento": departamento
  },

  "categorias": {
    "_id": _id_categoria,
    "categoria": categoria
  }
}
Dragoon

Amigo a parte dinâmica está no seu código, eu fiz um exemplo funcional onde está item você coloca a parte dinâmica. O problema é outro pelo visto

G

Isso, quando eu chamo os valores do meu comboBox para dentro do meu option ele aparece fixo lá, porém, se eu dar um put em algum outro campo, o meu comBox não envia o valor que foi pego antes, ele envia vazio. Assim, toda vez que eu for editar algo, eu sempre vou ter que selecionar o item do comboBox novamente.

Dragoon

Você observou que eu guardo o estado do selecta??? Ou não entendeu o exemplo?

G

Sim, eu estou passando assim:

class Select extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedValue: this.props.selectedValue
    }
  }
  render() {
    return (
      <div className="form-row">
        <label className="labelCombo">{this.props.nome}</label>
        <select className="form-control" onChange={this.props.onChange} id={this.props.idSelect}
          value={this.props.selectedValue}>
          {/* <option value={this.props.valor}>{this.props.selectedValue}</option> */}
          <option>Selecione</option>
          {
            this.props.dados.map(
              row => <option value={row._id} key={row._id} id={row._id}>{row.valor}</option>
            )
          }
        </select>
      </div>
    );
  }
}

export default Select;

no meu combo eu populo ele assim:

import React, { Component } from 'react';
import Select from './Select';
import ServiceApi from '../../services/ServiceApi';

export default class ComboBoxEndereco extends Component {
  constructor(props) {
    super(props);
    this.state = {
      option: [],
    }
  }
  componentDidMount() {
    ServiceApi.ListarEndereco()
      .then((list) => {
        this.setState({
          option: list
        });
        console.log('Endereço: ' + JSON.stringify(list))
      })
      .catch((err) => { console.log(err) }
      );
  }
  render() {
    return (
      <div >
        <Select dados={this.state.option} nome="Endereço" idSelect="endereco"
          selectedValue={this.props.selectedValue} onChange={this.props.onChange}
          defaultValue={this.props.defaultValue} />
      </div >
    );
  }
}

Desse modo ele me trás o valor que foi registrado por ultimo, porém ele não permite que eu mude outro campo do select sem selecionar novamente o campo que já foi registrado.

Dragoon

A sua duvida está confusa pra mim! como não estou vendo o projeto inteiro fica complicado dizer algo … eu te passei um exemplo, você parece que tem maiores duvidas.

G

Me desculpe, o que eu preciso mesmo é de um exemplo de um formulario com um combobox sendo gerado dinamicamente, dando para trazer o valor selecionado e poder edita-lo posteriormente

Dragoon

Simule algum exemplo então, porque isso foi respondido já! Mas você não consegue abstrair e colocar no seu, então nos mostre

G
Solucao aceita

Estou passando assim o meu Select em um componente separado para listar todos os meus options cadastrados:

import React, { Component } from 'react';

class Select extends Component {
  render() {
    return (
      <div className="form-row">
        <label className="labelCombo">{this.props.nome}</label>
        <select className="form-control" onChange={this.props.onChange} id={this.props.idSelect}
          value={this.props.selectedValue}>
          {/* <option value={this.props.valor}>{this.props.selectedValue}</option> */}
          <option>Selecione</option>
          {
            this.props.dados.map(
              row => <option value={row._id} key={row._id} >{row.valor}</option>
            )
          }
        </select>
      </div>
    );
  }
}

export default Select;

Para saber quais itens eu irei pegar para cada comboBox, crio um outro componente passando os valores que eu preciso dentro desse comboBox:

import React, { Component } from ‘react’;

import Select from './Select';

import ServiceApi from '../../services/ServiceApi';

export default class ComboBoxEndereco extends Component {

  constructor(props) {

    super(props);

    this.state = {

      option: [],

    }

  }

  componentDidMount() {

    ServiceApi.ListarEndereco()

      .then((list) => {

        this.setState({

          option: list

        });

        // console.log('Endereço: ' + JSON.stringify(list))

      })

      .catch((err) => { console.log(err) }

      );

  }

  render() {

    return (

      <div >

        <Select dados={this.state.option} nome="Endereço" idSelect="endereco"

          selectedValue={this.props.selectedValue} onChange={this.props.onChange}

          defaultValue={this.props.defaultValue} />

      </div >

    );

  }

}

Agora eu faço um map nesse comboBox

{
          this.state.item.map((item, _id) => {
            return (
              <form id="formulario" onSubmit={this.onSubmit} key={item._id} >
                <hr />
                <div className="row">
                  <ComboBoxEndereco onChange={this.onChangeCombo}
                    selectedValue={item.enderecos._id} />

Quando eu passo o meu selectedValue como item.enderecos._id ele mostra o valor selecionado, porém ele não permite que eu mude esse valor, meu onChangeCombo está

onChangeCombo = (e) => {

        e.preventDefault();

        // this.setState({ [e.target.id]: e.target.value });

        var index = e.nativeEvent.target.selectedIndex;

        if (e.target.id === "endereco") {

          this.setState({

            "_id_endereco": e.target.value,

            "endereco": e.nativeEvent.target[index].text

          });

        }

        if (e.target.id === "departamento") {

          this.setState({

            "_id_departamento": e.target.value,

            "departamento": e.nativeEvent.target[index].text

          });

        }

        if (e.target.id === "categoria") {

          this.setState({

            "_id_categoria": e.target.value,

            "categoria": e.nativeEvent.target[index].text

          });

        }

       }
Criado 20 de dezembro de 2019
Ultima resposta 26 de dez. de 2019
Respostas 11
Participantes 2