I'm kind of new with java and ReactJS and I have a big issue where when I tried to post my data, it posted a lot of unwanted data like rendering the whole table.
My console.log() printed this :
location_dest_id: 2
location_id: 1
origin: "test3"
picking_type_id: 1
stock_move_ids: Array(1)
0:
altKey: false
bubbles: true
button: 0
buttons: 0
cancelable: true
clientX: 317
clientY: 652
ctrlKey: false
currentTarget: null
defaultPrevented: false
demand: "12"
detail: 1
done: "0"
eventPhase: 3
getModifierState: ƒ modifierStateGetter(keyArg)
isDefaultPrevented: ƒ functionThatReturnsFalse()
isPropagationStopped: ƒ functionThatReturnsFalse()
isTrusted: true
metaKey: false
movementX: 0
movementY: 0
nativeEvent: PointerEvent {isTrusted: true, pointerId: 1, width: 1,
height: 1, pressure: 0, …}
pageX: 317
pageY: 754
product_tmpl_id: 9
product_uom: "1"
relatedTarget: null
screenX: 317
screenY: 723
shiftKey: false
target: span
timeStamp: 203547.59999990463
type: "click"
view: Window {window: Window, self: Window, document: document, name: '', location: Location, …}
_reactName: "onClick"
_targetInst: null
From what I understand, the error is when I tried to pass "stock_move_ids" nested data, it POST so much data as like the console.log() above. What it should be passed is like this :
[
{
"date":"02-09-2022",
"origin":"test2",
"picking_type_id":2,
"location_id":1,
"location_dest_id":2,
"stock_move_ids":
[
{
"demand":12,
"done":0,
"product_uom":1,
"product_tmpl_id":18
}
]
}
]
Is there any way to solve my problem? My code is based on this template : https://codesandbox.io/s/j0opp
Here's my code looks like :
Parent
import React, { useEffect, useContext } from "react";
import { Button, Form, Input, DatePicker, Select } from 'antd';
import { Stockmovetable } from "./Stockmovetable";
import { AppContext } from '../../../context/Appcontext'
const Stockpickingnew = ({ title }) => {
const { Function, State } = useContext(AppContext)
const { fetchDataPickingType, fetchDataLocation, fetchDataPupuk, option, stock_move_ids, StockPick, StockPickFailed } = Function
const { dateFormat, dataPupuk, dataStockLocation, dataStockPickingType } = State
useEffect(() => {
fetchDataPickingType()
fetchDataLocation()
fetchDataPupuk()
}, [])
return (
<>
<div className='new'>
<div className="top">
<h1>{title}</h1>
</div>
<div className="bottom">
<div className="stockPicking">
<Form
name="stockPickings"
layout="vertical"
onFinish={StockPick}
onFinishFailed={StockPickFailed}
autoComplete="off"
>
<div className="left">
<Form.Item
label="Origin :"
name='origin'
>
<Input placeholder="Origin" />
</Form.Item>
<Form.Item
label="Picking Type :"
name='picking_type_id'
>
<Select
placeholder="Picking Type"
options={dataStockPickingType.map(e => ({label: e.name, value: e.id}))}
/>
</Form.Item>
<Form.Item
label="Date :"
name='date'
>
<DatePicker
format={dateFormat}
/>
</Form.Item>
</div>
<div className="right">
<Form.Item
label="Location :"
name='location_id'
>
<Select
placeholder="Tujuan Awal"
options={dataStockLocation.map(e => ({label: e.name, value: e.id}))}
/>
</Form.Item>
<Form.Item
label="Destination :"
name='location_dest_id'
>
<Select
placeholder="Tujuan Akhir"
options={dataStockLocation.map(e => ({label: e.name, value: e.id}))}
/>
</Form.Item>
</div>
<div className="stockMove">
<Form.List name="stock_move_ids">
{(stock_move_ids, { add, remove }) => {
return <Stockmovetable stock_move_ids={stock_move_ids} option={option} add={add} remove={remove} dataPupuk={dataPupuk} />;
}}
</Form.List>
</div>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
</div>
</div>
</div>
</>
)
}
export default Stockpickingnew
Child
import React from "react";
import { Form, Input, Button, Table, Select } from "antd";
import { PlusOutlined, MinusOutlined } from "#ant-design/icons";
const { Column } = Table;
export const Stockmovetable = props => {
const { stock_move_ids, add, remove, dataPupuk, option } = props;
return (
<Table
dataSource={stock_move_ids}
pagination={false}
footer={() => {
return (
<Form.Item>
<Button onClick={add}>
<PlusOutlined /> Add field
</Button>
</Form.Item>
);
}}
>
<Column
dataIndex={"product_tmpl_id"}
title={"Nama Produk"}
render={(value, row, index) => {
return (
<Form.Item name={[index, "product_tmpl_id"]}>
<Select
placeholder="Produk"
options={dataPupuk.map(e => ({ label: e.name, value: e.id }))}
/>
</Form.Item>
);
}}
/>
<Column
dataIndex={"demand"}
title={"Demand"}
render={(value, row, index) => {
// console.log(row);
return (
<Form.Item name={[index, "demand"]}>
<Input
placeholder="Demand"
/>
</Form.Item>
);
}}
/>
<Column
dataIndex={"done"}
title={"Done"}
render={(value, row, index) => {
return (
<Form.Item name={[index, "done"]}>
<Select
placeholder="Tujuan Akhir"
options={option}
/>
</Form.Item>
);
}}
/>
<Column
dataIndex={"product_uom"}
title={"product_uom"}
render={(value, row, index) => {
return (
<Form.Item name={[index, "product_uom"]}>
<Input
placeholder="product_uom"
/>
</Form.Item>
);
}}
/>
<Column
title={"Action"}
render={(value, row, index) => {
return (
<React.Fragment>
<Button
icon={<MinusOutlined />}
shape={"circle"}
onClick={() => remove(row.name)}
/>
</React.Fragment>
);
}}
/>
</Table>
);
};
Context
export const AppContext = createContext()
export const AppProvider = props => {
const Navigate = useNavigate()
const dateFormat = ['DD-MM-YYYY'];
const StockPick = (values) => {
console.log('Success:', values);
let stockpick = [{
date: moment(values.date).format("DD-MM-YYYY"),
origin: values.origin,
picking_type_id: values.picking_type_id,
location_id: parseInt(values.location_id),
location_dest_id: parseInt(values.location_dest_id),
stock_move_ids: [
{
demand: parseInt(values?.stock_move_ids?.[0]?.demand),
done: parseInt(values?.stock_move_ids?.[0]?.done),
product_uom: parseInt(values?.stock_move_ids?.[0]?.product_uom),
product_tmpl_id: values?.stock_move_ids?.[0]?.product_tmpl_id,
},
],
}];
let params = JSON.stringify(stockpick)
console.log(params)
axios.post('http://127.0.0.1:5000/api/stockpickings', params, { headers })
.then(() => {
Navigate('/')
})
.catch(error => {
if (error.response) {
console.log(error.response);
}
});
};
}
I think this is all I can provide / needed to fix my codings, if there's anything I need to add and or fix, please tell me. Thank you.
Okay after some hours tries
as the comment above, i think all i need to do is just not making the body as dataindex.
from :
<Form.List name="stock_move_ids">
{(stock_move_ids, { add, remove }) => {
return <Stockmovetable stock_move_ids={stock_move_ids} option={option} add={add} remove={remove} dataPupuk={dataPupuk} />;
}}
</Form.List>
to
<Form.List name="stock_move_ids">
{(stock_move, { add, remove }) => {
return <Stockmovetable stock_move_ids={stock_move_ids} option={option} add={add} remove={remove} dataPupuk={dataPupuk} />;
}}
</Form.List>
Thank you very much for the helps!
Related
im quite new on reactJS and also ant design. right now im trying to get a value from a Form.List that i want to make it / render it as json nested data output.
my full code :
import { MinusCircleOutlined, PlusOutlined } from '#ant-design/icons';
import { Button, Form, Input, Space, DatePicker, Select } from 'antd';
import axios from 'axios'
import { useNavigate } from 'react-router-dom'
import Cookies from "js-cookies";
import moment from 'moment';
import 'moment/locale/zh-cn';
const Stockpickingnew = ({ title }) => {
const options = [
{
value: '1',
label: 'True',
},
{
value: '0',
label: 'False',
},
{
value: '7',
label: 'product_tmpl_id'
},
];
const Navigate = useNavigate()
const dateFormat = ['DD-MM-YYYY'];
//---------------------------------------------------------------------------------------------------------------
let headers = {
"Authorization": "Bearer " + Cookies.getItem('access_token')
}
const onFinish = (values) => {
console.log('Success:', values);
let stockpick = {
date: moment(values.date).format("DD-MM-YYYY"),
origin: values.origin,
picking_type_id: values.picking_type_id,
location_id: values.location_id,
location_dest_id: values.location_dest_id,
stock_move_ids: [{
demand: values.demand,
done: values.done,
product_uom: values.product_uom,
product_tmpl_id: values.product_tmpl_id,
}]
};
console.log(JSON.stringify(stockpick))
let params = JSON.stringify(stockpick)
axios.post('http://127.0.0.1:5000/api/stockpickings', params, { headers })
.then(() => {
Navigate('/')
})
.catch(error => {
if (error.response) {
console.log(error.response);
}
});
};
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
//---------------------------------------------------------------------------------------------------------------
return (
<>
<div className='new'>
<div className="top">
<h1>{title}</h1>
</div>
<div className="bottom">
<div className="stockPicking">
<Form
name="stockPickings"
layout="vertical"
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<div className="left">
<Form.Item
label="Origin :"
name='origin'
>
<Select
options={options}
placeholder="Origin"
/>
</Form.Item>
<Form.Item
label="Picking Type :"
name='picking_type_id'
>
<Select
options={options}
placeholder="Picking Type"
/>
</Form.Item>
<Form.Item
label="Date :"
name='date'
>
<DatePicker
format={dateFormat}
onChange={(dateInMomentFormat, dateInStringFormat) => {
console.log(dateInStringFormat);
}}
/>
</Form.Item>
</div>
<div className="right">
<Form.Item
label="Location :"
name='location_id'
>
<Select
options={options}
placeholder="Location"
/>
</Form.Item>
<Form.Item
label="Destination :"
name='location_dest_id'
>
<Select
options={options}
placeholder="Destination"
/>
</Form.Item>
</div>
<div className="stockMove">
<Form.Item>
<Form.List name="stock_move_ids">
{(fields, { add, remove }) => (
<>
{fields.map((field) => (
<Space
key={field.key}
style={{
display: 'flex',
marginBottom: 8,
}}
align="baseline"
>
<Form.Item
{...field}
name={[field.name, 'demand']}
key={[field.key, 'demand']}
rules={[
{
required: true,
message: 'Missing Demand',
},
]}
>
<Input placeholder="Demand" />
</Form.Item>
<Form.Item
{...field}
name={[field.name, 'done']}
key={[field.key, 'done']}
>
<Select
options={options}
placeholder="Done"
/>
</Form.Item>
<Form.Item
{...field}
name={[field.name, 'product_uom']}
key={[field.key, 'product_uom']}
rules={[
{
required: true,
message: 'Missing product_uom',
},
]}
>
<Select
options={options}
placeholder="product_uom"
/>
</Form.Item>
<Form.Item
{...field}
name={[field.name, 'product_tmpl_id']}
key={[field.key, 'product_tmpl_id']}
rules={[
{
required: true,
message: 'Missing product_tmpl_id',
},
]}
>
<Select
options={options}
placeholder="product_tmpl_id"
/>
</Form.Item>
<MinusCircleOutlined onClick={() => remove(field.name)} />
</Space>
))}
<Form.Item>
<Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
Add field
</Button>
</Form.Item>
</>
)}
</Form.List>
</Form.Item>
</div>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
</div>
</div>
</div>
</>
)
}
export default Stockpickingnew
im sorry if it's really hard to read but basically, what i really want to do is my Form.List can get a value as nested data like :
stock_move_ids: [{
demand: values.demand,
done: values.done,
product_uom: values.product_uom,
product_tmpl_id: values.product_tmpl_id,
}]
my console.log (values) and console.log JSON.stringify(stockpick) do have different result as image below.
first one is from console.log values and the bottom one is from console.log stockpick
Screenshoot here
stock_move_ids values have 0th index you can access it like this.
let stockpick = {
date: moment(values.date).format("DD-MM-YYYY"),
origin: values.origin,
picking_type_id: values.picking_type_id,
location_id: values.location_id,
location_dest_id: values.location_dest_id,
stock_move_ids: [
{
demand: values?.stock_move_ids?.[0]?.demand,
done: values?.stock_move_ids?.[0]?.done,
product_uom: values?.stock_move_ids?.[0]?.product_uom,
product_tmpl_id: values?.stock_move_ids?.[0]?.product_tmpl_id,
},
],
};
I'm using Formik and windmill for the multiselect form, see picture below. The problem is that I implemented a search functionality to look into the array of options and now it appears that even though I'm selecting an option it is not passing the value to Formik and is not submitting the form. Any help would be greatly appreciated. Thanks!
form
import { React, useState } from 'react';
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';
import { partService } from '../../services';
import { SearchIcon, AddIcon } from '../../icons';
import { Input, Label, Select, HelperText } from '#windmill/react-ui';
function CreateElementForm({ formRef, callback, partId }) {
const [searchTerm, setSearchTerm] = useState('');
const [iconSelection, setIconSelection] = useState(true);
const tempArray = [
{ name: 'data1', value: 'value1' },
{ name: 'data2', value: 'value2' },
{ name: 'data3', value: 'value3' },
{ name: 'data4', value: 'value4' },
];
return (
<Formik
innerRef={formRef}
initialValues={{
description: '',
percentage: '',
material: '',
}}
validationSchema={Yup.object().shape({
description: Yup.string().required('Element name is required'),
percentage: Yup.number().required('Percentage is required'),
material: Yup.string().required('Material is required'),
})}
onSubmit={(
{ description, percentage, material },
{ setStatus, setSubmitting }
) => {
setStatus();
setTimeout(async () => {
await partService
.createElement(partId, description, percentage, material)
.then(
(response) => {
callback(true);
},
(error) => {
if (error.response) {
setStatus(error.response.data.message);
} else {
setStatus('Some error occured.');
}
callback(false);
}
);
}, 400);
}}
>
{({ errors, status, touched, isSubmitting, setFieldValue, values }) => (
<Form>
<Label>
<span>Description</span>
<Field
className='mt-1'
as={Input}
name='description'
type='text'
placeholder='Part Element'
/>
<ErrorMessage name='name'>
{(msg) => <HelperText valid={false}>{msg}</HelperText>}
</ErrorMessage>
</Label>
<Label>
<span>Percentage</span>
<Field
className='mt-1'
as={Input}
name='percentage'
type='number'
placeholder='%'
/>
<ErrorMessage name='percentage'>
{(msg) => <HelperText valid={false}>{msg}</HelperText>}
</ErrorMessage>
</Label>
<Label>
<span>Search Field</span>
<div className='relative text-gray-500 focus-within:text-purple-600 dark:focus-within:text-purple-400'>
<Input
className='mt-1 pl-10 text-black dark:text-gray-300'
placeholder='Jane Doe'
onChange={(event) => {
setSearchTerm(event.target.value);
}}
/>
<div className='absolute inset-y-0 flex items-center ml-3 pointer-events-none'>
{iconSelection ? (
<SearchIcon className='w-5 h-5' aria-hidden='true' />
) : (
<AddIcon className='w-5 h-5' aria-hidden='true' />
)}
</div>
</div>
</Label>
<Label className='mt-4'>
<span>Multiselect</span>
<Field
className='mt-1'
as={Select}
name='material'
multiple={true}
type='text'
onChange={(evt) =>
setFieldValue('material', evt.target.selectedOptions.val)
}
>
{tempArray
.filter((value) => {
if (searchTerm === '') {
return value;
} else if (
value.name.toLowerCase().includes(searchTerm.toLowerCase())
) {
return value;
}
})
.map((i) => (
<option key={i.name} val={i.value}>
{i.name}
</option>
))}
</Field>
</Label>
{status && <HelperText valid={false}>{status}</HelperText>}
</Form>
)}
</Formik>
);
}
export default CreateElementForm;
How I can change value from this GooglePlacesAutocomplete?!
I want change googleplacesautocomplete value when I change marker position on map.
I have the opportunity to use only this package.
Maybe you can somehow change the value without using something third-party from the packages.
I've this code.
<Form.Item name="address">
<GooglePlacesAutocomplete
apiKey={API}
apiOptions={{
language: "ua",
region: "ua",
}}
selectProps={{
value,
onChange: setValue,
placeholder: "Select your address",
}}
name="address"
value={value.label}
/>
</Form.Item>
Full code:
import React, { useState, useCallback, useEffect } from "react";
import { GoogleMap, Marker, useJsApiLoader } from "#react-google-maps/api";
import { API } from "../../constants/map";
import Header from "../navigation/header";
import { createOffer } from "../../services/offerService";
import { getGoodCategories } from "../../services/goodCategoryService";
import { useHistory } from "react-router-dom";
import { inputValidationErrors } from "../../constants/messages/inputValidationErrors";
import { Form, Input, Button, DatePicker, AutoComplete, Select } from "antd";
import Geocode from "react-geocode";
import GooglePlacesAutocomplete, {
geocodeByAddress,
getLatLng,
} from "react-google-places-autocomplete";
Geocode.setApiKey(API);
Geocode.setLanguage("ua");
Geocode.setRegion("ua");
Geocode.enableDebug();
const { TextArea } = Input;
const { Option } = Select;
const containerStyle = {
width: "100%",
height: "100%",
};
const center = {
lat: 50.643,
lng: 26.263,
};
const defaultOptions = {
panControl: true,
zoomControl: true,
zoomEnabled: true,
mapTypeControl: true,
disableDefaultUI: true,
scaleControle: true,
streetViewControl: true,
rotateControl: true,
clickableIcons: true,
keyboardShortcuts: true,
scrollwheel: true,
fullscreenControl: true,
};
export default function Offer() {
const { isLoaded } = useJsApiLoader({
id: "google-map-script",
googleMapsApiKey: API,
});
let history = useHistory();
const [map, setMap] = useState();
const [clickedLatLng, setClickedLatLng] = useState(center);
const [data, setData] = useState(null);
const [value, setValue] = useState("Rivne");
const [coord, setCoord] = useState({ lat: 0, lng: 0 });
const onLoad = useCallback(function callback(map) {
const bounds = new window.google.maps.LatLngBounds(center);
map.fitBounds(bounds);
setMap(map);
}, []);
const onUnmount = useCallback(function callback(map) {
setMap(null);
}, []);
const [form] = Form.useForm();
const getData = (lat, lng) => {
Geocode.fromLatLng(lat, lng).then(
(response) => {
const address = response.results[0].formatted_address;
let settlement, region;
for (
let i = 0;
i < response.results[0].address_components.length;
i++
) {
for (
let j = 0;
j <
response.results[0].address_components[i].types.length;
j++
) {
switch (
response.results[0].address_components[i].types[j]
) {
case "locality":
settlement =
response.results[0].address_components[i]
.long_name;
break;
case "administrative_area_level_1":
region =
response.results[0].address_components[i]
.long_name;
break;
}
}
}
//setValue(address);
console.log("VALUE", value);
form.setFieldsValue({
address: address,
settlement: settlement,
region: region,
});
},
(error) => {
console.error(error);
}
);
};
useEffect(async () => {
setData(await getGoodCategories());
if (value) {
geocodeByAddress(value.label).then((result) => {
getLatLng(result[0]).then((googleCoord) =>
setCoord(googleCoord)
);
});
}
}, [geocodeByAddress, getLatLng, value, setCoord]);
console.log(coord.lat, coord.lng);
const onFinish = (values) => {
console.log(values);
createOffer(values, clickedLatLng, history);
};
const onFinishFailed = (values) => {
console.log("error");
};
return isLoaded ? (
<>
<Header />
<div className="createOfferBody">
<h1>Create offer</h1>
<Form
form={form}
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
initialValues={{ remember: true }}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
scrollToFirstError
>
<div className="topFormBlock">
<div className="addressBlock">
<Form.Item name="address">
<GooglePlacesAutocomplete
apiKey={API}
apiOptions={{
language: "ua",
region: "ua",
}}
selectProps={{
value,
onChange: setValue,
placeholder: "Select your address",
}}
name="address"
value={value.label}
/>
</Form.Item>
<Form.Item
name="settlement"
rules={[
{
type: "string",
message:
inputValidationErrors.EMPTY_SETTLEMENT_MESSAGE,
},
{
required: true,
message:
inputValidationErrors.EMPTY_SETTLEMENT_MESSAGE,
},
]}
>
<Input
name="settlement"
placeholder="Enter your settlement"
/>
</Form.Item>
<Form.Item
name="region"
rules={[
{
type: "string",
message:
inputValidationErrors.EMPTY_SETTLEMENT_MESSAGE,
},
{
required: true,
message:
inputValidationErrors.EMPTY_SETTLEMENT_MESSAGE,
},
]}
>
<Input
name="region"
placeholder="Enter your settlement"
/>
</Form.Item>
</div>
<div className="mapBlock">
<GoogleMap
mapContainerStyle={containerStyle}
center={center}
onLoad={onLoad}
onUnmount={onUnmount}
options={defaultOptions}
zoom={18}
onClick={(e) => setCoord(e.latLng.toJSON())}
id="map"
>
<Marker
position={coord}
onPositionChanged={getData(
coord.lat,
coord.lng
)}
icon={{
url: "https://cdn-icons-png.flaticon.com/512/6147/6147668.png",
origin: new window.google.maps.Point(
0,
0
),
anchor: new window.google.maps.Point(
15,
15
),
scaledSize: new window.google.maps.Size(
30,
30
),
}}
/>
</GoogleMap>
</div>
</div>
<div className="bottomFormBlock">
<div className="otherOfferDataBlock">
<Form.Item name="goodCategoryId">
<Select>
{data?.map((res, idx) => (
<Option value={idx + 1} key={idx}>
{res.name}
</Option>
))}
</Select>
</Form.Item>
<Form.Item name="startDate">
<DatePicker />
</Form.Item>
<Form.Item
name="goodsWeight"
rules={[
{
message:
inputValidationErrors.EMPTY_GOOD_WEIGHT_MESSAGE,
},
{
required: true,
message:
inputValidationErrors.EMPTY_GOOD_WEIGHT_MESSAGE,
},
]}
>
<Input
type="number"
placeholder="Goods Weight"
/>
</Form.Item>
</div>
<div className="otherOfferDataBlock">
<Form.Item
name="description"
className="description"
rules={[
{
message:
inputValidationErrors.EMPTY_DESCRIPTION_MESSAGE,
},
{
required: true,
message:
inputValidationErrors.EMPTY_DESCRIPTION_MESSAGE,
},
]}
>
<TextArea placeholder="Description" />
</Form.Item>
<Form.Item>
<Button
type="primary"
htmlType="submit"
className="submitButton"
>
Create offer
</Button>
</Form.Item>
</div>
</div>
</Form>
</div>
</>
) : (
<>
<span>Map is not loaded!</span>
</>
);
}
If you are getting the address of the clicked location, which it looks like you are doing in getData function, pass the address into setValue().
const getData = (lat, lng) => {
Geocode.fromLatLng(lat, lng).then(
(response) => {
const address = response.results[0].formatted_address;
setValue(address)
I'm learning React. My target is to make this object:
"Phones": [
{
"Type": "Mobile",
"Phone_Number": "6546543"
},
{
"Type": "Home",
"Phone_Number": "6546543"
}
]
I did some research and I followed this YouTube video ReactJS - Dynamically Adding Multiple Input Fields.
These values I'll fetch from a form. Th user can keep on adding as many numbers as he wants. My code is:
render() {
return (
<div>
<h1>The Form</h1>
<label>Contact</label>
{this.state.phones.map((phone, index) => {
return (
<div key={index}>
<input onChange={(e) => this.handleChange(e)} value={phone} />
<select>
{this.phoneTypes.map((phoneType, index) => {
return (
<option key={index} value={phoneType}>
{phoneType}
</option>
);
})}
</select>
<button onClick={(e) => this.handleRemove(e)}>Remove </button>
</div>
);
})}
<hr />
<button onClick={(e) => this.addContact(e)}>Add contact</button>
<hr />
<button onClick={(e) => this.handleSubmit(e)}>Submit</button>
</div>
);
}
I'm not pasting the entire code here as I've already created a stackblitz. My code is not working as expected. Please pitch in.
You need to pass index in the handleChange function for input field. I guess you missed that part from video.This will make the input field editable.
<input
onChange={(e) => this.handleChange(e, index)}
value={phone}
/>
For the second part to get the expected object array I have updated some code, please check:
import React, { Component } from 'react';
class Questionnaire extends Component {
state = {
phones: [{ type: '', number: '' }],
};
phoneTypes = ['Mobile', 'Home', 'Office'];
addContact() {
this.setState({ phones: [...this.state.phones, { type: '', number: '' }] });
}
handleChange(e, index) {
this.state.phones[index]['number'] = e.target.value;
this.setState({ phones: this.state.phones });
}
handleRemove(index) {
this.state.phones.splice(index, 1);
console.log(this.state.phones, '$$$');
this.setState({ phones: this.state.phones });
}
handleSubmit(e) {
console.log(this.state, '$$$');
}
render() {
return (
<div>
<h1>The Form</h1>
<label>Contact</label>
{this.state.phones.map((phone, index) => {
return (
<div key={index}>
<input
onChange={(e) => this.handleChange(e, index)}
value={phone.number}
name="number"
/>
<select>
{this.phoneTypes.map((phoneType, index) => {
return (
<option key={index} value={phoneType} name="type">
{phoneType}
</option>
);
})}
</select>
<button onClick={(e) => this.handleRemove(e)}>Remove </button>
</div>
);
})}
<hr />
<button onClick={(e) => this.addContact(e)}>Add contact</button>
<hr />
<button onClick={(e) => this.handleSubmit(e)}>Submit</button>
</div>
);
}
}
export default Questionnaire;
You can use input objects like formik
import { useState } from 'react';
const Component = () => {
const [inputs, setInputs] = useState({ // Initial inputs
email: "",
phoneNumber: "",
});
const handleSubmit = (e) => {
e.preventDefault();
// Do
};
const handleChange = (e) => {
setInputs({...inputs, [e.target.id]: e.target.value});
};
const addInput = () => {
const name = window.prompt("Type a name", "");
setInputs({...inputs, [name]: ""});
};
return (
<form onSubmit={handleSubmit}>
{object.keys(inputs).map((name, i) => {
<input type="text" onChange={handleChange} name={name} value={inputs[name]} />
})}
<button
type="button"
onClick={addInput}
>
Add Input
</button>
</form>
);
}
Still new in React and im in the middle of my practice creating table components, the task is: input, delete and edit data.
input data row is working
delete data row is working
edit data not working,
i can manage to get the value, but i can't edit it.
the code still messy too, but it works from point 1 to 2.
Here is the code. Hope you guys can point out my mistakes and maybe some tips to tidy up this code to make it more cleaner.
Thanks
//Table.js//
import React, { Component } from 'react'
import { Table, Icon, Button, Modal, Form } from 'semantic-ui-react'
import 'semantic-ui-css/semantic.min.css'
import { DateInput } from 'semantic-ui-calendar-react'
import './Tables.css'
var database = [
{
DocNum: 123,
DocTyp: 'Permit',
DocName: 'Permit A',
SignDate: '2007-11-05',
ExprDate: '2012-11-05'
},
{
DocNum: 456,
DocTyp: 'Permit',
DocName: 'Permit C',
SignDate: '2010-02-11',
ExprDate: '2015-02-11'
},
{
DocNum: 789,
DocTyp: 'Contract',
DocName: 'Contract Z',
SignDate: '2017-06-08',
ExprDate: '2022-06-08'
}
]
const options = [
{ key: 1, text: 'Permit', value: 'Permit' },
{ key: 2, text: 'Contract', value: 'Contract' },
]
const initialState = { open: false,
open2: false,
open3: false,
open4: false,
DocNum: '',
DocTyp: '',
DocName: '',
SignDate: '',
ExprDate: '',
del:'',
edit:''
}
function Addbtn ({ onShow3 }) {
return(
<Button content='Add Document' icon='plus' labelPosition='left' color="green" onClick={onShow3} />
)
}
function InputData ({ onChange, onSubmit, DataInput}) {
return (
<Form className="InputContainer">
<Form.Input label="Document Number" type="text" name="DocNum" onChange={onChange} />
<Form.Select label="Document Type" type="text" name="DocTyp" onChange={onChange} options={options} />
<Form.Input label="Document Name" type="text" name="DocName" onChange={onChange} />
<DateInput label="Signed Date" name="SignDate" onChange={onChange} value={DataInput[0].SignDate}/>
<DateInput label="Expired Date" name="ExprDate" onChange={onChange} value={DataInput[0].ExprDate}/>
</Form>
)
}
function EditData ({ onChange, onSubmit, DataEdit }) {
return (
<Form className="InputContainer">
<Form.Input label="Document Number" type="text" name="DocNum" onChange={onChange} value={DataEdit.DocNum}/>
<Form.Select label="Document Type" type="text" name="DocTyp" onChange={onChange} options={options} value={DataEdit.DocTyp} />
<Form.Input label="Document Name" type="text" name="DocName" onChange={onChange} value={DataEdit.DocName} />
<DateInput label="Signed Date" name="SignDate" onChange={onChange} value={DataEdit.SignDate}/>
<DateInput label="Expired Date" name="ExprDate" onChange={onChange} value={DataEdit.ExprDate}/>
</Form>
)
}
function RowData(props) {
const database = props.database
const RowList = database.map((data)=>
<Table.Row key={data.DocNum}>
<Table.Cell>{data.DocNum}</Table.Cell>
<Table.Cell>{data.DocTyp}</Table.Cell>
<Table.Cell>{data.DocName}</Table.Cell>
<Table.Cell>{data.SignDate}</Table.Cell>
<Table.Cell>{data.ExprDate}</Table.Cell>
<Table.Cell className="icon" collapsing>
<Icon color='yellow'
name='edit'
link
onClick={()=>props.onShow(data)}
/>
<Icon color='red'
name='trash'
link
key={data.DocNum}
onClick={()=>props.onShow2(data)}
/>
</Table.Cell>
</Table.Row>
)
return RowList
}
class TableComponent extends Component{
state = initialState
show = (data) => {
this.setState({ open: true,
edit: data })
}
show2 = (data) => {
this.setState({ open2: true,
del: data })
}
show3 = () => {
this.setState({ open3: true })
}
show4 = (data) => {
this.setState({ open4: true })
this.close()
}
close = () => {
this.setState({ open: false })
}
close2 = () => {
this.setState({ open2: false })
}
close3 = () => {
this.setState({ open3: false })
}
close4 = () => {
this.setState({ open4: false })
}
InputChange = (e, DataInput) => {
this.setState({ [DataInput.name]: DataInput.value })
}
SearchDel = () =>{
for(let i=0; i<database.length; i++){
if (this.state.del === database[i])
return database.splice(i, 1)}
}
DelData = () =>{
return ( this.SearchDel(),
this.close2())
}
Submit = (data) => {
return (database.push(data),
this.close3())
}
render(){
return(
<div className='MainContainer'>
<div className="TblContainer">
<div className="AddButton">
<Addbtn onShow3={this.show3}/>
</div>
<Table color="red" celled >
<Table.Header>
<Table.Row>
<Table.HeaderCell collapsing>Document Number</Table.HeaderCell>
<Table.HeaderCell width={2}>Document Type</Table.HeaderCell>
<Table.HeaderCell width={6}>Document Name</Table.HeaderCell>
<Table.HeaderCell collapsing>Signed Date</Table.HeaderCell>
<Table.HeaderCell collapsing>Expired Date</Table.HeaderCell>
<Table.HeaderCell collapsing />
</Table.Row>
</Table.Header>
<Table.Body>
<RowData database={database} onShow={this.show} onShow2={this.show2} />
</Table.Body>
</Table>
<Modal open={this.state.open} onClose={this.state.close} id="Modal1">
<Modal.Header>Edit Data</Modal.Header>
<Modal.Content>
<p>Are you sure you want to edit this?</p>
</Modal.Content>
<Modal.Actions>
<Button negative onClick={this.close}>No</Button>
<Button positive onClick={this.show4}>Yes</Button>
</Modal.Actions>
</Modal>
<Modal open={this.state.open2} onClose={this.state.close2} value={this.state} id="Modal2">
<Modal.Header>Delete Data</Modal.Header>
<Modal.Content>
<p>Are you sure you want to delete this?</p>
</Modal.Content>
<Modal.Actions>
<Button negative onClick={this.close2}>No</Button>
<Button positive onClick={()=>this.DelData()}>Yes</Button>
</Modal.Actions>
</Modal>
<Modal open={this.state.open3} onClose={this.state.close3} id="Modal3">
<Modal.Header>Inputing Data</Modal.Header>
<Modal.Content>
<InputData onChange={this.InputChange}
onSubmit={this.Submit}
DataInput={[this.state]} />
</Modal.Content>
<Modal.Actions>
<Button negative onClick={this.close3}>No</Button>
<Button positive onClick={()=>this.Submit(this.state)}>Submit</Button>
</Modal.Actions>
</Modal>
<Modal open={this.state.open4} onClose={this.state.close4} id="Modal4">
<Modal.Header>Editing Data</Modal.Header>
<Modal.Content>
<EditData onChange={this.InputChange}
onSubmit={this.Submit}
DataEdit={this.state.edit} />
</Modal.Content>
<Modal.Actions>
<Button negative onClick={this.close4}>No</Button>
<Button positive onClick={()=>this.Submit(this.state)}>Submit</Button>
</Modal.Actions>
</Modal>
</div>
</div>
)
}
}
export default TableComponent
//Table.css//
.TblContainer{
margin: 100px;
}
.AddButton{
display: flex;
justify-content: flex-end;
}