How to populate a dropdown menu in React - javascript

I am trying to populate my dropdown with the value of testType but it is not showing up. Is there something I am missing? When I print the data being sent, it is correct but it's not displaying in the actual dropdown menu. I don't want this to be populated everytime - only when the user clicks edit criteria (not for add question).
I'm currently testing it for criteriaNum = 1 so the dropdown should display testType = 'Visual Check'.
This is my EditQuestionnaire.js:
export const PureEditQuestionnaire = ({
criteriaNum,
criteriaFields,
image,
isSaving,
testType,
onFieldChange,
onClickSave,
getInputValue,
getDropdownValue,
}) => (
<>
<Header
tabIndex="-1"
isAddCriteria={!!criteriaNum}
onClickSave={onClickSave}
isSaving={isSaving}
isOnTop={true}
/>
<CategoryContainer>
<p>
Fields with <span style={{ color: "red" }}>*</span> are required
</p>
{criteriaFields.map((field) => (
<FieldContainer key={field.name}>
<label htmlFor={field.name.replaceAll(" ", "-")} className="fields">
{field.name}
</label>
{field.type === "input" ? (
<TextField
id={field.name.replaceAll(" ", "-")}
value={getInputValue(field.name)}
fullWidth={true}
required={true}
placeholder={"Enter the " + field.name}
multiline={field.name === "Description" && true}
rows={field.name === "Description" ? 4 : 0}
onChange={(event) =>
onFieldChange(field.name, event.target.value)
}
/>
) : field.type === "dropdown" ? (
<>
{/* <label htmlFor={field.name}>Select the {" " + field.name}</label> */}
<div id={field.name.replaceAll(" ", "-") + "-desc"}>
Select the {" " + field.name}
</div>
<select
id={field.name.replaceAll(" ", "-")}
aria-describedby={field.name.replaceAll(" ", "-") + "-desc"}
value={field}
onChange={(event) =>
onFieldChange(field.name, event.target.value)
}
>
<option selected disabled>
{/* Select a {" " + field.name} */}
</option>
{field.fields.map((field) => (
<option key={field} value={field}>
{field}
</option>
))}
</select>
</>
) : (
<ImageDropbox
id={field.name.replaceAll(" ", "-")}
image={image}
imageFieldName={field.name}
onImageChange={onFieldChange}
/>
)}
</FieldContainer>
))}
</CategoryContainer>
<CategoryContainer>
<h1>Answers</h1>
<AnswerTable />
</CategoryContainer>
<Header
onClickSave={onClickSave}
isSaving={isSaving}
isOnTop={false}
isAddCriteria={!!criteriaNum}
/>
</>
)
This is the getDropdownValue I'm exporting from my PureEditQuestionnaire:
const getDropdownValue = (fieldName) => {
switch (fieldName) {
case "Test Type":
return criteriaValues.testType
case "Capability":
return criteriaValues.capability
default:
return ""
}
}

Double-check you usage of the select and option element. I'm also not sure what's the object type of field.
Hopefully this helps:
How to use select option in react js?

Related

Focus next input field after maxLength is full. React.js

Hi I am having a problem with my for and inputs. I have 6 inputs with maxLength = 1 and i want to focus next input when when value is entred.
<Form
form={form}
className={styles.form}
onFinish={onFinish}
initialValues={initialValues}
>
<div className={styles.labeContainer}>
<LabelField name="code">
{({ value, onChange }) => {
return (
<div>
{inputsArr.map((_, index) => (
<Input
key={index}
maxLength={1}
defaultValue={value[index]}
className={styles.codeInput}
onChange={(val) => {
onChange(
value.substring(0, index) +
val.target.value +
value.substring(index + 1)
);
}}
/>
))}
</div>
);
}}
</LabelField>
</div>
</Form>
I was trying to use something with refs but i had no idea how to get this working. Also did some reseasrch on this, but nothing helped. I am using rc-field-form but docs are very vage

React How to clear all input values from infinite inputs list?

