The points are:
when I enter any number in input so % sign add after the digit.
when I delete all numbers, % sign remove and width reset according entering the value.
if number already come from the api so when i click then my focus before % sign .
number <=100
so my functionality is working fine, but the problem is i am using multiple events (onClick, KeyPress, keyUp, onBlur etc) , so how i manage this functionality
<div className={`form-control valbox1 dvPercValue`} disabled = {isDisabled ? true : false } onClick={event=>this.focusPerc(event, rowIndex)}>
<Textbox
onTextboxChange={e => this.onTextboxChange(e, rowIndex)}
name="percentage"
isDisabled={isDisabled}
value={(value) }
maxLength={4}
refData={(input) => {
this.myAllocat[rowIndex] = input
}}
className = "percValue"
onInputKeyPress= {event=> this.setWidth(event, rowIndex) }
onInputkeyUp={ event=> this.setInputValue(event, rowIndex)}
textBoxWidth= { textBoxWidth }
/>
{ value && <span className="percSign ">%</span> }
</div>
const textBoxWidth = {
width: (value && parseInt(value,10) < 101) ? ((value.length ) * 8) : 0
};
focusPerc =(e, rowIndex) => {
if (rowIndex >=0) {
let searchInput= null;
const allBox = document.querySelectorAll(".dvPercValue");
for (let i=0;i<allBox.length;i++) {
allBox[i].classList.remove("active");
}
if (e.target && e.target.tagName) {
if (e.target.tagName.toLowerCase() === 'span' || e.target.tagName.toLowerCase() === 'input') {
e.target.parent.classList.add("active");
searchInput= e.target.parent.children[0];
} else {
e.target.classList.add("active");
searchInput = e.target.children[0]
}
}
if (searchInput) {
const strLength = searchInput.value.length * 2;
searchInput.focus();
searchInput.setSelectionRange(strLength, strLength);
}
}
}
setInputValue = (e, rowIndex) => {
const inputvalue=e.target.value.trim();
if (e.keyCode ===8 && rowIndex >=0) {
if (parseInt(inputvalue,10) > 100) {
return;
}
e.target.style.width = ((inputvalue.length ) * 8) + 'px';
}
}
setWidth =(e, rowIndex) => {
const inputval=e.target.value.trim();
if (parseInt(inputval,10) > 100) {
return;
}
e.target.style.width = ((inputval.length + 1) * 8) + 'px';
}
const TextboxComponent = (props) => {
return (
<input type="text
value= {props.value}
name= {props.name}
maxLength= {props.maxLength}
className={props.className}
disabled= {props.isDisabled}
placeholder= {props.placeHolder}
onChange={props.onTextboxChange}
onKeyPress = {props.onInputKeyPress}
onBlur = {props.onTextBoxBlur}
ref={props.refData}
autoComplete="off"
onKeyUp = {props.onInputkeyUp}
style = { props.textBoxWidth }
/>
)
}
For optimizing your ReactJS code you can firstly divide it into clear components and subsequently work on their functionality
So say you want add/remove a class "active" to your element so that you can highlight the field that the user is currently focused on this can be done as following:
<input
type="text"
className="simple"
onFocus={e => (e.target.classList += " active")}
onBlur={e => (e.target.className = "simple")}
/>
Which will help you avoid the current approach (which I guess is like jQuery) where you first capture all the elements and then loop over them.
Similarly if you want to capture the whole input of the user and then replace % sign for the deleted characters you can use a state for your component updating it through onChange.
If it is simply about showing a % sign after your input you can continue with your own code value && <span className="percSign ">%</span>
Related
When I click on the button, if the value of the button is 0, then the text will not show in that space. I mean, how can it be done without showing -10?
console.log(variable)
The this is the error I'm getting ..
const Mobile = () => {
const [charge, setCharge] = useState(20)
const setMobileCharge = () => setCharge(charge - 10)
if (setMobileCharge === 0) {
return 0;
}
return (
<div>
<h3>Charge : {charge}</h3>
<button onClick={setMobileCharge}>Battery down</button>
</div>
);
};
export default Mobile;
this happens because the react "ticks" your render is not fully synced with the state ... so to prevent that you can set the new state like that
setCharge(oldCharge => oldCharge -10 )
you can add a condition like below,
const Mobile = () => {
const [charge, setCharge] = useState(20)
const setMobileCharge = () => {
if(charge > 0) setCharge(charge - 10)} //here
if (setMobileCharge === 0) {
return 0;
}
return (
<div>
<h3>Charge : {charge === 0 ? "" : charge}</h3> //here
<button onClick={setMobileCharge}>Battery down</button>
</div>
);
};
I'm don't quite understand your question.
But if you want when 0 not to decrease, you can :
const setMobileCharge = () => {
if (charge > 0) {
setCharge(charge - 10)
}
}
If you want when 0 Mobile component disappear you can:
if (charge === 0) {
return 0;
}
I want to prevent negative values ( < 0) to be chosen on input field. Being "0" the lowest value available for the input field.
Here is the javascript and html code:
// Button functions
const minusButton = document.getElementById('minus');
const plusButton = document.getElementById('plus');
const inputField = document.getElementById('amount');
minusButton.addEventListener('click', event => {
event.preventDefault();
const currentValue = Number(inputField.value) || 0;
inputField.value = currentValue - 0.01;
});
plusButton.addEventListener('click', event => {
event.preventDefault();
const currentValue = Number(inputField.value) || 0;
inputField.value = currentValue + 0.01;
});
// Returning 0 when clearing input
const numInputs = document.querySelectorAll('input[type=number]')
numInputs.forEach(function(input) {
input.addEventListener('change', function(e) {
if (e.target.value == '') {
e.target.value = 0
}
})
})
<button class="input-btn" id="minus">−</button>
<button class="input-btn" id="plus">+</button>
<input class="input" type="number" value="0" id="amount"/>
Your code is almost correct.
In the minusButton event handler logic, you can enforce that the value never gets set to anything lower than 0.
Edit the input event handler to check for values lower than 0, not equal to it.
Note: the event handler you add to input to fire upon 'change' only gets executed when the user manually makes the change to the value of input box, and NOT when it gets changed by code (as you're doing through minusButton and plusButton). Since, the user clicks the button (and never interact with the input directly), the event happens on the button, not the input box.
You can give below code a try.
// Button functions
const minusButton = document.getElementById("minus");
const plusButton = document.getElementById("plus");
const inputField = document.getElementById("amount");
minusButton.addEventListener("click", (event) => {
event.preventDefault();
const currentValue = Number(inputField.value) || 0;
// if less than 0, set to 0, else currentValue - 0.01
inputField.value = currentValue - 0.01 < 0 ? 0 : currentValue - 0.01;
});
plusButton.addEventListener("click", (event) => {
event.preventDefault();
const currentValue = Number(inputField.value) || 0;
inputField.value = currentValue + 0.01;
});
// Returning 0 when clearing input
const numInputs = document.querySelectorAll('input[type="number"]');
numInputs.forEach((input) => {
input.addEventListener("change", function (e) {
if (e.target.value === "" || e.target.value < 0) {
e.target.value = 0;
}
});
});
If you were using a submit button and the input box was in a form element, you could have used the min attribute
<input class="input" type="number" value="0" id="amount" min="0" />
This would be the ideal front-end way of doing it.
You could use JavaScript too, but it can be disabled by the user.
You should, however, check this value (validation) when it gets submitted, before you use it because even this can be bypassed.
let newValue = currentValue - 0.01
if(newValue < 0) {
newValue = 0
}
inputField.value = newValue
I made a component to format phone number from XXXXXXXXXX to '(XXX) XXX-XXXX'
here is my code
function formatPhoneNumber(phone) {
const area = phone.slice(0, 3);
const first = phone.slice(3, 6);
const second = phone.slice(6, 10);
let formattedTelephoneNumber = phone;
if (phone.length >= 1) {
formattedTelephoneNumber = `(${formattedTelephoneNumber}`;
}
if (phone.length >= 4) {
formattedTelephoneNumber = `(${area}) ${first}`;
}
if (phone.length >= 7) {
formattedTelephoneNumber = `(${area}) ${first}-${second}`;
}
return formattedTelephoneNumber;
}
function getRawPhoneNumber(inputValue) {
return [...inputValue].filter((char) => /\d/.test(char)).join("");
}
export default function App() {
const [value, setValue] = useState("");
const handleInputChange = (e) => {
const phoneNumber = getRawPhoneNumber(e.target.value);
const formatted = formatPhoneNumber(phoneNumber);
setValue(formatted);
};
return (
<div className="App">
<input value={value} onChange={handleInputChange} />
</div>
);
}
It works ok but when you are typing in the middle of a string - either add an extra number or delete one number, the cursor will jump to the end.
Does anyone know how to fix it?
here is a live demo you can play with
https://codesandbox.io/s/phone-number-format-x4nnk?file=/src/App.js
Hello,
I know its not recommended to use jQuery with react & I am aware of method on react for changing CSS of element but here I am just trying to see if my req can be achieved or not , all i want is to change the colour of li element when corresponding tick icon is clicked for it, I am using a jQuery code
const markdone = () => {
let c = $("#ll")
console.log(c)
$(c).closest("li").css("background-color", "green");
};
but when i am clicking the css gets applied but not on its corresponding li element in my case for ex have attached image when i click on 3 tick icon css gets changed for 1 is there any way i can fix it
attaching whole code below
check markdone function for making css change :
const [input, setValue] = useState("");
const [todos, setTodos] = useState([]);
// passing entered
const handleInput = (event) => {
setValue(event.target.value);
};
const lp = (event) => {
// let c = [1,2,34,55]
event.preventDefault();
// if no input nothing will happen return none
if (!input) return;
// using spread operator its used whenever we need to add array data to exiting array
const newTodos = [...todos, input];
setTodos(newTodos);
// clearing input text
setValue("");
};
const handeldel = (index) => {
// console.log(index)
todos.splice(index, 1);
setTodos([...todos]);
// const newTodos = todos.splice(index, 1);
// setTodos([...newTodos]);
};
const [line, setline] = useState(false);
// const [ll, setll] = useState(false);
const markdone = () => {
let c = $("#ll")
console.log(c)
$(c).closest("li").css("background-color", "green");
};
useEffect(() => {
$(document).ready(function() {
$("#pk").click(function(e) {
// e.preventDefault();
alert('hello')
});
});
});
return ( <
div >
<
h1 id = "pk"
className = "text-center font-weight-bolder alert-info mb-5" >
Tasks To Do < i class = "fas fa-clipboard-list text-success" > < /i> <
/h1> <
div class = "input-group mb-3 container" >
<
input className = "form-control border-primary font-weight-bold"
style = {
{
height: 60
}
}
placeholder = "Enter Text here"
type = "text"
value = {
input
}
onChange = {
handleInput
}
/> <
div class = "input-group-append" >
<
button className = "input-group-append font-weight-bolder "
style = {
{
fontSize: 20
}
}
onClick = {
lp
} >
{
" "
} <
i class = "fas fa-plus-square fa-2x p-2" > < /i>{" "} <
/button> <
/div> <
/div> {
todos.map((x, index) => ( <
ol style = {
{
listStyle: "outside"
}
}
className = "container" >
<
li className = "font-weight-bolder table-bordered text-capitalize alert-secondary "
style = {
{
fontSize: 30,
textDecoration: line ? "line-through" : "none",
// backgroundColor: ll ? "Chartreuse" : "none",
}
} >
{
x
} <
i class = "fas fa-check-circle float-md-right text-success"
id = "ll"
onClick = {
markdone
} >
< /i>{" "} <
i class = "fas fa-trash-alt text-danger float-md-right"
onClick = {
() => handeldel(index)
} >
< /i> <
/li> <
/ol>
))
}
{ /* for future ref */ } {
/* <div >
{data.map((user) => (
<div className="user">{user.id + " " + user.name
}</div>
))}
</div> */
} <
/div>
I suppose using a Ref should do the trick, as Refs provide a way to access DOM nodes or React elements created in the render method.
Just put it on the element you'd like to style using jQuery and access it with RefName.current
IDs must be unique
You do not need jQuery, just delegation
Plain JS - there are other ways in React
I am assuming .input-group-append is the container
document.querySelector(".input-group-append").addEventListener("click",function(e) {
const tgt = e.target;
if (tgt.classList.contains("text-success")) {
tgt.closest("li").style.backgroundColor = "green";
}
})
I have a simple input that I'm using an keyup event listener on. If the input length is too short, the span element will remove the class on it that hides the element and display "Input too short".
If I have multiple inputs, how can I only enable the Submit button if all fields pass the validation.
Unfortunately, I'm thinking in a React-way and would accomplish this via state.
<style type="text/css">
.hide-first {
display: none;
}
.hide-last {
display: none;
}
</style>
<div>
<div>
<input id="first-name" />
<span id="validation-span" class="hide-first">Input too short</span>
</div>
<button>Submit</button>
</div>
<script type="text/javascript">
let firstName = document.getElementById( 'first-name' );
let span = document.getElementById( 'validation-span' );
firstName.addEventListener( 'keyup', () => {
console.log( event.target.value.length )
if ( event.target.value.length < 5 ) {
span.classList.remove( 'hide-first' )
} else {
span.classList.add( 'hide-first' )
}
} );
</script>
All your inputs could call the same validation function that checks everything except inputs that are empty. Only show the submit button if they all succeed and show the appropriate message on inputs that fail the validation.
Pseudo-code:
boolean succes = true
if username is invalid and not empty
username invalid message
success = false
if password is invalid and not empty
password invalid message
success = false
if success is true
show submit button
At first add style your button style="display:none". You can use jQuery as bellow
$( document ).ready( function () {
var _rules = {
"first-name": function ( $owner ) {
var val = $owner.val();
if ( !val ) return false;
if ( val.length < 5 ) return false;
return true;
}
};
//Validate here
function validate(total_mark) {
var mark = 0;//total mark
//Read all input value, than check rules
$( 'input' ).each( function () {
if ( 'function' !== typeof ( _rules[this.id] ) ) return;
var $owner = $( this );
var result = _rules[this.id]( $owner );
if ( !result ) {
mark -= 1;
$owner.next().removeClass( 'hide-first' );
return;
}
$owner.next().addClass( 'hide-first' );
mark += 1;
return;
} );
return mark;
};
var $btn = $( 'button' );
//Register keyup event for all input
var total_input = 1;
$( 'input' ).on( "keyup", function ( e ) {
e.preventDefault();
$btn.css( "display", "none" );
if ( validate() < total_input ) return;
$btn.css( "display", "" );
} );
} );
Something like this should work
<div>
<div>
<input id="first-name" onchange='validation()'/>
<span id ="validation-span" class="hide-first">Input too short</span>
</div>
<button id='submit-button'>
Submit
</button>
</div>
<script type="text/javascript">
function validateFirstName() {
let firstName = document.getElementById('first-name');
let span = document.getElementById('validation-span');
if (event.target.value.length < 5) {
span.classList.remove('hide-first')
return True
}
span.classList.add('hide-first')
return False
}
function validation() {
let submitButton = document.getElementById('submit-button');
submitButton.disabled = validateFirstName();
}
</script>
As you add additional fields, you should create the validation function for that field, and then running it inside validation() like:
function validation() {
let submitButton = document.getElementById('submit-button');
submitButton.disabled = validateFirstName() && validateSecondField() && validateThirdField() &&...;
}
Remember to add to the html input the onchange event listener.
Simple logic. Make a function that checks if all of the fields are validated, and call it from within the onkeyup event. A seemingly straight-forward way would be like this:
let firstName = document.getElementById('first-name'),
lastName = document.getElementById('last-name'),
company = document.getElementById('company-name');
let span = document.getElementById('validation-span'),
span1 = document.getElementById('validation-span1'),
span2 = document.getElementById('validation-span2'),
conditions = [],
length = 3;
firstName.addEventListener('keyup', () => {
console.log(event.target.value.length)
if (event.target.value.length < 5) {
span.classList.remove('hide-first')
conditions[0] = true;
} else {
span.classList.add('hide-first')
conditions[0] = false;
}
})
lastName.addEventListener('keyup', () => {
console.log(event.target.value.length)
if (event.target.value.length < 5) {
span1.classList.remove('hide-first')
conditions[1] = true;
} else {
span1.classList.add('hide-first')
conditions[1] = false;
}
})
company.addEventListener('keyup', () => {
console.log(event.target.value.length)
if (event.target.value.length < 5) {
span2.classList.remove('hide-first')
conditions[2] = true;
} else {
span2.classList.add('hide-first')
conditions[2] = false;
}
})
function checkAllTrueAndActivateSubmitBtn() {
var result = true;
for(var i = 0; i < length; i++) {
if(!conditions[i]) {
result = false;
}
}
if(result) {
submitBtn.classList.add("shown"); //or whatever
}
}
but of course, the more fields you have,the more messy this becomes. A more efficient way would be to use an array for the fields, and conditions:
let IDsAndConditions = {
'first-name':{
condition: (x) => x.length >= 5,
span: 'validation-span'
},
'last-name': {
condition: (x) => x.length >= 8,
span: 'validation-span-lastName'
},
'phoneNumber':{
condition: (x) => x.match(/^-{0,1}\d+$/),//or whatever
span:"phone-span"
}
};
var conditions = [];
var num = 0;
for(var k in IDsAndConditions) {
var cur = IDsAndConditions[k];
var el = document.getElementById(k);
var span = document.getElementById(cur["span"]);
if(el && span) {
el.addEventListener('keyup', () => {
console.log(event.target.value.length)
if (!cur["condition"](event.target.value)) {
span.classList.remove('hide-first')
conditions[num] = true;
} else {
span.classList.add('hide-first')
conditions[num] = false;
}
checkAllTrueAndActivateSubmitBtn();
});
} else {
conditions[num] = true; //this is to make the validation work even if the element doesn't exist
}
num++;
}
function checkAllTrueAndActivateSubmitBtn() {
var result = true;
for(var i = 0; i < IDsAndConditions.length; i++) {
if(!conditions[i]) {
result = false;
}
}
if(result) {
submitBtn.classList.add("active"); //or whatever
} else {
submitBtn.classList.remove("active"); //even if it was active at one point, if someone changes a field to an incorrect value, it deactivates again
}
}