I am using TextField that field data I am adding into the table that works fine what my task is I have one field called Total no of count their I am storing my data count so whenever I add data into the table it will be based on the count, mean like example if I have count 3 then I am able to use count max 3 or if I want to divide that count with a different name that also works only max count I used whatever present in Total no of count or after dividing count with a user name I need to update remaining count in that field or whatever count is present after added into a table showing remaining count when I use all count in one time or add it to the table that works fine mean Total no of count get subtracted with table data count and remain 0 but when I divide that count into 2 or 3 names field mean by 1 by 1 then it will not work properly mean count not get subtracted properly
In this method, I am subtracting and setting the remaining count
const totalRemainingCount =
totalUsers -
Number(
AssignSearchesForm.values.countAssigned ||
teamdata?.map((data) => data.countAssigned)
);
export default function App() {
const [teamdata, setTeamData] = React.useState([]);
const AssignSearchesForm = useFormik({
initialValues: {
selectName: "",
selectAge: "",
location: "",
countAssigned: ""
},
validationSchema,
onSubmit: (values, formikHelper) => {
setTeamData([values, ...teamdata]);
formikHelper.resetForm();
}
});
let filteredArray = nameList.filter(
(e) => !teamdata.some((data) => data.selectName === e.selectName)
);
const handleChange = (e) => {
const selectedName = e.target.value;
const name = nameList.find((data) => data.selectName === selectedName);
const newOptions = Object.values(name).reduce((optionList, key) => {
optionList.push({ value: key, label: key });
return optionList;
}, []);
AssignSearchesForm.setFieldValue("selectName", selectedName);
AssignSearchesForm.setFieldValue("selectAge", newOptions[1]?.value || "");
AssignSearchesForm.setFieldValue("location", newOptions[2]?.value || "");
};
const totalUsers = 3;
const totalRemainingCount =
totalUsers -
Number(
AssignSearchesForm.values.countAssigned ||
teamdata?.map((data) => data.countAssigned)
);
return (
<div className="App">
<Card color="primary" variant="outlined">
<CardHeader
title={
<Typography variant="subtitle1">
Total no of count ={" "}
{totalRemainingCount <= 0 ? 0 : totalRemainingCount}
</Typography>
}
/>
<Divider />
<CardContent>
<Grid container direction="row" spacing={1}>
<Grid item xs={4}>
<TextField
sx={{ minWidth: 185 }}
select
id="outlined-basic"
label="Select Name"
name="selectName"
size="small"
onChange={handleChange}
value={AssignSearchesForm.values.selectName}
error={
AssignSearchesForm.errors.selectName &&
AssignSearchesForm.touched.selectName
}
helperText={
AssignSearchesForm.touched.selectName &&
AssignSearchesForm.errors.selectName
}
>
{filteredArray?.map((option) => (
<MenuItem key={option.selectName} value={option.selectName}>
{option.selectName}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={4}>
<TextField
id="outlined-basic"
label="location"
name="location"
size="small"
{...AssignSearchesForm.getFieldProps("location")}
error={
AssignSearchesForm.touched.location &&
AssignSearchesForm.errors.location
}
helperText={
AssignSearchesForm.touched.location &&
AssignSearchesForm.errors.location
}
/>
</Grid>
<Grid item xs={4}>
<TextField
id="outlined-basic"
label="Select Age"
name="selectAge"
size="small"
{...AssignSearchesForm.getFieldProps("selectAge")}
error={
AssignSearchesForm.errors.selectAge &&
AssignSearchesForm.touched.selectAge
}
helperText={
AssignSearchesForm.touched.selectAge &&
AssignSearchesForm.errors.selectAge
}
/>
</Grid>
<Grid item xs={4}>
<TextField
id="outlined-basic"
label="Count Assign"
name="countAssigned"
size="small"
type="number"
{...AssignSearchesForm.getFieldProps("countAssigned")}
error={
AssignSearchesForm.errors.countAssigned &&
AssignSearchesForm.touched.countAssigned
}
helperText={
AssignSearchesForm.touched.countAssigned &&
AssignSearchesForm.errors.countAssigned
}
/>
</Grid>
<Grid item xs={4}>
<Button
onClick={() => {
AssignSearchesForm.handleSubmit();
}}
variant="contained"
>
Add
</Button>
</Grid>
</Grid>
</CardContent>
</Card>
<Table teamdata={teamdata} />
</div>
);
}
CodeSandBox Link
You need to update your logic for the way you are calculating the count:
const totalRemainingCount =
totalUsers -
(parseInt(
AssignSearchesForm.values.countAssigned
? AssignSearchesForm.values.countAssigned
: 0,
10
) + teamdata?.reduce((partialSum, a) => partialSum + a.countAssigned, 0));
You were getting NaN because the data you were trying to use for subtraction was not the number. Here, I am doing the sum of countAssigned in the table and adding it with the form data that will allow you to get the right value.
Here is an example:https://codesandbox.io/s/preset-ranges-antd-4-19-2-forked-kczd1y?file=/App.js:1838-2095
What I have understood so far is that the Total count is not setting properly. If this is the case then you need to set state of count when you click add button, so that it stores the countAssigned value. Also using the max property in TextField to limit the count to remaining value.
I have edited your codesandbox example.
Related
There are several filters on my site (by date, duration, and so on). Accordingly, from a large amount of data, the user can find what he needs
There is also a "reset all filters" button that resets all filters and returns the full list of products.
However, with one of the filters, I ran into a problem: in this filter, I use a TextField from the mui. And the problem is that the values themselves, by which the desired products are filtered, are discarded, and what the user entered in the field remains unchanged.
I will give an example: The user filters only by this field. Having received any result, he wants to return to the original list and presses the "reset all filters" button. All filters are reset and the original list is returned, but the data entered in the field remains, that is, the field itself is not cleared.
Help solve the problem
const MAX_DURATION = 9999999
export default function FilterDuration() {
const [minDuration, setMinDuration] = useState(0);
const [maxDuration, setMaxDuration] = useState(MAX_DURATION);
useEffect(() => {
updatedFilters.durationRange = { min: minDuration, max: maxDuration }
setFilters(updatedFilters)
if (maxDuration === 0) {
setMaxDuration(MAX_DURATION)
}
}, [minDuration, maxDuration])
return (
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<div style={{ width: "120px" }}>
<TextField
onInput={(e) => {
const newValue = Number(e.target.value)
if (newValue )
setMinDuration(newValue)
}} />
</div>
</div>
);
}
Add a value prop to your TextField which has the minDuration like this:
<TextField
type='number'
size="small"
margin="dense"
label="From"
value={minDuration}
onInput={(e) => {
e.target.value = Math.max(0, parseInt(e.target.value)).toString().slice(0,7)
const newValue = Number(e.target.value)
if (newValue <= maxDuration && newValue >= 0 && newValue <= MAX_DURATION)
setMinDuration(newValue)
}} />
You want the value of the TextField to be managed by the state of your component. Add a value attribute and set it to the current value of minDuration:
<TextField
...
value={minDuration}
/>
I have input feild which takes a input (interest) from user and after hitting the Enter key adds the interest to the interests array. Then the elements in this array are displayed on screen via the Domain component as the user goes on adding. The Domain component contains an icon X (cross) which on click should delete the selected/clicked element from the array. Right now the last element in the array is getting removed after clicking.
How can I resolve this? Here is the code:
function Demo() {
const [interest, setinterest] = useState("");
const [interests, setinterests] = useState([]);
const domainSelection = (e) => {
if (e.key === "Enter" && interest.length > 0) {
setinterests((interests) => [...interests, interest]);
setinterest("");
}
};
const RemoveDomain = (e) => {
var arr = [...interests];
var index = arr.indexOf(e.target.value);
arr.splice(index, 1);
setinterests(arr);
};
const Domain = ({ interest }) => {
return (
<span>
{interest}
<span>
<X onClick={RemoveDomain} />
</span>
</span>
);
};
return (
<div>
<Input
name="intersts"
type="text"
placeholder="eg Machine Learning .. "
value={interest}
required={true}
onChange={(e) => setinterest(e.target.value)}
className="interest-input inputs"
onKeyDown={domainSelection}
/>
{interests.map((interest, i) => (
<Domain
interest={interest}
// Prevent duplicate keys by appending index:
key={interest + i}
/>
))}
</div>
);
}
export default Demo;
I think e.target.value is undefined.
Use Filter, This might help
const RemoveDomain = (value) => {
var arr = interests.filter((item) => item !== value);
setinterests(arr);
};
const Domain = ({ interest }) => {
return (
<span>
{interest}
<span>
<X onClick={() => RemoveDomain(interest)} />
</span>
</span>
);
};
Within my reactjs class component, I want to create a button that opens a new text area everytime I click on it (e.g., when I click 5 times on it, it should open 5 textareas). In the current result, it only opens a textarea ones.
Thus, In a first step, I created a state with value 0 and create a function that should change the state:
// InitialState
state = {
value: 0,
};
onChange() {
this.setState({
value: this.state.value + 1,
});
}
In the next step, I rendered a button and created if-statements to show the textareas (which does not work):
render() {
return (
<div>
<IconButton onClick={this.onChange.bind(this)}>
<AddCircleOutlineIcon />
</IconButton>
<br />
{this.state.value >= 1 ? this.showTextArea() : null}
</div>
);
}
And this is my showTextArea function:
showTextArea = () => {
return (
<textarea
placeholder={this.state.placeholder}
value={this.state.value}
onChange={this.onChange1.bind(this)}
rows="2"
style={{ fontSize: "18px" }}
onFocus={(e) => (e.target.placeholder = "")}
onBlur={(e) => (e.target.placeholder = this.state.placeholder)}
/>
);
};
You condition is wrong. this.state.value >= 1 It should be like this because after first textbox opens and you click your button value will be 2 and first textbox will hide
This can be achieved using only single condition. Change your render method like this with for loop:
render() {
return (
<div>
<IconButton onClick={this.onChange.bind(this)}>
<AddCircleOutlineIcon />
</IconButton>
<br />
{
for (let i = 0; i < this.state.value; i++) {
{this.showTextArea()}
}
}
</div>
);
}
Ok so I have been trying this for a moment and I don't know how to go about it, what I want is simple, generate a brand new form but with a react transtion group effect from the old form to the new form (everytime a user clicks the submit button)
you are a lifesaver if you can provide help or a thought.
this.state.transitionTimes I tried to increment a state key maybe watch that but it doesn't work
<div disabled={currentAccommodation.isLoading || currentRoom.isLoading} className="accommodation_popup_innerContainer_inputContainer_transition_container">
<SwitchTransition>
<CSSTransition
key={this.state.isAddRoom}
addEndListener={(node, done) =>
node.addEventListener('transitionend', done, false)
}
classNames="fade"
>
{(isAddRoom || this.state.isAddRoom) === true ? (
<CreateRoomForm
ScrollBar={ScrollBar}
LabelInput={LabelInput}
currentState={this.state}
handleChange={() => this.handleChange}
removeItem={this.removeItem}
handleMultipleChange={this.handleMultipleChange}
setTheState={this.setTheState}
error={this.state.error}
/>
) : ( // I want the transition on this side
<cssTransition
key={this.state.transitionTimes}
addEndListener={(node, done) =>
node.addEventListener('transitionend', done, false)
}
classNames="fade">
<CreateAccommodationForm
ScrollBar={ScrollBar}
LabelInput={LabelInput}
currentState={this.state}
handleChange={() => this.handleChange}
removeItem={this.removeItem}
handleMultipleChange={this.handleMultipleChange}
setTheState={this.setTheState}
OnChangeDescription={this.OnChangeDescription}
error={this.state.error}
/>
</cssTransition>
)}
</CSSTransition>
</SwitchTransition>
</div>
submit buttons
<Button
type="submit"
className="btn accommodation_popup_innerContainer_buttons_button"
value={isAddRoom ? 'Add' : 'Submit'}
onClick={
(isAddRoom || this.state.isAddRoom)
? this.handleAddRoomBtn // for the top form
: this.handleSubmitBtn // for th bottom form
}
/>
My submit button
handleAddRoomBtn = async (e) => {
e.preventDefault();
await this.setState({
...this.initiaState,
transitionTimes: this.state.transitionTimes + 1
})
console.log(this.state)
};
We need user to enter only numbers and it should have a maximum length of say 3.
How can we accomplish this in material ui ?
<TextField
id="score"
label="score"
className={classes.textField}
name="totalScore"
margin="normal"
defaultValue={score}
/>
We want only numeric values here
Try this...
<TextField
id="score"
label="score"
name="totalScore"
style={style.filedStyle}
inputProps={{ min: 3, max: 3}}
/>
Actually this is the way it works, you have input type as number. so, you can apply max attribute but it will validate not limit the input numbers, Checkout this thread.
The workaround is to apply oninput and count the length. like this
onInput={(e)=>{
e.target.value = Math.max(0, parseInt(e.target.value) ).toString().slice(0,3)
So your textinput would look like
<TextField type="number"
className="text-field-amount"
onInput={(e)=>{
e.target.value = Math.max(0, parseInt(e.target.value) ).toString().slice(0,2)
}}
min={0}
/>
Demo
Use controlled input, and update state only if the input is number.
ex:
state will be like this
this.state={
score: 0
}
create a function to handle change in text field.
handleChange(e){
//update state here with value from TextField.
}
and your textfield will look like this.
<TextField
id="score"
label="score"
className={classes.textField}
name="totalScore"
margin="normal"
value={this.state.score}
onChange={this.handleChange.bind(this)}
/>
<TextField
id="score"
label="score"
className={classes.textField}
name="totalScore"
margin="normal"
defaultValue={score}
/>
you can do this with Jquery
$('#score').keypress(function(e){
var code = (e.which) ? e.which : e.keyCode;
if($('#' + e.target.id).val().length > 2)
e.preventDefault();
if (code > 31 && (code < 48 || code > 57)) {
e.preventDefault();
}
});
<TextField
id="number"
placeholder="Enter Number"
type="number"
value={state.count}
onChange={(event) => {
const regex = /^([0-9]){minLength,maxLength}$/;
if (event.target.value === '' || regex.test(event.target.value)) {
setState({ ...state, count: event.target.value });
}
}}
variant="outlined" />
number + length restriction
<TextField
value={phone}
onChange={event => setPhone(event.target.value)}
variant="outlined"
placeholder={'Phone number'}
type={'number'}
onInput={(e)=>{e.target.value = Math.max(0, parseInt(e.target.value)).toString().slice(0,10)}}
min={0}
/>