muiSlider restrict for certaing range - javascript

i'm usign below Mui Slider component
for a UI where i have to restrict it's value for certaing range. For example slider's ball will not dragable after 50. user can select values upto 50 but it will show it full range. i didn't found any direct solution so i figured out a bypass with Discrete Slider Values. here's the code sandbox link ,Where i have make a array of full available values. Is there any neat and clean solution ?
<Slider
size="small"
defaultValue={30}
aria-label="Small"
valueLabelDisplay="auto"
/>

Hello Fazlay Rabbi it's so simple you need just think out of the box, just need to write simply if condition I write your solution in blow :
import React, { useState } from "react";
import Box from '#mui/material/Box';
import Slider from '#mui/material/Slider';
export default function DiscreteSliderLabel() {
const [sliderValue, setSliderValue] = useState(0);
const handleChange2 = (event, newValue) => {
if (newValue > 50){
setSliderValue(50);
}else{
setSliderValue(newValue);
}
};
return (
<Box sx={{ width: 300 }}>
<Slider
value={sliderValue}
aria-label="Always visible"
onChange={handleChange2}
valueLabelDisplay="on"
/>
</Box>
);
}

I think you have to determine max value for yor slider like below
<Slider
...
max={50}
min={0}
/>
And i see your code and i think you can determine marks array for just labels not all values

Related

How to remove value from state?

I need simple functionality: show Button when value is more than 0. And for this I use code below.
I created some Text Fields with similar states (4) and I don't understand why only in 3rd this didn't work.
My code:
export default function TextFields() {
...
const [showButton3, setShowButton3] = useState("");
...
const handleChange = (event) => {
setShowButton3(event.target.value);
console.log("value is:", event.target.value);
};
return (
<InputOutlined
type={"text"}
id={"text3"}
name={"text3"}
value={showButton3}
onChange={handleChange}
leftElement={
<Img
width={36}
height={36}
radius={12}
src={
"https://images.unsplash.com/photo-1665174271625-178021f8b1a5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1160&q=80"
}
/>
}
rightElement={
showButton3 ? (
<IconButton
icon={<MdClose size={24} />}
variant={"surface"}
type="reset"
onClick={() => setShowButton3("")}
></IconButton>
) : null
}
>
Your name
</InputOutlined>
)}
I have checked Component, here I add some text
And when I want to clear value, I get this
You can see, value is cleared. But I still see it in my input. How to fix that? Or maybe I doing something wrong?
Proof:
This is very similar Components. I changed id, but I don't understand why value isn't removed. Maybe I need to use useRef or useId. But I have 4 different inputs and only 1 have this issue.

Antd Segmented: Set tabindex=-1 to the internal Input component

I'm using the Segmented component by Ant Design. My application has some component like this:
...
import EmployeeCard from './EmployeeCard';
import ContractorCard from './ContractorCard';
function MyComponent() {
const [cardType, setCardType] = useState('Employee');
...
function changeCard(value) {
setCardType(value);
}
return (
...
<Segmented
options={['Employee', 'Contractor']}
onChange={changeCard)
value={cardType}
tabIndex={-1}
/>
{cardType === 'Employee'
? <EmployeeCard />
: <ContractorCard />
}
...
);
}
The EmployeeCard and ContractorCard have some input components in them that I want to be part of the overall tab flow on the page. However, I don't want the Segmented buttons themselves to be part of it. I set tabIndex={-1} on the Segmented component in order to take it out of the tab-flow, but apparently, internally, that component includes an Input component, which still has the default tabIndex={0}. I cannot figure out how to reach that component in order to set its tab index to -1.

React Mui TextField for currency input - how to permit enter digits only in iPhone Safari browser

