How to extract data of cell clicked grid.js - javascript

I am using Grid.js to render a table in react. I need to extract the data in one of the cells. When I map the args, I get two results back....a MouseEvent and 'n' which contains the data that I need. How do I extract the data out of the 'n' result? Below is an image of what I receive from my current code which is below the picture.
import React, { useState, useEffect, useRef, Fragment } from 'react';
import axios from 'axios';
import { API } from '../../config';
import Layout from '../../components/Layout';
import { Grid, html, h } from 'gridjs';
import 'gridjs/dist/theme/mermaid.css';
const PendingUser = () => {
const [pendingUser, setPendingUser] = useState({});
const wrappedRef = useRef(null);
useEffect(() => {
getPendingUsers();
setPendingUser(pendingUser);
grid.render(wrappedRef.current);
}, []);
const getPendingUsers = async () => {
const { data } = await axios.get(`${API}/admin/pendinguser`);
await data.filter(user => {
user.accountApproved ? setPendingUser(user) : setPendingUser();
});
};
const handleClick = e => {
e.preventDefault();
const buttonValue = e.target.value;
console.log(buttonValue);
grid.on('rowClick', (...args) =>
args.map(data => {
console.log(data);
})
);
};
const grid = new Grid({
search: true,
columns: [
{
name: 'ID',
hidden: true
},
{
name: 'First Name'
},
{
name: 'Last Name'
},
{
name: 'Email'
},
{
name: 'Agency'
},
{
name: 'Approve',
formatter: (cell, row) => {
return h(
'button',
{
style: 'cursor: pointer',
className: 'py-2 mb-2 px-2 border rounded text-white bg-success',
value: 'approve',
onClick: e => handleClick(e, 'value')
},
'Approve'
);
}
},
{
name: 'Deny',
formatter: (cell, row) => {
return h(
'button',
{
styel: 'cursor: pointer',
className: 'py-2 mb-2 px-2 border rounded text-white bg-danger',
value: 'deny',
onClick: e => handleClick(e, 'value')
},
'Deny'
);
}
},
{
name: 'Denied Reason',
formatter: (_, row) =>
html(
'<select>' +
'<center><option value="Non Law Enforcement">Non Law Enforcement</option><option value="Non Law Enforcement">Non US Law Enforcement</option></center>' +
'</select>'
)
}
],
server: {
url: `${API}/admin/pendinguser`,
method: 'GET',
then: data =>
data.map(user => [
user._id,
user.firstName,
user.lastName,
user.email,
user.leAgency
])
}
});
return (
<Layout>
<div ref={wrappedRef} />
</Layout>
);
};
export default PendingUser;
here is what the 'n' data looks like and I have circled what I want to extract.

