4

I have TextField Select Material UI components based on a certain number of value in a variable.

{this.state.selectedNextHops.map((nextHop, index) => (
              <div>
                <TextField
                    select
                    className="vnfprofile-field"
                    InputProps={{ className: 'variable-value site-details-view-textfield' }}
                    InputLabelProps={{ shrink: true }}
                    SelectProps={{
                        MenuProps: {
                            className: 'vnf-designer-value',
                            getContentAnchorEl: null,
                            anchorOrigin: {
                                vertical: 'bottom',
                                horizontal: 'left',
                            }
                        },
                    }}
                    value = {this.state.selectedNextHops[index] || ''}
                    disabled={this.props.newPopoverPanelView === 'VIEW' ? true : false}
                    onChange={(e) => this.handleChange('nexthop', e)}
                  >
                    {this.state.remainingNextHops.length !== 0 ? this.state.remainingNextHops.map((option, i) => (
                        <MenuItem key ={i} value = {option || ''}>
                          {option}
                        </MenuItem>
                      )) :
                        <MenuItem value = {'No Data Available'}>
                            {'No Data Available'}
                        </MenuItem>}
                  </TextField>
                  <TextField
                    className="vnfprofile-field subnet-textfield"
                    InputProps={{ className: 'variable-value' }}
                    InputLabelProps={{ shrink: true }}
                    value = {'29'}
                  />
                </div>
                ))
          }

The TextFields show up sequentially when I select value from the previous dropdown and filters the menu based on previous selection.

if(selectedNextHops.indexOf(event.target.value) === -1) {
            selectedNextHops.push(event.target.value);
        }
        remainingNextHops = this.props.nextHopSapds.filter(nextHop => selectedNextHops.indexOf(nextHop) === -1);

this.setState({
            selectedNextHops: selectedNextHops,
            remainingNextHops: remainingNextHops
        });

Update: Here is my handleChange Method ->

handleChange(type, event) {
    let selectedNextHops = JSON.parse(JSON.stringify(this.state.selectedNextHops));
    let remainingNextHops = [];
    if(type === 'nexthop') {
        selectedNextHops = selectedNextHops.filter(nh => nh !== '');
        isContentChanged = true;
        if(selectedNextHops.indexOf(event.target.value) === -1) {
            selectedNextHops.push(event.target.value);
        }
        remainingNextHops = this.props.nextHopSapds.filter(nextHop => selectedNextHops.indexOf(nextHop) === -1);
        if(remainingNextHops.length !== 0) {
            selectedNextHops.push('');
        }
        this.setState({
            selectedNextHops: selectedNextHops,
            remainingNextHops: remainingNextHops
        });
    }
  }

The state is updating fine, but the textfield does not display the selected value. I have tried everything I knew. Any help is appreciated.

vjeta
  • 1,178
  • 2
  • 11
  • 18
  • Please share your `handleChange` method. Why is there a `value = {'29'}` prop? – Dupocas May 02 '19 at 23:09
  • I always want to show 29 in that field – vjeta May 02 '19 at 23:23
  • 1
    A [CodeSandbox](https://codesandbox.io/s/new) reproducing your issue would make it much easier to provide assistance. – Ryan Cogswell May 03 '19 at 15:07
  • @Katamari could you please create demo on Code Sandbox as suggested by Ryan. Otherwise it is really difficult to help you guys here. – maximus ツ Aug 29 '19 at 15:44
  • @maximus https://codesandbox.io/embed/priceless-dijkstra-oqxzi I tried to boil both mine and OP's issue down to a simple version, value state is being set but not visible – Katajun Aug 29 '19 at 17:21
  • @Katamari target values used to set state/select input are not correct. Check this corrected codesanbox demo https://codesandbox.io/s/great-lumiere-dgmyf You can fetch additional value per menu item using `event.currentTarget.dataset` in even handler. – maximus ツ Sep 02 '19 at 08:29

2 Answers2

5

This is hard to debug without seeing a working snippet or the state ( especially this.state.selectedNextHops) , but based on the code sandbox provided ( in the comment ) , I assume it's the same problem, so this answer will apply to the sandbox code :

this.setState({
  selectedID: event.target.value.id,
  visibleValue: event.target.value.name
});

event.target.value.id and event.target.value.name are undefined,

console.log(console.log(event.target)) // {value: "S0002", name: undefined}

For the select to display a selected option, the value attribute for both need to match :

<select value="2">
        ^^^^^^^^^
  <option value="1">first value</option>
  <option value="2">second value</option>
          ^^^^^^^^^ 
</select>

in the example in the code sandbox, the value of the Select is value={this.state.visibleValue} and the values of the options are value={x.label}

Since this.state.visibleValue is always undefined, you'll never see the value of the select update.

A quick fix for this is to change the handleChage function to :

handleChangeTest = event => {
  this.setState({
    selectedID: event.target.id,
    visibleValue: event.target.value
  });
};

but that will leave selectedID undefined , to set it, add the attribute id={x.id} to the option and use event.currentTarget to get its value :

{this.state.data.map(x => (
  <MenuItem key={x.id} value={x.label} id={x.id}>
                                      ^^^^^^^^^
    {x.name}
  </MenuItem>
))}

And

handleChangeTest = event => {    
  this.setState({
    selectedID: event.currentTarget.id,
                ^^^^^^^^^^^^^^^^^^^^^^
    visibleValue: event.target.value
  });
};

Working SandBox

Taki
  • 17,320
  • 4
  • 26
  • 47
3

So you try to access the key with e.target.value.id but the target object has only the value and not the id itself. That is why it is undefined after you call the handleChange method. There is a way to access the key though:

The callback does not only pass the event but also the child object as second parameter and this can be used to get the key like this:

handleChangeTest = (event, child) => {
    this.setState({
      selectedID: child.key,
      visibleValue: event.target.value
    });
  };

This will set the key as selectedID and the value of the selected item as visibleValue.

halfer
  • 19,824
  • 17
  • 99
  • 186
Domino987
  • 8,475
  • 2
  • 15
  • 38