This is the total code that I currently have.
import { React, useEffect, useState } from 'react';
import { AgGridReact } from "ag-grid-react";
import "ag-grid-community/dist/styles/ag-grid.css";
import "ag-grid-community/dist/styles/ag-theme-balham.css";
const FetchStocks = () => {
const API_KEY = "apiKey1";
const API_KEY2 = "apiKey2";
const API_KEY3 = "apiKey3";
const [data, setData] = useState({ StockSymbols: null, StockName: null, StockIndustry: null })
const [MSFT, setMSFT] = useState({ MSFTSymbols: null, MSFTName: null, MSFTIndustry: null })
const [AA, setAA] = useState({ AASymbols: null, AAName: null, AAIndustry: null })
const [BABA, setBABA] = useState({ BABASymbols: null, BABAName: null, BABAIndustry: null })
const [SAIC, setSAIC] = useState({ SAICSymbols: null, SAICName: null, SAICIndustry: null })
const [search, setSearch] = useState < string > ('');
useEffect(() => {
fetch(`https://www.alphavantage.co/query?function=OVERVIEW&symbol=IBM&apikey=${API_KEY}`)
.then(
function (response) {
return response.json();
}
)
.then(
function (data) {
setData({
StockSymbols: data['Symbol'],
StockName: data['Name'],
StockIndustry: data['Industry']
})
})
fetch(`https://www.alphavantage.co/query?function=OVERVIEW&symbol=MSFT&apikey=${API_KEY2}`)
.then(
function (response) {
return response.json();
}
)
.then(
function (MSFT) {
setMSFT({
MSFTSymbols: MSFT['Symbol'],
MSFTName: MSFT['Name'],
MSFTIndustry: MSFT['Industry']
})
})
fetch(`https://www.alphavantage.co/query?function=OVERVIEW&symbol=AA&apikey=${API_KEY3}`)
.then(
function (response) {
return response.json();
}
)
.then(
function (AA) {
setAA({
AASymbols: AA['Symbol'],
AAName: AA['Name'],
AAIndustry: AA['Industry']
})
})
fetch(`https://www.alphavantage.co/query?function=OVERVIEW&symbol=BABA&apikey=${API_KEY}`)
.then(
function (response) {
return response.json();
}
)
.then(
function (BABA) {
setBABA({
BABASymbols: BABA['Symbol'],
BABAName: BABA['Name'],
BABAIndustry: BABA['Industry']
})
})
fetch(`https://www.alphavantage.co/query?function=OVERVIEW&symbol=SAIC&apikey=${API_KEY2}`)
.then(
function (response) {
return response.json();
}
)
.then(
function (SAIC) {
setSAIC({
SAICSymbols: SAIC['Symbol'],
SAICName: SAIC['Name'],
SAICIndustry: SAIC['Industry']
})
})
}, [])
const table = {
columns: [
{ headerName: "Symbol", field: "symbol" },
{ headerName: "Name", field: "name" },
{ headerName: "Industry", field: "industry" }
],
rowData: [
{ symbol: `${data.StockSymbols}`, name: `${data.StockName}`, industry: `${data.StockIndustry}` },
{ symbol: `${MSFT.MSFTSymbols}`, name: `${MSFT.MSFTName}`, industry: `${MSFT.MSFTIndustry}` },
{ symbol: `${AA.AASymbols}`, name: `${AA.AAName}`, industry: `${AA.AAIndustry}` },
{ symbol: `${BABA.BABASymbols}`, name: `${BABA.BABAName}`, industry: `${BABA.BABAIndustry}` },
{ symbol: `${SAIC.SAICSymbols}`, name: `${SAIC.SAICName}`, industry: `${SAIC.SAICIndustry}` }
],
}
let containerStyle = {
height: 500,
width: 700
}
return (
<div>
<div>
<input type="search" placeholder="Search Stock" />
</div>
<div
className="ag-theme-balham"
style={containerStyle}
>
<AgGridReact
columnDefs={table.columns}
rowData={table.rowData}
pagination={true}
/>
</div>
</div>
)
};
export default FetchStocks;
I'm trying to make search bar for the symbols column in the table.
This is the table
However, I'm concerned because every element in the table is fetched and saved in differenct const (eg. data, MSFT, AA).
How would I be able to create a search bar that searches by the stock symbol in the table?
One of the easiest way I can think of is to use filter method on 'rowData' property of 'table'.
rowData: [
{
symbol: `${data.StockSymbols}`,
name: `${data.StockName}`,
industry: `${data.StockIndustry}`
}
].filter((data) => {
return data.name.includes(search);
})
Add setSearch to onChange eventHandler of input Element.
In here, I have shown to use name of the stock, you can also use industry and filter based on that.
Attached, codesandbox link
Related
I have a project with nextjs and typescript.I use prime react as a UI kit for my project.
On one of my pages I have a table and in this table I have a checkbox per row for select that row
also if user dblClicked on a row it should navigate into another page.my issue is when I dblClick on a row checkbox is triggered(onSelectionChange method trigger). I know that prime table can get selectionMode='checkbox' prop and in that case checkbox triggered only if user clicks on a checkbox itself but I want if user singleClicks on a row onSelectionChange trigger too.
I wrote a wrapper for prime table component (<"Table someProps />)
this is my code
import React, {useEffect, useState} from 'react';
import {DataTableDataSelectableParams} from 'primereact/datatable';
import Table from '../Table';
import {AutoCompleteCompleteMethodParams} from 'primereact/autocomplete';
import {FlightStaticService} from '../../../adapter/FlightStaticService';
import OptionsMenu from '../../OptionsMenu/OptionsMenu';
import {InputSwitch} from 'primereact/inputswitch';
import InputWrapper from '../../InputWrapper/InputWrapper';
import {FlightService} from '../../../adapter/FlightService';
import ConfirmationStatus from '../../ConfirmationStatus/ConfirmationStatus';
import {useRouter} from 'next/router';
const flightStaticInstance = new FlightStaticService();
const flightInstance = new FlightService();
const FlightsListTable = () => {
const [selectedRows, setSelectedRows] = useState<{ [key: string]: string | number | boolean }[]>([]);
const [filteredAirlines, setFilteredAirlines] = useState([]);
const [filteredAirports, setFilteredAirports] = useState([]);
const [shouldUpdateTable, setShouldUpdateTable] = useState(false);
const router = useRouter();
const searchAirlines = (e: AutoCompleteCompleteMethodParams) => {
if (!e.query) {
e.query = 'as';
}
flightStaticInstance
.getAirlines(e.query)
.then((res) => {
setFilteredAirlines(res.data.result);
})
.catch(e => {
setFilteredAirlines([]);
});
};
const searchAirports = (e: AutoCompleteCompleteMethodParams) => {
if (!e.query) {
e.query = 'meh';
}
flightStaticInstance
.getAirports(e.query)
.then((res) => {
setFilteredAirports(res.data.result);
})
.catch(e => {
setFilteredAirports([]);
});
};
const isRowSelectable = (event: DataTableDataSelectableParams) => {
const data = event.data;
if (selectedRows.find((sel) => sel.id === data.id)) {
return true;
}
return selectedRows.length < 2 && data.isActive;
};
useEffect(() => {
if (shouldUpdateTable) {
setShouldUpdateTable(false);
}
}, [shouldUpdateTable]);
useEffect(() => {
if (selectedRows.length > 0) {
sessionStorage.setItem('flights', JSON.stringify(selectedRows));
}
}, [selectedRows]);
const confirmStatusBodyTemplate = (rowData: any) => {
return <ConfirmationStatus status={rowData.status}/>
};
const statusBodyTemplate = (rowData: any) => {
return rowData.isActive ? 'فعال' : 'غیرفعال';
};
const optionsBodyTemplate = (rowData: any) => {
return <OptionsMenu options={[{
type: 'link',
url: `/flight/${rowData.id}`,
label: 'جزییات پرواز',
iconName: 'icon-note-text2'
}, {
type: 'link',
url: `/flight/${rowData.id}/edit`,
label: 'ویرایش پرواز',
iconName: 'icon-edit-2'
},
{
type: 'link',
url: `/flight/${rowData.id}/pricing?flightGroupTitle=${rowData.flightGroupTitle}`,
label: 'تقویم قیمتی',
iconName: 'icon-calendar-2'
},
{
type: 'element',
element: <div className='w-full' onClick={e => e.stopPropagation()}>
<InputWrapper labelClassName='text-grey-4' className='w-full' labelBeforeInput={true}
labelBesideInput label='وضعیت'>
<InputSwitch
onChange={e => {
flightInstance.toggleFlightStatus(rowData.id).then(res => {
setShouldUpdateTable(true);
}).catch(e => {
});
}
}
checked={rowData.isActive}
className='mr-auto'/>
</InputWrapper>
</div>
}
]}/>
}
return (
<Table
url="/Flight/GetFlights"
shouldUpdateTable={shouldUpdateTable}
filters={[
{
name: 'airlineId',
label: 'ایرلاین',
type: 'autocomplete',
value: '',
suggestions: filteredAirlines,
completeMethod: searchAirlines,
optionValue: 'iata',
optionType: 'string',
fieldName: 'nameFa'
},
{
name: 'flightGroupTitle',
label: 'عنوان پرواز',
type: 'text',
value: ''
},
{
name: 'originAirPortId',
label: 'فرودگاه مبدا',
type: 'autocomplete',
value: '',
optionValue: 'iata',
optionType: 'string',
suggestions: filteredAirports,
completeMethod: searchAirports,
fieldName: 'nameFa'
},
{
name: 'destinationAirPortId',
label: 'فرودگاه مقصد',
type: 'autocomplete',
value: '',
optionValue: 'iata',
optionType: 'string',
suggestions: filteredAirports,
completeMethod: searchAirports,
fieldName: 'nameFa'
}
]}
columns={[
{
field: 'airlineNameFa',
header: 'ایرلاین',
},
{
field: 'flightGroupTitle',
header: 'عنوان پرواز',
sortable: true,
},
{field: 'originCityNameFa', header: 'مبدا'},
{field: 'destinationCityNameFa', header: 'مقصد'},
{field: 'baggageAllowance', header: 'بار مجاز', sortable: true},
{
field: 'confirmStatus',
header: 'وضعیت تایید',
body: confirmStatusBodyTemplate,
},
{
field: 'isActive',
header: 'وضعیت',
body: statusBodyTemplate,
},
{
field: 'options',
body: optionsBodyTemplate
},
]}
tableProps={{
selection: selectedRows,
onSelectionChange: (e) => setSelectedRows(e.value),
isDataSelectable: isRowSelectable,
showSelectAll: false,
rowClassName: (data) => data.isActive ? '' : 'text-disabled',
onRowDoubleClick: (e) => router.push(`/flight/${e.data.id}`)
}}
/>
);
};
export default FlightsListTable;
OK here is a working Code Sandbox showing exactly what you want to do:
https://codesandbox.io/s/primereact-datatable-single-and-double-click-selection-0in9em?file=/src/demo/DataTableSelectionDemo.js
The trick is to handle onRowClick yourself.
const onRowClick = (event) => {
if (event.originalEvent.detail === 1) {
timer.current = setTimeout(() => {
const selected = [...selectedProducts8];
selected.push(event.data);
setSelectedProducts8(selected);
}, 300);
}
};
const onRowDoubleClick = (e) => {
clearTimeout(timer.current);
console.log("dblclick");
};
If you agree with this don't forget to select this as the right answer.
I have 2 inputs in which i provide value to search whether its name of the company, position (1st input) or location (2nd input). It works with one argument provided into foundJobs mutation and then into action. But when payload has an object everything is undefined and array is empty. What am i doing wrong?
component:
<script setup>
import IconSearch from "../Icons/icon-search.vue";
import IconLocation from "../Icons/icon-location.vue";
import { ref } from "vue";
import { useStore } from "vuex";
const store = useStore();
const nameFilter = ref("");
const locationFilter = ref("");
</script>
<template>
<div class="header-filter">
<div class="header-filter__search">
<IconSearch />
<input
type="text"
placeholder="Filter by title, companies, expertise…"
ref="nameFilter"
/>
</div>
<div class="header-filter__location">
<IconLocation />
<input
type="text"
placeholder="Filter by location…"
ref="locationFilter"
/>
</div>
<div class="header-filter__fulltime">
<input type="checkbox" />
<p>Full Time Only</p>
<button
type="button"
#click="
store.dispatch('foundJobs', {
nameFilter: nameFilter.value,
locationFilter: locationFilter.value,
})
"
>
Search
</button>
</div>
</div>
</template>
vuex: (not working)
import { createStore } from "vuex";
const store = createStore({
state() {
return {
jobs: [],
filteredJobs: [],
};
},
mutations: {
setJobs(state, jobs) {
state.jobs = jobs;
},
foundJobs(state, { nameInputValue, locationInputValue }) {
let copiedJobsArr = [...state.jobs];
if (nameInputValue !== "") {
copiedJobsArr = copiedJobsArr.filter(
(job) =>
job.company === nameInputValue || job.position === nameInputValue
);
}
if (locationInputValue !== "") {
copiedJobsArr = copiedJobsArr.filter(
(job) => job.location === locationInputValue
);
}
console.log(locationInputValue); // undefined
state.filteredJobs = copiedJobsArr;
console.log(state.filteredJobs); //empty array
},
},
actions: {
foundJobs(context, { nameInputValue, locationInputValue }) {
context.commit("foundJobs", { nameInputValue, locationInputValue });
},
loadJobs(context) {
return fetch("./data.json")
.then((response) => {
return response.json();
})
.then((data) => {
const transformedData = data.map((job) => {
return {
id: job.id,
company: job.company,
logo: job.logo,
logoBackground: job.logoBackground,
position: job.position,
postedAt: job.postedAt,
contract: job.contract,
location: job.location,
website: job.website,
apply: job.apply,
description: job.description,
reqContent: job.requirements.content,
reqItems: job.requirements.items,
roleContent: job.role.content,
roleItems: job.role.items,
};
});
context.commit("setJobs", transformedData);
});
},
},
getters: {
jobs(state) {
return state.jobs;
},
filteredJobOffers(state) {
return state.filteredJobs;
},
},
});
export default store;
vuex (working) - here i also provide one argument into action assigned to a button (in a component file)
import { createStore } from "vuex";
const store = createStore({
state() {
return {
jobs: [],
filteredJobs: [],
};
},
mutations: {
setJobs(state, jobs) {
state.jobs = jobs;
},
foundJobs(state, nameInputValue) {
let copiedJobsArr = [...state.jobs];
if (nameInputValue !== "") {
copiedJobsArr = copiedJobsArr.filter(
(job) =>
job.company === nameInputValue || job.position === nameInputValue
);
}
console.log(nameInputValue);
state.filteredJobs = copiedJobsArr;
console.log(state.filteredJobs);
},
},
actions: {
foundJobs(context, nameInputValue) {
context.commit("foundJobs", nameInputValue);
},
loadJobs(context) {
return fetch("./data.json")
.then((response) => {
return response.json();
})
.then((data) => {
const transformedData = data.map((job) => {
return {
id: job.id,
company: job.company,
logo: job.logo,
logoBackground: job.logoBackground,
position: job.position,
postedAt: job.postedAt,
contract: job.contract,
location: job.location,
website: job.website,
apply: job.apply,
description: job.description,
reqContent: job.requirements.content,
reqItems: job.requirements.items,
roleContent: job.role.content,
roleItems: job.role.items,
};
});
context.commit("setJobs", transformedData);
});
},
},
getters: {
jobs(state) {
return state.jobs;
},
filteredJobOffers(state) {
return state.filteredJobs;
},
},
});
export default store;
store.dispatch('foundJobs', {
nameFilter: nameFilter.value,
locationFilter: locationFilter.value,
})
You are sending data like this and trying to get on the wrong way
foundJobs(state, { nameInputValue, locationInputValue })
you can receive data this way:
foundJobs(state, { nameFilter, locationFilter})
I am using react hooks forms, and I am trying to set the default values of a form that is outputted by mapping over an array and outputting the inputs in the form. I have reduced the array to an object like this {name0:"fijs",name1:"3838"...} and if I manually pass that in the default values it maps to my inputs and populates them. However if I enter them from the variable that is doing the reduce function it doesn't populate it. I think it is because on first render it is undefined. I have tried using a useEffect, but that didn't work so I am stuck.
This is the part of the code I am working on
const test = formState?.reduce((obj, item, idx) => {
return { ...obj, [`${item.name}${idx}`]: "fdsjfs" };
}, {});
const { register, handleSubmit, errors } = useForm({
defaultValues: test,
});
console.log(test);
and this is the whole thing
import { useQuery, gql, useMutation } from "#apollo/client";
import { useEffect, useState } from "react";
import { v4 as uuidv4 } from "uuid";
import { useForm } from "react-hook-form";
const INPUT_VALUES = gql`
query GetInputValues {
allFormInputVals {
data {
name
_id
type
}
}
}
`;
const ADD_INPUT_VALUES = gql`
mutation AddInputValues(
$name: String!
$type: String!
$index: Int!
$ID: ID!
) {
createFormInputVal(
data: {
name: $name
type: $type
index: $index
formRoot: { connect: $ID }
}
) {
name
}
}
`;
const Home = () => {
const blankFormInput = {
__typename: "FormInputVal",
name: "test",
_id: uuidv4(),
type: "text",
};
const [formState, setFormState] = useState([blankFormInput]);
const [formStateVals, setFormStateVals] = useState(undefined);
const { loading, error, data } = useQuery(INPUT_VALUES);
const [createFormInputVal, { data: createInputData }] = useMutation(
ADD_INPUT_VALUES
);
useEffect(() => {
setFormState(data?.allFormInputVals?.data);
}, [data]);
const test = formState?.reduce((obj, item, idx) => {
return { ...obj, [`${item.name}${idx}`]: "fdsjfs" };
}, {});
const { register, handleSubmit, errors } = useForm({
defaultValues: test,
});
console.log(test);
const onSubmit = (data) => console.log(data);
console.log(errors);
const addInput = async () => {
const blanktext = {
__typename: "FormInputVal",
name: "Product Image",
_id: uuidv4(),
type: "text",
};
setFormState([...formState, { ...blanktext }]);
console.log(formState);
const res = await createFormInputVal({
variables: {
name: "test",
type: "text",
index: 0,
ID: "291541554941657608",
},
}).catch(console.error);
console.log(res);
};
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<>
<form onSubmit={handleSubmit(onSubmit)}>
<input type="button" value="Add Form Input" onClick={addInput} />
{formState?.map((val, idx) => {
const nameId = `name${idx}`;
const typeId = `type-${idx}`;
return (
<div key={val._id}>
{val.type === "text" && (
<>
<label htmlFor={nameId}>{`${val.name} #${idx + 1}`}</label>
<input
type="text"
name={nameId}
id={nameId}
className={val.type}
ref={register()}
/>
{/* <label htmlFor={typeId}>{`Type #${idx + 1}`}</label>
<select name={typeId} id={typeId} className={val.type}>
{data.allFormInputVals.data.map((item) => {
return (
<option key={item._id} value={item.type}>
{item.type}
</option>
);
})}
</select> */}
</>
)}
</div>
);
})}
<button type="submit">Save Form</button>
</form>
</>
);
};
export default Home;
UPDATE: I have tried useEffect with a reset from the api, I thought this was the solution, but still no dice.
const { register, handleSubmit, errors, reset } = useForm();
useEffect(() => {
const result = test; // result: { firstName: 'test', lastName: 'test2' }
reset(result); // asynchronously reset your form values
}, [reset]);
UPDATE: I abstracted the Form to it;s own component, but it still does not work.
Form.js
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { useQuery, gql, useMutation } from "#apollo/client";
import { v4 as uuidv4 } from "uuid";
const ADD_INPUT_VALUES = gql`
mutation AddInputValues(
$name: String!
$type: String!
$index: Int!
$ID: ID!
) {
createFormInputVal(
data: {
name: $name
type: $type
index: $index
formRoot: { connect: $ID }
}
) {
name
}
}
`;
export default function Form({ formState, setFormState }) {
const test = formState?.reduce((obj, item, idx) => {
return { ...obj, [`${item.name}${idx}`]: "fdsjfs" };
}, {});
console.log(test);
const { register, handleSubmit, errors } = useForm({ defaultValues: test });
const [formStateVals, setFormStateVals] = useState(undefined);
// console.log(test);
const onSubmit = (data) => console.log(data);
console.log(errors);
const addInput = async () => {
const blanktext = {
__typename: "FormInputVal",
name: "Product Image",
_id: uuidv4(),
type: "text",
};
setFormState([...formState, { ...blanktext }]);
console.log(formState);
const res = await createFormInputVal({
variables: {
name: "test",
type: "text",
index: 0,
ID: "291541554941657608",
},
}).catch(console.error);
console.log(res);
};
const [createFormInputVal, { data: createInputData }] = useMutation(
ADD_INPUT_VALUES
);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input type="button" value="Add Form Input" onClick={addInput} />
{formState?.map((val, idx) => {
const nameId = `name${idx}`;
const typeId = `type-${idx}`;
return (
<div key={val._id}>
{val.type === "text" && (
<>
<label htmlFor={nameId}>{`${val.name} #${idx + 1}`}</label>
<input
type="text"
name={nameId}
id={nameId}
className={val.type}
ref={register()}
/>
{/* <label htmlFor={typeId}>{`Type #${idx + 1}`}</label>
<select name={typeId} id={typeId} className={val.type}>
{data.allFormInputVals.data.map((item) => {
return (
<option key={item._id} value={item.type}>
{item.type}
</option>
);
})}
</select> */}
</>
)}
</div>
);
})}
<button type="submit">Save Form</button>
</form>
);
}
index.js
import { useQuery, gql, useMutation } from "#apollo/client";
import { useEffect, useState } from "react";
import { v4 as uuidv4 } from "uuid";
import Form from "../components/Form";
const INPUT_VALUES = gql`
query GetInputValues {
allFormInputVals {
data {
name
_id
type
}
}
}
`;
const Home = () => {
const blankFormInput = {
__typename: "FormInputVal",
name: "test",
_id: uuidv4(),
type: "text",
};
const [formState, setFormState] = useState([blankFormInput]);
const { loading, error, data } = useQuery(INPUT_VALUES);
useEffect(() => {
const formData = data?.allFormInputVals?.data;
setFormState(formData);
}, [data]);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<>
<Form formState={formState} setFormState={setFormState} />
</>
);
};
export default Home;
You could extract the form to its own component and only render it when the data is fetched. This way, when you use useForm in the child component, the default values will be set properly.
const Home = () => {
const { loading, error, data } = useQuery(INPUT_VALUES)
const blankFormInput = {
__typename: "FormInputVal",
name: "test",
_id: uuidv4(),
type: "text",
}
const [formState, setFormState] = useState([blankFormInput])
// other code
if (loading) {
return <p>Loading...</p>
}
return <MyForm defaultValues={formState} />
}
If you don't want to change the structure, you could set the input values using setValue when the data is ready.
useEffect(() => {
const formData = data?.allFormInputVals?.data
setFormState(formData)
formData?.forEach((item, idx) => {
setValue(`${item.name}${idx}`, 'whatever')
})
}, [data])
// index.js
import React, { Component } from "react";
import MaterialTable, { MTableEditRow } from "material-table";
import axios from "axios";
import DataModel from "./DataModel";
import TitleInput from "./TitleInput";
class Report extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
workOrderOptions: [],
newEntry: {
userId: "",
id: "",
title: "",
body: ""
}
};
this.handleNewTitle = this.handleNewTitle.bind(this);
this.cancelAdd = this.cancelAdd.bind(this);
}
renderData() {
const URL = "https://jsonplaceholder.typicode.com/posts";
axios
.get(URL)
.then(response => {
this.setState({
data: response.data
});
})
.catch(error => {
console.log("ERROR:", error);
});
}
// I want to fire this method upon canceling the "add row"
cancelAdd() {
this.setState({
newEntry: {
userId: "",
id: "",
title: "",
body: ""
}
});
}
handleNewTitle(title) {
this.setState({
newEntry: {
// ...this.state.newEntry.title,
title: title
}
});
}
componentDidMount() {
this.renderData();
}
render() {
const columns = [
{
title: "ID",
field: "id",
editable: "never"
},
{
title: "User ID",
field: "userId",
editable: "never"
},
{
title: "Title",
field: "title",
editable: "never"
},
{
title: "Body",
field: "body",
editable: "never"
}
];
if (this.state.data) {
return (
<div>
<MaterialTable
components={{
EditRow: props => {
return (
<div>
<TitleInput
value={this.state.newEntry.title}
title={this.handleNewTitle}
/>
{/* <BodyInput
value={this.state.newEntry.body}
body={this.handleNewBody}
/>, <UserIDInput />, etc... */}
<MTableEditRow
{...props}
data={this.state.newEntry}
// Is there a handleCancelAction (or something ma something)?
</div>
);
}
}}
editable={{
// Just a sample add
onRowAdd: newData =>
new Promise((resolve, reject) => {
const result = {
id: 15465,
userId: 87946542,
title: this.state.newEntry.title,
body: "Old man Santiago"
};
console.log(result);
const data = this.state.data;
data.push(result);
this.setState({
...this.state
});
resolve();
})
}}
data={this.state.data}
columns={columns}
title={"Title"}
/>
</div>
);
} else if (!this.state.data) {
return <div>Loading...</div>;
}
}
}
export default Report;
// TitleInput.js
import React, { Component } from "react";
class TitleInput extends Component {
constructor(props) {
super(props);
this.handleTitleChanges = this.handleTitleChanges.bind(this);
}
handleTitleChanges(event) {
const title = event.target.value;
this.props.title(title);
}
render() {
return (
<div>
<select onChange={this.handleTitleChanges}>
<option selected hidden />
<option value="Old Man and the Sea">Old Man and the Sea</option>
<option value="Where the Red Fern Grows">
Where the Red Fern Grows
</option>
<option value="Nineteen Eighty-Four">Nineteen Eighty-Four</option>
<option value="The Kite Runner">The Kite Runner</option>
</select>
</div>
);
}
}
export default TitleInput;
// DataModel.js
export const DataModel = {
userId: "",
id: "",
title: "",
body: ""
};
You can see the sandbox example here: https://codesandbox.io/embed/festive-engelbart-7ned7
<MTableEditRow
{...props}
data={this.state.newEntry}
// on the onEditingCanceled prop, you can access the cancel method
// in this instance, we're clearing the state and then calling the
// method provided by the prop to close the showAddRow, we're passing
// mode, which will return "add"
onEditingCanceled={(mode, rowData) => {
this.cancelAdd();
props.onEditingCanceled(mode);
}}
/>
Line 309, (onEditingCanceled): https://github.com/mbrn/material-table/blob/master/src/material-table.js
// index.js
import React, { Component } from "react";
import MaterialTable, { MTableEditRow } from "material-table";
import axios from "axios";
import DataModel from "./DataModel";
import TitleInput from "./TitleInput";
class Report extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
workOrderOptions: [],
newEntry: {
userId: "",
id: "",
title: "",
body: ""
}
};
this.handleNewTitle = this.handleNewTitle.bind(this);
this.cancelAdd = this.cancelAdd.bind(this);
}
renderData() {
const URL = "https://jsonplaceholder.typicode.com/posts";
axios
.get(URL)
.then(response => {
this.setState({
data: response.data
});
})
.catch(error => {
console.log("ERROR:", error);
});
}
// I want to fire this method upon canceling the "add row"
cancelAdd() {
this.setState({
newEntry: {
userId: "",
id: "",
title: "",
body: ""
}
});
}
handleNewTitle(title) {
this.setState({
newEntry: {
// ...this.state.newEntry.title,
title: title
}
});
}
componentDidMount() {
this.renderData();
}
render() {
const columns = [
{
title: "ID",
field: "id",
editable: "never"
},
{
title: "User ID",
field: "userId",
editable: "never"
},
{
title: "Title",
field: "title",
editable: "never"
},
{
title: "Body",
field: "body",
editable: "never"
}
];
if (this.state.data) {
return (
<div>
<MaterialTable
components={{
EditRow: props => {
return (
<div>
<TitleInput
value={this.state.newEntry.title}
title={this.handleNewTitle}
/>
{/* <BodyInput
value={this.state.newEntry.body}
body={this.handleNewBody}
/>, <UserIDInput />, etc... */}
<MTableEditRow
{...props}
data={this.state.newEntry}
// looks like there is with onEditingCanceled
onEditingCanceled={(mode, rowData) => {
this.cancelAdd();
props.onEditingCanceled(mode);
}}
/>
</div>
);
}
}}
editable={{
// Just a sample add
onRowAdd: newData =>
new Promise((resolve, reject) => {
const result = {
id: 15465,
userId: 87946542,
title: this.state.newEntry.title,
body: "Old man Santiago"
};
console.log(result);
const data = this.state.data;
data.push(result);
this.setState({
...this.state
});
resolve();
})
}}
data={this.state.data}
columns={columns}
title={"Title"}
/>
</div>
);
} else if (!this.state.data) {
return <div>Loading...</div>;
}
}
}
export default Report;
I'm trying to pass data in React from parent to child , I already managed to set right value from one file to another, but same that information that I passed I need to pass once more again. I will show you some code so you can understand actual problem.
From List.js file I'm taking the right information like
<Products categoryid={item.id}/>
so that same item.id I passed to Products, as you see I have this.props.categoryid which is giving me right information as value to add this item as you see, and it looks like
import React, { Component } from 'react'
import { getProducts, addItem, deleteItem, updateItem } from './ProductFunctions'
class Products extends Component {
constructor() {
super()
this.state = {
id: '',
title: '',
price: '',
off_price: '',
category_id: '',
arttitle: '',
artbody: '',
editDisabled: false,
items: []
}
this.onSubmit = this.onSubmit.bind(this)
this.onChange = this.onChange.bind(this)
}
componentDidMount() {
this.getAll()
}
onChange = e => {
this.setState({
[e.target.name]: e.target.value
})
}
getAll = () => {
getProducts().then(data => {
this.setState(
{
title: '',
price: '',
off_price: '',
category_id: this.props.categoryid,
items: [...data]
},
() => {
console.log(this.state.items)
}
)
})
}
So the real problem is how to pass this this.props.categoryid as a category_id to getProducts function in ProductFunctions.js so I can get list from ?
export const getProducts = category_id => {
return axios
.get('/api/products/${category_id}', {
headers: { 'Content-Type': 'application/json' }
})
.then(res => {
return res.data
})
}
It seems you forgot to use `` and instead used '' in the getProducts function in ProductFunctions.js, so let's correct that.
export const getProducts = category_id => {
return axios
.get(`/api/products/${category_id}`, {
headers: { "Content-Type": "application/json" }
})
.then(res => {
return res.data;
});
};
Now, just pass the categoryid you obtained from props to the getProducts in the getAll method, when its invoked. (As per what the exported function expects in ProductFunctions.js
getAll = () => {
const { categoryid } = this.props;
getProducts(categoryid).then(data => {
this.setState(
{
title: "",
price: "",
off_price: "",
category_id: categoryid,
items: [...data]
},
() => {
console.log(this.state.items);
}
);
});
};
Access the prop within getAll function
getAll = () => {
getProducts(this.props.categoryid).then(data => {
this.setState({
title: '',
price: '',
off_price: '',
category_id: this.props.categoryid,
items: [...data]
},
() => {
console.log(this.state.items)
}
)
})
}