columns: [{ name: 'Name',
attributes: (cell) => {
// add these attributes to the td elements only
if (cell) {
return {
'data-cell-content':cell,
'onclick': () => alert(cell)
};
}
}},
This worked for me bro.

Related

Request to api works fine in component but not when using provider with react

When making a request to my API from a component and using react-data-table-component everything works perfectly but if I try to make the request from my Product Provider the pagination is incorrect and no longer works as expected.
With this code I make the request, datatable and pagination from my component working perfectly:
import React, { useState, useEffect, useCallback, useMemo } from "react";
import axiosClient from "../config/axiosClient";
import DataTable from 'react-data-table-component-with-filter'
import { CSVLink } from "react-csv"
import { Link } from 'react-router-dom'
import useProducts from "../hooks/useProducts";
const removeItem = (array, item) => {
const newArray = array.slice();
newArray.splice(newArray.findIndex(a => a === item), 1);
return newArray;
};
const ProductsTest = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [totalRows, setTotalRows] = useState(0);
const [perPage, setPerPage] = useState(10);
const [currentPage, setCurrentPage] = useState(1);
const [searchBox, setSearchBox] = useState('')
const STRING_TRADUCTIONS = { "KILOGRAM" : "KILOGRAMOS", "GRAMS" : "GRAMOS", "BOX" : "CAJA", "PACKAGE" : "PAQUETE", "BOTTLE" : "BOTE", "PIECES" : "PIEZAS", "BAG" : "BOLSA", "LITER" : "LITRO" }
const fetchUsers = async (page, limit = perPage, search = searchBox) => {
setLoading(true)
const dataOnLs = localStorage.getItem('cmtjs')
const config = {
headers: {
"Content-Type": "application/json",
apiKey: dataOnLs
} ,
params: {
limit,
page,
search
}
}
const response = await axiosClient(`/products`, config)
const data = response.data.products.docs.map( doc => (
{
_id: doc._id,
idProduct: doc.idProduct,
barCode: doc.barCode,
name: doc.name,
presentation: STRING_TRADUCTIONS[doc.presentation],
salePrice: doc.salePrice,
purchasePrice: doc.purchasePrice,
stock: doc.stock,
user: doc.user.username,
category: doc.category.name,
provider: doc.provider.name
}
))
setData(data);
setTotalRows(response.data.products.totalDocs);
setLoading(false);
};
useEffect(() => {
fetchUsers(1)
}, []);
const columns = useMemo(
() => [
{
name: "ID",
selector: "idProduct",
sortable: true
},
{
name: "Código de Barras",
selector: "barCode",
sortable: true
},
{
name: "Nombre",
selector: "name",
sortable: true
},
{
name: "Presentación",
selector: "presentation",
sortable: true
},
{
name: "Precio",
selector: "salePrice",
sortable: true
},
{
name: "Stock",
selector: "stock",
sortable: true
},
{ cell: row =>
<Link to={ `/dashboard/product/${row._id}`}>
<button className='btn btn-ghost text-xs'>
Mas
</button>
</Link>}
]
);
const handlePageChange = page => {
fetchUsers(page);
setCurrentPage(page);
};
const handlePerRowsChange = async (newPerPage, page) => {
fetchUsers(page, newPerPage);
setPerPage(newPerPage);
}
const headers = [
{ label: "ID", key: "idProduct" },
{ label: "Código de Barras", key: "barCode" },
{ label: "Nombre", key: "name" },
{ label: "Presentación", key: "presentation" },
{ label: "Precio Venta", key: "salePrice" },
{ label: "Precio Compra", key: "purchasePrice" },
{ label: "Stock", key: "stock" },
{ label: "Creador", key: "user" },
{ label: "Categoría", key: "category" },
{ label: "Proveedor", key: "provider" }
]
const paginationComponentOptions = {
rowsPerPageText: 'Mostrar',
rangeSeparatorText: 'de',
selectAllRowsItem: true,
selectAllRowsItemText: 'Todos',
};
const clear = () => {
setPerPage(10)
setSearchBox('')
fetchUsers(1, 10, '')
}
return (
<div>
<input type="text" onChange={(e)=> setSearchBox(e.target.value)}/>
<button onClick={ ()=> fetchUsers()}>Buscar</button>
<CSVLink data={data} headers={headers} filename={"productos.cdtmx.csv"} className="cursor-pointer">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABmJLR0QA/wD/AP+gvaeTAAACnUlEQVRoge2YXUhUQRiGn7HVRVddc8k0QawQw6hQohKSlsp+oDulQBGCbuxGQ1itDIx+IIWINKK86S4o6ibFEG9ywQzCEJLVSCylorYf1CJaXXe6SPvZ1ePZs3tczfNcfsP3zfvOzHc4M2BgYGAQSYTWxJSrReUg6oHEYHNtuRu1TDkupKx27Tp38+9glJZKv9AmPgQSpYiq9w+GYGBBxU8jrf6RUAwsCgwDkcYwEGlM/gFLVf4JkBcEWJQSvw+/Ua4cJYixWjElxoemcB4CDKgRrwqfZGJ0lImpqYChFe53IZefIeAIhUX8DDJsleZkyffA8jBgNkXTe+ouXy93U2Ev+R3PSE7jU70T96VHZNrSdROphCoDHu8kZ1quAVC1u4x4cxwAdQfLMZuiaei4xevPb/VTqYDqI9Ta56Rj4Ak2SxLHCw6zaU0Wxbl7Gfw4QlPnbT01KjLLZ3RuTj9oxJ61lQp7CYUbdiAQVN5rwOOd1EvfvATVxAMfXtHcdZ+k2ATy127hzrN2nIM9emlTRVA7AJAwff4BhJj/QmfpDuwNT0pCsNPOSVA7ULA+j7Jth3g63EfXUC9H8vazJ3t72MRoQbUBsymaK0UOhBCcbbtBbUsTUkoai2uIi4nVU6Miqg2c3HeM7NWZtPc/xjnYQ8+Ii9Y+JxnJadQUHtVToyKqDOSkrqPSXopP+jj/8M+jQF3bdby+KSrspWxOz9JNpBKqmtj1fojk6oKA+Ev3CCsdO8MuKhiWx7/QYmY2A9/CVt2n/4Vgth6oBS4Cod0FfVKa3Z4fgMd/yPb8i+ay/pma30ZTD+RoXl5rxiqtqbxo7vxH83/ZA0sKw0CkWdYGxsOmQj1j/gHNBoQQDhABBXVkTEocCzifgYGBgQp+AlpMnf09Cu/RAAAAAElFTkSuQmCC"/>
</CSVLink>
<DataTable
columns={columns}
data={data}
progressPending={loading}
pagination
paginationServer
paginationTotalRows={totalRows}
paginationDefaultPage={currentPage}
onChangeRowsPerPage={handlePerRowsChange}
onChangePage={handlePageChange}
selectableRows
//onSelectedRowsChange={({ selectedRows }) => console.log(selectedRows)}
paginationComponentOptions={paginationComponentOptions}
noDataComponent="No hay resultados"
/>
{
searchBox && searchBox !== '' && <button onClick={ () => clear() }>Limpiar</button>
}
</div>
)
}
But I have my product provider where I make a get request to all my products, avoiding making the requests from my component and having the data globally, but if I use "getProducts" from my provider, the first view of the datatable is correct however , when clicking on a page or next, the pager advances but the data displayed does not, for example: it shows me the first 10 records but I ask for the next 10 and the pager advances correctly but the data is still the first 10 records, No I know how to use my provider and make the pager show the following data depending on what the user needs.
This is the code of my provider to obtain the product data
const getProducts = async(page, limit, search) => {
const dataOnLs = localStorage.getItem('cmtjs')
const config = {
headers: {
"Content-Type": "application/json",
apiKey: dataOnLs
} ,
params: {
page,
limit,
search
}
}
try {
const { data } = await axiosClient(`/products`, config)
setProducts(data)
} catch (error) {
So in my component I call "getProducts" from my provider to have the products data in "products" using the useEffect hook
useEffect(() => {
getProducts()
setData(products.products?.docs)
setTotalRows(products.products?.totalDocs)
setLoading(false)
}, []);
In my paginator to obtain the following 10 product records, I click and the text changes that indicates which page is being shown, but the data remains the same as the first page
const handlePageChange = page => {
getProducts(page); // it does not show the next 10 records as it happened in the fetch of my component
setCurrentPage(page); // OK
};
In the same way, my browser no longer works using it in this way, I only changed the function to call my provider now, but it does not work
<input type="text" onChange={(e)=> setSearchBox(e.target.value)}/>
<button onClick={ ()=> getProducts()}>Buscar</button>
I would like to know if you can help me to make my datatable and browser work using my provider. Thanks.
In this code
useEffect(() => {
getProducts()
setData(products.products?.docs)
setTotalRows(products.products?.totalDocs)
setLoading(false)
}, []);
You are calling getProducts(), which is asynchronous. Then you try setData(products...), but the asynchronous call did not finish yet, so products was not updated yet. When eventually the asynchronous code terminates, the useEffect statement is not triggered again, because the dependency array states that the effect is only executed when the component mounts.
Split up your effect in two parts instead, so the second effect gets triggered when new products are available:
useEffect(() => {
getProducts()
}, []);
useEffect(() => {
setData(products.products?.docs)
setTotalRows(products.products?.totalDocs)
setLoading(false)
}, [products]);

"Missing config for event" using #xstate/test

I'm testing a state machine using model-based testing using #xstate/test and #testing-library/react.
Basically, I'm testing this machine:
const itemDamagedMachine = createMachine({
initial: 'newModal',
context: {
productScan: '',
binScan: '',
},
states: {
newModal: {
initial: 'scanDamagedItem',
states: {
scanDamagedItem: {},
scanDamagedBin: {},
declareItemDamaged: {},
},
},
closed: {},
},
on: {
UPDATE_PRODUCT_SCAN: {
actions: assign({
productScan: 123456,
}),
},
VALIDATE: {
target: 'newModal.scanDamagedBin',
},
UNREADABLE: {
target: 'newModal.scanDamagedBin',
},
CANCEL: {
target: 'closed',
},
UPDATE_DAMAGED_BIN_SCAN: {
actions: assign({
binScan: 'PB_DAMAGED',
}),
},
},
});
I'm then configuring the model, and testing it using const testPlans = itemDamagedModel.getSimplePathPlans();.
Everything seems to run smoothly with about 200 passing tests, but I'm having a few issues:
For each of my test and each of my event, I'm getting a warning Missing config for event "VALIDATE". I don't understand what it's supposed to mean.
All of my tests are validated even if I make typos on purpose in my model event. Sometimes the number of tests is reduced, but I would have hoped to see a few warnings when the model doesn't find a particular input or button.
The tests are all passing, even if I'm passing an empty div as my xstate/test rendered component.
I do not get the idea, but I have tested a component as follow:
First I have my machine:
import { createMachine, sendParent } from 'xstate';
export const machineDefinition = {
id: 'checkbox',
initial: 'unchecked',
states: {
unchecked: {
on: {
TOGGLE: [
{
actions: [ 'sendParent' ],
target: 'checked',
},
],
},
},
checked: {
on: {
TOGGLE: [
{
actions: [ 'sendParent' ],
target: 'unchecked',
},
],
},
},
},
};
const machineOptions = {
actions: {
sendParent: sendParent((context, event) => event.data),
},
};
export default createMachine(machineDefinition, machineOptions);
Second, I have extended the render method of testing-library
import React from 'react'
import HelmetProvider from 'react-navi-helmet-async'
import SpinnerProvider from '#atoms/GlobalSpinner'
import AlertProvider from '#molecules/GlobalAlert'
import InternationalizationProvider from '#internationalization/InternationalizationProvider'
import { render as originalRender } from '#testing-library/react'
const render = (ui, { locale = 'es', ...renderOptions } = {}) => {
const Wrapper = ({ children }) => {
return (
<InternationalizationProvider>
<AlertProvider>
<SpinnerProvider>
<HelmetProvider>
{children}
</HelmetProvider>
</SpinnerProvider>
</AlertProvider>
</InternationalizationProvider>
)
}
return originalRender(ui, { wrapper: Wrapper, ...renderOptions })
}
export * from '#testing-library/react'
export { render }
Finally, I have created the test
import React from 'react';
import { produce } from 'immer';
import { machineDefinition } from '#stateMachines/atoms/checkbox';
import { createMachine } from 'xstate';
import { createModel } from '#xstate/test';
import { render, cleanup, fireEvent } from '#root/jest.utils';
import Checkbox from '#atoms/Checkbox';
const getMachineDefinitionWithTests = () => produce(machineDefinition, (draft) => {
draft.states.unchecked.meta = {
test: ({ getByTestId }) => {
expect(getByTestId('checkbox-child-3')).toHaveClass('w-8 h-4 rounded-md duration-500 bg-dark-300 dark:bg-accent-100');
},
};
draft.states.checked.meta = {
test: ({ getByTestId }) => {
expect(getByTestId('checkbox-child-3')).toHaveClass('w-8 h-4 rounded-md duration-500 bg-dark-300 dark:bg-accent-100');
expect(getByTestId('checkbox-child-3.1')).toHaveClass('bg-light-100 w-4 h-4 rounded-full duration-500 dark:transform dark:translate-x-full');
},
};
});
const getEvents = () => ({
TOGGLE: {
exec: ({ getByTestId }) => {
fireEvent.click(getByTestId('checkbox-container'));
},
cases: [ {} ],
},
});
describe('checkbox', () => {
const machine = createMachine(getMachineDefinitionWithTests(), {
actions: {
sendParent: () => {},
},
});
const machineModel = createModel(machine)
.withEvents(getEvents());
const testPlans = machineModel.getSimplePathPlans();
testPlans.forEach((plan) => {
describe(plan.description, () => {
afterEach(cleanup);
plan.paths.forEach((path) => {
it(path.description, () => {
const rendered = render(
<Checkbox
test
label='main.txt1'
data={{}}
machine={machine}
/>,
{ locale: 'en' },
);
return path.test(rendered);
});
});
});
});
describe('coverage', () => {
it('should have full coverage', () => {
machineModel.testCoverage();
});
});
});
I have created a react boilerplate which contains XState, there you can find the previous test

Can't get pass the -> TypeError: Cannot read property 'id' of undefined at production build

Long story short, I have a table where I've build a searching functionality using the following code to search in the object arrays and update the state using hooks.
const SearchView = (e) => {
e.preventDefault();
console.log(e.target.value)
if (!e.target.value) {
setSearchDataSuggestions([])
setSearchField(null)
} else {
setSearchField(true)
props.setSeachingView(true)
for (const row of Object.values(rows)) {
Object.keys(row).forEach(function (item, index) {
if (typeof(row[item]) === 'string' && row[item].toLowerCase().includes(e.target.value.toLowerCase().trim())) {
setSearchDataSuggestions([...search_data_suggestions, (rows[index]) ])
}
});
}
}
}
The code works as fine in the npm start but wont work at production build ... Whenever I try to type something into the text field (where the SearchView() is called onChange) it crashes on a blank page along the following console error:
Console Error
I've no idea where this error is telling me ... Since there's no .id being passed whatsoever in my code. By any chance, I'm posting the entire code here anyways.
Can someone please help me identify where is the bug trigger and why it works fine in a dev server and not in prod !??!
Full code goes below:
import React, { useState, useEffect } from 'react';
import DataTable from 'react-data-table-component';
import moment from 'moment'
import TextField from '#material-ui/core/TextField';
import InputAdornment from '#material-ui/core/InputAdornment';
const LookUpTable = (props) => {
const [error, setError] = useState(null);
const [isLoaded, setIsLoaded] = useState(false);
const [rows, setItems] = useState([]);
const [search_data_suggestions, setSearchDataSuggestions] = useState([]);
const [accessToken] = useState(props.accessToken)
const [isSearching] = useState(props.isSearching);
const [search_field, setSearchField] = useState(null);
const success_validation = row_success => {
if (row_success) {
return "True";
} else {
return "False";
}
};
const columns = [
{
name: 'Timestamp',
selector: 'timestamp',
sortable: true,
format: row => moment(row.timestamp).format('lll'),
},
{
name: 'Project ID',
selector: 'project_id',
sortable: true,
},
{
name: 'Client Name',
selector: 'client_name',
sortable: true,
right: true,
},
{
name: 'Client Email',
selector: 'client_email',
sortable: true,
right: true,
},
{
name: 'Client Mobile',
selector: 'client_mobile',
sortable: true,
},
{
name: 'Sent By',
selector: 'sent_by',
sortable: true,
},
{
name: 'Success',
selector: 'success_validation',
sortable: true,
right: true,
format: row => success_validation(row.success),
},
];
const ExpanableComponent = ({ data }) => {
return(
<div>
<p></p>
<ul>
<li><strong>Report Filename: </strong>{data.file_name} </li>
<li><strong>Project Description: </strong>{data.project_desc} </li>
<li><strong>Project Owner's Name: </strong>{data.project_owner_name} </li>
<li><strong>Project Owner's Email: </strong>{data.project_owner_email} </li>
</ul>
</div>
)
}
const SearchView = (e) => {
e.preventDefault();
console.log(e.target.value)
// setSearchValue(e.target.value.toLowerCase())
// const values = (Object.values(rows));
if (!e.target.value) {
setSearchDataSuggestions([])
setSearchField(null)
} else {
setSearchField(true)
props.setSeachingView(true)
for (const row of Object.values(rows)) {
Object.keys(row).forEach(function (item, index) {
// console.log('[' + index + '] ' + 'keys: ' + item + ' values : ' + row[item]);
if (typeof(row[item]) === 'string' && row[item].toLowerCase().includes(e.target.value.toLowerCase().trim())) {
setSearchDataSuggestions([...search_data_suggestions, (rows[index])])
// console.log('Got search as: ' + e.target.value + ' and updated with the row: ' + (rows[index]) )
}
});
}
}
}
const CustonSearchViewRender = () => {
if (search_field) {
return (
<DataTable
columns={columns}
data={search_data_suggestions}
highlightOnHover={true}
pagination={true}
fixedHeader={true}
expandableRows={true}
expandableRowsComponent={<ExpanableComponent />}
striped={true}
/>
)
}
}
// Note: the empty deps array [] means
// this useEffect will run once
// similar to componentDidMount()
useEffect(() => {
fetch("/lookup/", {
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`,
}
}
)
.then(res => res.json())
.then(
(result) => {
setIsLoaded(true);
setItems(result);
},
// Note: it's important to handle errors here
// instead of a catch() block so that we don't swallow
// exceptions from actual bugs in components.
(error) => {
setIsLoaded(true);
setError(error);
}
)
}, [accessToken])
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className='lookup-table container-fluid'>
<div className="search-bar container">
<br></br>
<h4 className="search-bar-title">Past 90 days report table lookup ...</h4>
<TextField
label="Search me"
onChange={e => SearchView(e)}
variant="outlined"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<i className="fas fa-search"></i>
</InputAdornment>
)
}}
/>
</div>
{isSearching && !search_field?
<DataTable
columns={columns}
data={rows}
highlightOnHover={true}
pagination={true}
fixedHeader={true}
expandableRows={true}
expandableRowsComponent={<ExpanableComponent />}
striped={true}
/> : null}
{search_field ? <CustonSearchViewRender/> : null}
</div>
);
}
}
export default LookUpTable;
Thank you so much.

React dispatch is not defined remove action

i have a problem with my actionsFormatter.
When I click on the DELETE button, I get the error:
Uncaught ReferenceError: dispatch is not defined at onClick
How could I fix this problem?
import { removeEnvironnement } from '../../actions/environnement';
const EnvironnementList = (props) => (
<BootstrapTable
keyField='id'
data={ props.store.environnements }
columns={ columns }
selectRow={selectRow}
pagination={ paginationFactory() }
filter={ filterFactory() }
striped hover condensed
/>
);
const actionsFormatter = (cell, row) => {
const id=row.id
return (
<button className="btn btn-danger"
onClick={() => {
dispatch(removeEnvironnement({ id }));}}
>Delete</button>
);
};
const columns = [{
dataField: 'id',
text: 'ID'
}, {
dataField: 'nom',
text: 'Nom',
filter: textFilter()
}, {
dataField: 'actions',
text: 'Action',
formatter: actionsFormatter
} ];
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
bgColor: '#00BFFF'
};
const mapStateToProps = (state) => {
return {
store: state
};
}
export default connect(mapStateToProps)(EnvironnementList);
Here is my code to do the remove :
Should I remove the dispatch part?
const _removeEnvironnement = ({ id } = {}) => ({
type: 'REMOVE_ENVIRONNEMENT',
id
});
export const removeEnvironnement = ({ id } = {}) => {
return (dispatch) => {
return axios.delete(`environnements/${id}`).then(() => {
dispatch(_removeEnvironnement({ id }));
})
}
};
What is dispatch in your actionsFormatter? It is defined neither on actionsFormatter scope nor on out of actionsFormatter scope. That's the problem and that's the javascript interpreter talking you about.
One of the possible fix is to import you redux store
store.js
export const store = createStore(...)
EnvironmentList.js
import { store } from './path/to/store.js'
// ...
const actionsFormatter = (cell, row) => {
const { dispatch } = store
const id = row.id
// ...
};
This way you'll get dispatch available in actionsFormatter body.
Another way is to provide mapped method via connect -> EnvironmentList -> actionsFormatter chain. Do what Arnaud Christ suggested in his reply and then refactor the code:
const EnvironmentList = (props) => (
<BootstrapTable
keyField='id'
data={ props.store.environnements }
columns={ columns(props.removeEnvironment) }
selectRow={selectRow}
pagination={ paginationFactory() }
filter={ filterFactory() }
striped hover condensed
/>
);
const actionsFormatter = (removeEnvironment) => (cell, row) => {
const id=row.id
return (
<button className="btn btn-danger"
onClick={() => {
removeEnvironment({ id });
}}
>Delete</button>
);
};
const columns = (removeEnvironment) => [{
dataField: 'id',
text: 'ID'
}, {
dataField: 'nom',
text: 'Nom',
filter: textFilter()
}, {
dataField: 'actions',
text: 'Action',
formatter: actionsFormatter(removeEnvironment)
} ];
So, the connected EnvironmentList got necessary removeEnvironment method on it's props. Then we passes it to columns creator, which passed it to actionsFormatter creator.
You have to link your component with the dispatch method.
As you are already using react-redux to connect your component to your Redux store, you can easily do that through mapping dispatch to props.
Just add the following:
const mapStateToProps = (state) => {
return {
store: state
};
}
const mapDispatchToProps = dispatch => {
return {
removeEnvironnement: id => {
dispatch(removeEnvironnement({ id }));
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(EnvironnementList);
And then in your onClick handler, just call this.props.removeEnvironnement(id)

Antd filtering not working correctly, client code is executed but no filtering happeans

I am trying to follow this page sample:
https://ant.design/components/table/
The antd filtering sample to be precise
I have a column which I know its 2 possible values only.
I can see in the debugger that the handlechange event is executed, but after click OK in the filter, the table is not filtered as it should
My best guess I am missing something on the OnFilter event
import React, { Component } from 'react';
import { Table, Tag, Button} from 'antd';
import { adalApiFetch } from '../../adalConfig';
import Notification from '../../components/notification';
class ListPageTemplatesWithSelection extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
filteredInfo: null,
sortedInfo: null,
};
this.handleChange= this.handleChange.bind(this);
this.clearFilters= this.clearFilters.bind(this);
this.clearAll= this.clearAll.bind(this);
}
handleChange(pagination, filters, sorter){
console.log('Various parameters', pagination, filters, sorter);
this.setState({
filteredInfo: filters,
sortedInfo: sorter,
});
}
clearFilters(){
this.setState({ filteredInfo: null });
}
clearAll(){
this.setState({
filteredInfo: null,
sortedInfo: null,
});
}
fetchData = () => {
adalApiFetch(fetch, "/PageTemplates", {})
.then(response => response.json())
.then(responseJson => {
if (!this.isCancelled) {
const results= responseJson.map(row => ({
key: row.Id,
Name: row.Name,
SiteType: row.SiteType,
Tags: row.Tags
}))
this.setState({ data: results });
}
})
.catch(error => {
console.error(error);
});
};
componentDidMount(){
this.fetchData();
}
render(){
let { sortedInfo, filteredInfo } = this.state;
sortedInfo = sortedInfo || {};
filteredInfo = filteredInfo || {};
const columns = [
{
title: 'Id',
dataIndex: 'key',
key: 'key',
},
{
title: 'Name',
dataIndex: 'Name',
key: 'Name',
},
{
title: 'Site Type',
dataIndex: 'SiteType',
key: 'SiteType',
filters: [
{ text: 'Modern Team Site', value: 'Modern Team Site' },
{ text: 'CommunicationSite', value: 'CommunicationSite' },
],
filteredValue: filteredInfo.name || null,
onFilter: (value, record) => record.Tags.includes(value),
},{
title: 'Tags',
key: 'Tags',
dataIndex: 'Tags',
render: Tags => (
<span>
{Tags && Tags.map(tag => {
let color = tag.length > 5 ? 'geekblue' : 'green';
if (tag === 'loser') {
color = 'volcano';
}
return <Tag color={color} key={tag}>{tag.toUpperCase()}</Tag>;
})}
</span>
),
}
];
const rowSelection = {
selectedRowKeys: this.props.selectedRows,
onChange: (selectedRowKeys) => {
this.props.onRowSelect(selectedRowKeys);
}
};
return (
<div>
<Button onClick={this.clearFilters}>Clear filters</Button>
<Button onClick={this.clearAll}>Clear filters and sorters</Button>
<Table rowSelection={rowSelection} columns={columns} dataSource={this.state.data} onChange={this.handleChange} />
</div>
);
}
}
export default ListPageTemplatesWithSelection;
In your SiteType column, you have mistakenly set filteredValue prop to filteredInfo.name. But the filter is not on a name column, it is on SiteType column.
Change this line from:
filteredValue: filteredInfo.name || null,
To:
filteredValue: filteredInfo.SiteType || null,
And it should be fine.
You need execute the fetchData function in the handleChange function. Add filter params to ajax request. Just like this:
handleTableChange = (pagination, filters, sorter) => {
const pager = { ...this.state.pagination };
pager.current = pagination.current;
this.setState({
pagination: pager,
});
this.fetch({
results: pagination.pageSize,
page: pagination.current,
sortField: sorter.field,
sortOrder: sorter.order,
...filters,
});
}

Categories

Resources