I'm coding a infinite inputs component to add bill items in a page, so the user can add how many items row as he wants. But now I have a crucial problem, when I click on "cancel" button for clean all the inputs and show just 1 row of items I show the previous state of this first row. How can I clear all the inputs and then show the placeholder in the first row of items? Thanks
PrincipalComponent.tsx:
type BillingManualProps = LinkStateProps & LinkDispatchProps;
const BillingManual: React.FC<BillingManualProps> = ({...}) => {
return (
<>
<section className="entity__main-container">
<div className="billing-manual-items-to-bill">
<h2 className="billing-title-row">Indique los ítems a facturar:</h2>
<BillingItems
selectedShipper={selectedShipper}
selectedShipperSettings={selectedShipperSettings}
billItems={billItems}
setOpenBillItem={setOpenBillItem}
setUpdateBillItem={setUpdateBillItem}
setNewBillItem={setNewBillItem}
setRemoveBillItem={setRemoveBillItem}
/>
</div>
<div className="billing-manual-shadow">
{billItems && (
<IonLabel
className="shipper_document_add_new_document button-border"
onClick={() => setNewBillItem()}
>
+ NEW ITEM
</IonLabel>
)}
</div>
<div className="billing-manual__buttonsGroup">
<GalaxyButton
color="medium"
className="GalaxyButton"
onClick={() => {
resetPropsFn();
}}
>
CANCEL
</GalaxyButton>
</div>
</section>
</>
);
};
resetProps action:
export const resetPropsFn = () => {
return async (dispatch: Dispatch) => {
dispatch(billingManualSlice.actions.resetPropsFn());
};
};
resetProps Slice:
resetPropsFn: (state) => {
return {
...state,
isFetching: false,
selectedShipper: null,
selectedShipperSettings: null,
billItems: [
{
item: null,
amount: null,
},
],
};
},
Billin child component:
<div className="billing-manual-scroll">
{!!billItems &&
billItems.map((document, id) => {
return (
<div key={id} className="billing-manual-items-container">
<IonRow className="input-delete-container" key={id}>
<IonCol className="billing-manual-column" size="6">
<IonItem style={{ marginTop: 4 }}>
<IonLabel color="primary" position={'stacked'}>
Ítem {id + 1}*
</IonLabel>
<TextField
name={'item'}
defaultValue={null}
id="billing-item-input"
variant="standard"
fullWidth={true}
disabled={
!(!!selectedShipper && !!selectedShipperSettings)
}
placeholder={'Indique el ítem a facturar'}
value={document.item ? document.item : null}
onChange={(event: any) => {
setUpdateBillItem(
id,
ValuesType.ITEM,
event.target.value
);
}}
/>
</IonItem>
</IonCol>
<IonCol className="billing-manual-column" size="6">
<IonItem style={{ marginTop: 4 }}>
<IonLabel color="primary" position={'stacked'}>
Monto*
</IonLabel>
<TextField
name={'amount'}
defaultValue={null}
style={{ backgroundColor: '#F5F5F5' }}
fullWidth={true}
type={'number'}
disabled={
!(!!selectedShipper && !!selectedShipperSettings)
}
placeholder={'0.00'}
value={
!!selectedShipper && !!selectedShipperSettings
? document.amount
: null
}
onChange={(event: any) => {
setUpdateBillItem(
id,
ValuesType.AMOUNT,
event.target.value
);
}}
InputProps={{
type: 'search',
startAdornment: (
<InputAdornment position="start">
{' '}
<AttachMoney fontSize={'small'} />
</InputAdornment>
),
}}
/>
</IonItem>
</IonCol>
</IonRow>
</div>
);
})}
</div>
You can set all the input states/hooks to empty string after completing the desired action

Changes are made in all selections, instead of the one I choose

Changes are made in all selections, instead of the one I choose. When I check the checkbox in one selection, all the others change. Changing How can I change that?
applications should change the name to the name of the marked checkbox in each selected selection. However, it changes in all the selections I have.
const handleSelect = (e,id) => {
let newValue = [1];
if (e.target.value.length) {
newValue = e.target.value.filter((item) => {
return item > 1;
});
}
const finalString = newValue
.reduce((acumulatedFinal, pass) => {
return acumulatedFinal + ", " + exportOptionNames[pass - 1];
}, "")
.replace(",", "")
.trim();
setSelectedSelections(finalString.length ? finalString : "Export Option");
setExportOption(newValue);
};
<FormControl }>
<Select onClick={(e)=> e.stopPropagation()}
labelId="label"
id="select"
value={exportOption}
multiple
onChange={(e) => handleSelect (e, item.id)}
key={item.id}
renderValue={() => {
return selectedOptionNames;
}}
input={<BootstrapInput />}
>
<MenuItem value={1} disabled>
Export Report
</MenuItem>
<MenuItem value={2}>
<Checkbox checked={exportOption.includes(2)} />
<ListItemText>{exportOptionNames[1]}</ListItemText>
</MenuItem>
<MenuItem value={3}>
<Checkbox checked={exportOption.includes(3)} />
<ListItemText>{exportOptionNames[2]}</ListItemText>
</MenuItem>
<MenuItem value={4}>
<Checkbox checked={exportOption.includes(4)} />
<ListItemText>{exportOptionNames[3]}</ListItemText>
</MenuItem>
</Select>

Jsx Component not showing after conditional checks