I have a Mui TextField component for currency input and I made it to show numeric keyboard only in Safari Browser.
But when the user tries to paste literal string into the field, I'd like to prevent it and make it sure that allows enter currency number inputs only.
import { TextField } from '#mui/material';
export default function CustomCurrencyTestScreen(props){
const [amount, setAmount] = useState('');
const handleChange = e => {
setAmount(e.target.value);
}
const handleBlur = e => {
//some validation functionalities
}
return (
<TextField
size="small"
id="amount"
name="amount"
onChange={handleChange}
onBlur={handleBlur}
inputProps={{
style:{
fontSize:14,
}
inputMode:'numeric',
}}
InputProps={{
startAdornment: (
<InputAdornment position="start">
$
</InputAdornment>
),
endAdornment:(
<InputAdornment position='end'>
{
Boolean(amount) &&
<CancelRounded size="small" color="grey" sx={{padding:0}} onClick={()=>
setAmount('')}/>
}
</InputAdornment>
),
}}
/>
);
}
It shows numeric keyboard successfully in Safari browser, however, when you paste the literal string into the field, the field shows it.
How can I prevent user not to input or paste other characters than numbers(float value also)?
I tried with CurrencyInput and IMaskInput, but there's a problem in implementing startAdornment and endAdornment, so I don't prefer it.
Is there any solution to implement Currency Input with Adornment in Mui, working correctly in Safari Browser?
I don't think there's any way to prevent an actual paste, but you could use a useEffect on amount, and strip out all non-numeric characters:
useEffect(() => {
function hasNonNumeric(s) {
// return true if has non numeric
}
function stripNonNumeric(s) {
// logic here that returns a string with non-numeric chars stripped
}
if(hasNonNumeric(amount)) {
setAmount(stripNonNumeric(amount))
}
}, [amount])
That being said, I probably wouldn't recommend doing it, I hate when websites mess with stuff I paste. Rather, I'd recommend having validation, and showing an error if it contains non-numeric allowing the user to fix it on their terms.
You can add onPaste handler to your TextField component so that you can implement your logic within this function.
const handleOnPaste = e => {
//do whatever you want with the pasted value
//add your logic here
}
<TextField
...
onPaste={handleOnPaste}
...

Material UI React Slider Component Not Working on mobile

I have been trying to add Slider component to a react project. functionality wise its working fine but i am having two issues which i am not able to get rid of
changing value of the slider is not smooth. Dragging doesn't work properly, its just drags to the nearest value and then stops.
On a mobile device its even worse, no dragging at all, i have to tap on the exact spot for the slider to move.
I did find the issue, i was using onChange, so when i removed it it worked exactly like the example. But i need to update state of parent component, so added line 18, but then again the same issue appeared. I fi remove line 18 then all this gets fixed but i need line 18 to call a function of parent component, to update its state variable.
Here is the gist link of my code
https://gist.github.com/kapiljhajhria/0e9beda641d561ef4448abf9195dbcca
import React from "react";
import Slider from "#material-ui/core/Slider";
export default function SliderWithLabel(props) {
const {
labelText, range = {
min: 0,
max: 10
}, step = 1,
// defaultValue = Math.ceil((range.min + range.max) / 2),
handleSliderChange,
name,
value: sliderValue
} = props;
function sliderValuetext(value) {
// handleChange({target: {value: value}});
if(value!==sliderValue)handleSliderChange(value,name)
return `${value}`;
}
return (
<div className="sliderField" style={{display: "flex", flexDirection: "column"}}>
<div>
{labelText}
</div>
<Slider
style={{width: "90%", justifyContent: "center", display: "flex", margin: "auto"}}
defaultValue={sliderValue}
getAriaValueText={sliderValuetext}
aria-labelledby="discrete-slider"
valueLabelDisplay="auto"
// onChange={sliderChange}
step={step}
// name={name}
// onChange={handleChange}
marks
min={range.min}
max={range.max}
/>
</div>
)
}
after spending 2 days on the issue, creating a sample project , trying to recreate the issue , it turned out to be a simple fix.
Parent component has a FORM, key which i was using for the form was
Date().getTime()
This was what was causing the issue with the slider. My guess would be that it was rebuilding the whole form with each slider value change. Which made slider UI behave in such a way. using appropraite key fixed the issue. I am now switching between two key value.

