Reputation: 71
I'm working on React.js
project.
I wanna create 3 Text Fields where:
1st Text Field - I want to insert only hexadecimal values. It should accept the numbers from 0-9 & letters from A-F & colon. It should accept only 23 chars(numbers, letters from A-F & colon).
2nd Text Field- It should only Hexadecimal values.
3rd Text Field- It should accept only Alpha Numeric values (only Numbers &
letters).
4th Text Field- Only Letters.
Note: Special Characters should not be accepted.
Please help me out to solve this.
Sample Code:
constructor(props) {
super(props);this.state = {showModal: true};
this.modalFooter = this.modalFooter.bind(this);
this.modalBody = this.modalBody.bind(this); this.updateState = this.updateState.bind(this);
};
modalFooter() {
return (
<div>
<BButton name="Cancel" onClickHandler={() => { this.setState({ showModal: false }) }} />
</div>);
}
modalBody() {
return (
<div>
<br className="Class">
<br> Hex Value: <input type="text" className="Class" formnovalidate="return isNumber(event)"
maxLength="23" placeholder="" /></br>
<br> Addr: <input type="text" className="Class" maxLength="6" name=""
placeholder="" /></br><br> Name: <input type="text" className="Class" id="Number"
maxLength="64"
name="" placeholder="" /></br>
</br>
</div>
);
}
updateState(e) {
this.setState({data: e.target.value});
}
render() {
let body = this.modalBody();
let footer = this.modalFooter();
let modal = <BModal header="Add Message"
body={body}
footer={footer} />
return (
<div className="page-title">
<center>
<h3> Sample Program </h3>
</center>
<hr className="horizontal-line"></hr>
<div> <font color="grey"><input type="text" value={this.state.data}
onClick={() => { this.setState({ showModal: true }) }} /></font>
{this.state.showModal ? modal : ""}
</div>
</div>);
}
Upvotes: 7
Views: 40015
Reputation: 130065
Below is a working demo of a complete highly-generic Input
component which has its smarts by utilizing the HTML5 pattern attribute and blocking undesired content according to the regular expression defined in the pattern
prop:
const Input = (props) => {
const onKeyPress = e => {
// normalize the pattern as a Regular expression
const pattern = props.pattern instanceof RegExp ? props.pattern : new RegExp(props.pattern)
// if the currently typed character is not in the regular expression, do not allow it (to be rendered)
// if the length of the input will exceed, do not allow
if( !pattern.test(e.key) || e.target.value.length + 1 > (props.max||Infinity))
e.preventDefault()
// if also has "onKeyPress" prop, fire it now
props.onKeyPress && props.onKeyPress(e)
}
// prevent invalid content pasting
const onPaste = e => {
// get the pattern with midifications for testig a whole string rather than a single character
const pattern = props.pattern instanceof RegExp ? props.pattern : new RegExp(`^${props.pattern}+$`)
// get pasted content as string
const paste = (e.clipboardData || window.clipboardData).getData('Text')
// vaildate
if( !pattern.test(paste) || paste.length > (props.max||Infinity))
e.preventDefault()
// if also has "onPaste" prop, fire it now
props.onPaste && props.onPaste(e)
}
return <input {...props} onKeyPress={onKeyPress} onPaste={onPaste} />
}
ReactDOM.render((
<form>
<Input pattern="[0-9a-fA-F:]" max={6} placeholder="Only HEXA & colon, up to 6 chars"/>
<Input pattern="[0-9a-fA-F]" placeholder="Only HEXA"/>
<Input pattern="[0-9a-zA-Z]" placeholder="Only Alphanumeric"/>
<Input pattern="[a-zA-Z]" placeholder="Only (Latin) Letters"/>
<Input placeholder="Everything allowed"/>
</form>)
, root)
input{
display: block;
width: 220px;
margin: 5px;
padding: 5px;
}
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>
Upvotes: 0
Reputation: 22862
Actually, it's not complicated at all. You only need to take care of extracting allowed characters from text input, limit its length, ... To be honest, this is not related to React in any way - it's pure Javascript.
Let's begin with simple function which extracts substring from string by pattern
const extract = (str, pattern) => (str.match(pattern) || []).pop() || '';
// Usage
extract("01az", "[0-9a-fA-F]+") // "01a"
Then, wrap this function into functions which solve pattern problems for 1, 2, 3 and 4
const extractHexadecimalWithColon = (str) => extract(str, "[0-9a-fA-F:]+");
const extractHexadecimal = (str) => extract(str, "[0-9a-fA-F]+");
const extractAlphanum = (str) => extract(str, "[0-9a-zA-Z]+");
const extractAlpha = (str) => extract(str, "[a-zA-Z]+");
It super easy to limit length of string
const limitLength = (str, length) => str.substring(0, length);
Then, create your text inputs components, listen for changes and update state as required.
var App = React.createClass({
getInitialState() {
return {};
},
setA(e) {
this.setState({
a: limitLength(extractHexadecimalWithColon(e.target.value), 23),
});
},
setB(e) {
this.setState({
b: extractHexadecimal(e.target.value),
});
},
setC(e) {
this.setState({
c: extractAlphanum(e.target.value),
});
},
setD(e) {
this.setState({
d: extractAlpha(e.target.value),
});
},
render() {
return (
<div>
<div>
Hexadecimal, max 23 chars, colon allowed<br/>
<textarea value={this.state.a} onChange={this.setA} />
</div>
<div>
Hexadecimal only, no length restriction<br/>
<textarea value={this.state.b} onChange={this.setB} />
</div>
<div>
Alphanumeric<br/>
<textarea value={this.state.c} onChange={this.setC} />
</div>
<div>
Letters only<br/>
<textarea value={this.state.d} onChange={this.setD} />
</div>
</div>
)
}
});
Full working fiddle here https://jsfiddle.net/69z2wepo/36536/
Original solution split into separate components https://jsfiddle.net/69z2wepo/36654/
Upvotes: 4
Reputation: 1111
I suggest you to use React onKeyPress
event with regexp verifications (see example below and the jsbin link)
var Form = React.createClass({
firstMethod(e) {
const re = /[0-9A-F:]+/g;
if (!re.test(e.key)) {
e.preventDefault();
}
},
secondMethod(e) {
const re = /[0-9A-F]+/g;
if (!re.test(e.key)) {
e.preventDefault();
}
},
thirdMethod(e) {
const re = /[0-9a-fA-F]+/g;
if (!re.test(e.key)) {
e.preventDefault();
}
},
fourthMethod(e) {
const re = /[a-fA-F]+/g;
if (!re.test(e.key)) {
e.preventDefault();
}
},
render() {
return (
<form>
<input ref="first" onKeyPress={(e) => this.firstMethod(e)} />
<input ref="second" onKeyPress={(e) => this.secondMethod(e)} />
<input ref="third" onKeyPress={(e) => this.thirdMethod(e)} />
<input ref="fourth" onKeyPress={(e) => this.fourthMethod(e)} />
</form>
);
}
});
ReactDOM.render(
<Form />,
document.getElementById('example')
);
http://jsbin.com/juyakaqawe/edit?html,js,output
Upvotes: 20