The problem is I have two redux stores
items(Items Store
quotationItems(Quote Items.
When a product item is added to quotationItems I Would to show <RedButton title="Remove" /> or when the quotationItems is empty the <AddButton title="Add" /> should be shown.
using if statement tends to re-render the component and adds new components e.g: After adding a new product to quotation items, there will be a new <AddButton /> in FlatList Component.
interface IProps {
items: ItemInterface[];
documentItems: ItemInterface[];
onAddItem: any;
}
const ItemFlatList2: FC<Partial<IProps>> = ({
items,
documentItems,
onAddItem,
}) => {
const TestView = (itemCode) => {
documentItems.map((x) => {});
};
return (
<FlatList
data={items}
keyExtractor={(item) => item.itemCode.toString()}
renderItem={({
item: { itemCode, itemDescription, itemSellingPrice },
}) => {
return (
<div className={styles.itemContainer}>
<h4>Item Code: {itemCode}</h4>
<h4>Description: {itemDescription}</h4>
<div>
{documentItems.map((x) => {
x.itemCode === itemCode ? (
<RedButton title={"Remove"} key={itemCode} />
) : (
<AddButton title={"Add"} key={itemCode} />
);
})}
</div>
</div>
);
}}
/>
);
};
Other options I've tried:
I've also tried this, still doesn't work, the buttons will show up but after clicking on the first button, which will successful add the product item to quotation item store but when I try and click on the 2nd or 3rd button of `<AddButton title={'Add'} key={itemCode} /> I get no response.
<div>
{documentItems.length <= 0 ? (
<AddButton
title={"Add"}
key={itemCode}
onClick={() => onAddItem(itemCode)}
/>
) : (
documentItems!.map((x) =>
x.itemCode === itemCode ? (
<RedButton title={"Remove"} key={itemCode} />
) : (
<
AddButton title={"Add"} key={itemCode} onClick={() => onAddItem(itemCode)} />
)
)
)}
</div>
This is the result of the modified code above:
Please add the return keyword.
documentItems.map((x) => {
return (x.itemCode === itemCode ? (
<RedButton title={"Remove"} key={itemCode} />
) : (
<AddButton title={"Add"} key={itemCode} />
);
)})
Or Just remove the curly braces.
documentItems.map((x) => (x.itemCode === itemCode ? (
<RedButton title={"Remove"} key={itemCode} />
) : (
<AddButton title={"Add"} key={itemCode} />
)))
Based on the updations that you did in the questions. It is an issue with the data in "documentItems". Since you only need 1 button per item code. Instead of map use find. It will return 1 item and fix this duplicacy.

Formik FieldArray nested object validations with Yup

https://codesandbox.io/s/wonderful-brattain-928gd
Above, I have added some sample code of the problem I am trying to figure out. I am not sure how to map the errors to the correct items in the FieldArray.
In the example, there are yes/no radio buttons which allow a user to indicate whether they have foods they want to add. If they select 'yes', the food options appear and they must select at least 1 of the foods and enter its expiration date to fully validate.
I am trying to add an "expiration" validation error when the users fails to enter an expiration date in the text field. For example, if I select "Beef" and do not enter an expiration date, the errors populate in the Formik errors. However, I don't know how to map that error to the correct expiration text box.
Any help is appreciated!
Note:
Validations are only triggered when the validated button is clicked
There is codesandbox and code shown belown:
<Form>
<pre
style={{
textAlign: "left"
}}
>
<h3>Data</h3>
{JSON.stringify(values, null, 2)}
<h3>Errors</h3>
{JSON.stringify(errors, null, 2)}
</pre>
<Field
name="food.hasFood"
value
type="radio"
onChange={e => {
setFieldValue("food.hasFood", true);
}}
/>{" "}
Yes
<Field
name="food.hasFood"
value={false}
type="radio"
onChange={e => {
setFieldValue("food.hasFood", false);
}}
/>{" "}
No
{values.food.hasFood && (
<FieldArray name="food.selected">
{arrayHelpers => {
return foodTypes.map(item => (
<div key={item}>
<Field
name={item}
value={item}
type="checkbox"
as={Checkbox}
checked={values.food.selected
.map(f => f.name)
.includes(item)}
onChange={e => {
if (e.target.checked) {
arrayHelpers.push({
name: e.target.value,
expiration: ""
});
} else {
const index = values.food.selected
.map(f => f.name)
.indexOf(e.target.value);
arrayHelpers.remove(index);
}
}}
/>
{item}
{errors.food && touched.food && (
<p>
{Array.isArray(errors.food.selected)
? ""
: errors.food.selected}
</p>
)}
{values.food.selected.map((selectedFood, index) => {
if (item === selectedFood.name) {
return (
<div>
<Field
key={index}
as={TextField}
name={`food.selected[${index}].expiration`}
/>
{console.log(errors)}
{errors.food && touched.food && (
<p>
{Array.isArray(errors.food.selected)
? errors.food.selected[index].expiration
: errors.food.selected}
</p>
)}
</div>
);
}
return null;
})}
</div>
));
}}
</FieldArray>
)}
<button
type="button"
onClick={() => {
validateForm();
}}
>
Validate
</button>
</Form>

Categories

Resources