Cursor moves to end of input when tooltip in react

I am trying to build an input field where it accepts time as an input here is my code
<InputMask
mask="99:99"
onBlur={handleOnBlur}
onChange={(e) => {
const text = e.target.value
setInputValue(text)
setValueValid(true)
const fixedText = text.replace(/:/g, '')
if (onChange) {
onChange({
...e,
target: {
...e.target,
value: fixedText,
},
})
}
}}
//value={inputValue}
{...rest}
>
{(inputProps) => (
<Tooltip
open={!valueValid}
placement="bottom-start"
title="Ops Wrong Time Format!"
>
<StyledInput
{...inputProps}
autoFocus={rest.autoFocus}
className={rest.className}
onKeyDown={(e) => {
if (e.keyCode === 13) {
checkTimeFormat(inputValue)
if (valueValid) {
if (rest.onBlur) rest.onBlur(e)
e.target.blur()
if (onSubmit) {
const fixedText = inputValue.replace(/:/g, '')
onSubmit({
...e,
target: {
...e.target,
value: fixedText,
},
}, fixedText)
}
}
}
}}
/>
</Tooltip>
)}
</InputMask>
)
I am trying to use InputMask to set the correct format and to make sure only numbers are used as an input. I would like to display a tooltip if the time is not an acceptable time (eg/ 75:89, 99:78...etc) So everything seems to be working and I am able to see the tooltip if i type in something invalid, however, I am not able to get rid of a strange behavior where the cursor always ends up at the end of the input box after any sort of change... I have searched online for an answer but it seems that nothing was of much help. Note that if I remove the tooltip component wrapping my custom input (StyledInput) then everything turns back to normal (cursor stops where the user is currently modifying).
At first I thought this was a rendering issue so I tried commenting out the hooks
setInputValue(text)
setValueValid(true)
and even tried to remove the toggle for the tooltip
open={!valueValid}
but it seems that the tooltip is what's causing the issue... does anyone have any idea how to solve this? Any recommendations or reference to a doc would be of great help!
Here is the sandbox code:
https://codesandbox.io/s/wandering-frost-0dy78
If you put the Tooltip around the entire InputMask element (rather than around the input inside InputMask) it works fine. I haven't taken the time to fully understand why the Tooltip causes issues in the previous location (which would require digging deeper into the internals of InputMask to understand how it manages cursor position), but it isn't surprising to me that it causes issues there.
Below is a modified version of your sandbox:
import React, { useState, useEffect } from "react";
import Tooltip from "#material-ui/core/Tooltip";
import InputMask from "react-input-mask";
import "./styles.css";
export default function App() {
const [inputValue, setInputValue] = useState("value");
const [valueValid, setValueValid] = useState(true);
const checkTimeFormat = time => {
const [hour, minute] = time.split(":");
if (parseInt(hour, 10) > 23 || parseInt(minute, 10) > 59) {
setValueValid(false);
}
};
return (
<Tooltip
open={!valueValid}
placement="bottom-start"
title="Ops Wrong Time Format"
>
<InputMask
mask="99:99"
//beforeMaskedValueChange={beforeMaskedValueChange}
onChange={e => {
const text = e.target.value;
setInputValue(text);
setValueValid(true);
const fixedText = text.replace(/:/g, "");
}}
value={inputValue}
//{...rest}
>
{inputProps => (
<input
{...inputProps}
//autoFocus={rest.autoFocus}
//className={rest.className}
onSubmit={checkTimeFormat(inputValue)}
onKeyDown={e => {
if (e.keyCode === 13) {
if (valueValid) {
console.log("Value is valid");
}
}
}}
/>
)}
</InputMask>
</Tooltip>
);
}

Categories