Reputation: 57
I came across a validation scenario in React js in which the validation must happen on the single row rather than all the rows present.
I am hereby providing an screenshot in which I am adding wrong value of External port and Its displaying an error message on all the rows present,
Below is the code which I have written inside map,
<div className="tab-data-cointainer">
<div className="tab-data-section">
<div className="content-section port-farwarding">
<p className="small-title">Port forwarding for single static Public IP</p>
<div className="port-layout">
<div className="port-row">
<div className="port-column">
<span>Enable</span>
</div>
<div className="port-column">
<span>Protocol</span>
</div>
<div className="port-column">
<span>External ports</span>
</div>
<div className="port-column">
<span>Port to IP address</span>
</div>
<div className="port-column">
<span>Forward to port</span>
</div>
<div className="port-column"></div>
</div>
{
this.state.portForwardSettings && this.state.portForwardSettings.map((portForwardSettingsIterate, index) => {
if (null != portForwardSettingsIterate) {
return (
<React.Fragment>
<div className="port-row">
<div className="port-column">
<span className="responsive-label">Port 1:</span>
<label className={portForwardSettingsIterate.enabled ? "mark-label active" : "mark-label"}>
<input className="mark-check" type="checkbox" checked={!!portForwardSettingsIterate.enabled} onChange={(e) => this.checkboxHandler(e, index)} />
<svg focusable="false" aria-hidden="true" className="icon"><use xlink="http://www.w3.org/1999/xlink" href="#icon-tick"></use></svg>
</label>
</div>
<div className="port-column column-select">
<span className="responsive-label">Protocol</span>
<select value={portForwardSettingsIterate.protocol} onChange={(e) => this.selectProtocolDropDownHandler(e,index)}>
<option value="TCPUDP">TCP/UDP</option>
<option value="TCP">TCP</option>
<option value="UDP">UDP</option>
</select>
<svg focusable="false" aria-hidden="true" className="icon"><use xlink="http://www.w3.org/1999/xlink" href="#icon-chevron-down"></use></svg>
</div>
<div className="port-column">
<span className="responsive-label">External ports</span>
<input type="text" className="inputPort externalPorts" placeholder="65535" value={portForwardSettingsIterate.externalPort} onChange={(e) => this.externalPortChangeHandler(e,index)} />
{ !this.state.isExternalPortValid && <span className="field-error">Please enter valid values</span> }
</div>
<div className="port-column">
<span className="responsive-label">Port to IP address</span>
<input type="text" className="inputPort portIP" placeholder="123.456.789.123" value={portForwardSettingsIterate.internalClientIpAddress} onChange={(e) => this.internalIPAddressChangeHandler(e,index)} />
{ !this.state.isInternalClientIPAddressValid && <span className="field-error">Please enter valid values</span>}
</div>
<div className="port-column">
<span className="responsive-label">Forward to port</span>
<input type="text" className="inputPort forwardingIP" placeholder="65535" value={portForwardSettingsIterate.internalClientPort} onChange={(e) => this.internalClientPortChangeHandler(e,index)} />
{ !this.state.isInternalClientPortValid && <span className="field-error">Please enter valid values</span> }
</div>
<div className="port-column">
<label className="delete-label">
<input className="delete-check" type="checkbox" />
<svg onClick={() => this.deletePortSetting(index)} focusable="false" aria-hidden="true" class="icon" automationid="PortForwarding_Svg_DeleteIcon_1">
<use xlink="http://www.w3.org/1999/xlink" href="#icon-delete"></use>
</svg>
</label>
</div>
<div className="port-column">
</div>
</div>
</React.Fragment>
)
}
})
}
<a className="btn-add-port" onClick={() => this.addNewPortHandler()}>+ Add new port</a>
{/* <p className="max-port-msg">Maximum ports have been added</p> */}
</div>
</div>
<div className="section-btn-row">
<div className="btn-group">
<a>CANCEL</a>
<a className={this.state.portUpdateDisabled}>UPDATE</a>
</div>
</div>
</div>
</div >
externalPortChangeHandler = (e,index) => {
let temp_arr = JSON.parse(JSON.stringify(this.state.portForwardSettings))
let temp_object = temp_arr[index];
temp_object.externalPort = e.target.value;
this.setState({ portForwardSettings: temp_arr });
if(PortForwardConstants.PORT_RANGE.test(e.target.value)){
this.setState({ isExternalPortValid: true });
}
else{
this.setState({ isExternalPortValid: false });
}
}
There is an option given to user for adding the rows - so there is no fixed size row and managing Its validation to particular row is difficult. Can anyone have Idea to manage It?
Upvotes: 3
Views: 134
Reputation: 1037
You can add validation for each object of the array. I changed it for the ExternalPort, you can do the same for other columns.
<div className="tab-data-cointainer">
<div className="tab-data-section">
<div className="content-section port-farwarding">
<p className="small-title">Port forwarding for single static Public IP</p>
<div className="port-layout">
<div className="port-row">
<div className="port-column">
<span>Enable</span>
</div>
<div className="port-column">
<span>Protocol</span>
</div>
<div className="port-column">
<span>External ports</span>
</div>
<div className="port-column">
<span>Port to IP address</span>
</div>
<div className="port-column">
<span>Forward to port</span>
</div>
<div className="port-column"></div>
</div>
{
this.state.portForwardSettings && this.state.portForwardSettings.map((portForwardSettingsIterate, index) => {
if (null != portForwardSettingsIterate) {
return (
<React.Fragment>
<div className="port-row">
<div className="port-column">
<span className="responsive-label">Port 1:</span>
<label className={portForwardSettingsIterate.enabled ? "mark-label active" : "mark-label"}>
<input className="mark-check" type="checkbox" checked={!!portForwardSettingsIterate.enabled} onChange={(e) => this.checkboxHandler(e, index)} />
<svg focusable="false" aria-hidden="true" className="icon"><use xlink="http://www.w3.org/1999/xlink" href="#icon-tick"></use></svg>
</label>
</div>
<div className="port-column column-select">
<span className="responsive-label">Protocol</span>
<select value={portForwardSettingsIterate.protocol} onChange={(e) => this.selectProtocolDropDownHandler(e,index)}>
<option value="TCPUDP">TCP/UDP</option>
<option value="TCP">TCP</option>
<option value="UDP">UDP</option>
</select>
<svg focusable="false" aria-hidden="true" className="icon"><use xlink="http://www.w3.org/1999/xlink" href="#icon-chevron-down"></use></svg>
</div>
<div className="port-column">
<span className="responsive-label">External ports</span>
<input type="text" className="inputPort externalPorts" placeholder="65535" value={portForwardSettingsIterate.externalPort} onChange={(e) => this.externalPortChangeHandler(e,index)} />
{ !portForwardSettingsIterate.isExternalPortValid && <span className="field-error">Please enter valid values</span> }
</div>
<div className="port-column">
<span className="responsive-label">Port to IP address</span>
<input type="text" className="inputPort portIP" placeholder="123.456.789.123" value={portForwardSettingsIterate.internalClientIpAddress} onChange={(e) => this.internalIPAddressChangeHandler(e,index)} />
{ !this.state.isInternalClientIPAddressValid && <span className="field-error">Please enter valid values</span>}
</div>
<div className="port-column">
<span className="responsive-label">Forward to port</span>
<input type="text" className="inputPort forwardingIP" placeholder="65535" value={portForwardSettingsIterate.internalClientPort} onChange={(e) => this.internalClientPortChangeHandler(e,index)} />
{ !this.state.isInternalClientPortValid && <span className="field-error">Please enter valid values</span> }
</div>
<div className="port-column">
<label className="delete-label">
<input className="delete-check" type="checkbox" />
<svg onClick={() => this.deletePortSetting(index)} focusable="false" aria-hidden="true" class="icon" automationid="PortForwarding_Svg_DeleteIcon_1">
<use xlink="http://www.w3.org/1999/xlink" href="#icon-delete"></use>
</svg>
</label>
</div>
<div className="port-column">
</div>
</div>
</React.Fragment>
)
}
})
}
<a className="btn-add-port" onClick={() => this.addNewPortHandler()}>+ Add new port</a>
{/* <p className="max-port-msg">Maximum ports have been added</p> */}
</div>
</div>
<div className="section-btn-row">
<div className="btn-group">
<a>CANCEL</a>
<a className={this.state.portUpdateDisabled}>UPDATE</a>
</div>
</div>
</div>
</div >
externalPortChangeHandler = (e,index) => {
let portForwardSettings = [...this.state.portForwardSettings]
let temp_arr = JSON.parse(JSON.stringify(this.state.portForwardSettings))
let temp_object = temp_arr[index];
temp_object.externalPort = e.target.value;
this.setState({ portForwardSettings: temp_arr });
if(PortForwardConstants.PORT_RANGE.test(e.target.value)){
//this.setState({ isExternalPortValid: true });
portForwardSettings[index].isExternalPortValid = true;
}
else{
portForwardSettings[index].isExternalPortValid = false;
//this.setState({ isExternalPortValid: false });
}
this.setState({portForwardSettings})
}
Upvotes: 4