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.
Related
I need to have an editor field, for which I have used react-quill, but I need it to show suggestions when a user types something inside the editor. Now the react-autosuggest has a prop called 'renderInputComponent' to which we can pass an input component. But the problem is, that it doesn't work with react-quill. When I pass a react-quill component to the autosuggest, it doesn't call the onSuggestionsFetchRequested method and doesn't display the suggested results.
This is my autosuggest component:
import React, { useState } from 'react';
import Autosuggest from 'react-autosuggest';
import { quillModules, quillFormats } from 'constants/defaultValues';
import ReactQuill from 'react-quill';
const getSuggestionValue = (suggestion) => suggestion.name;
const renderSuggestion = (suggestion) => <div>{suggestion.name}</div>;
const ReactAutoSuggest = ({ data, value, placeholder, onChange }) => {
const [valueState, setValueState] = useState(value);
const [dataState] = useState(data || []);
const [suggestions, setSuggestions] = useState([]);
const getSuggestions = (val) => {
if (val) {
const inputValue = val.trim().toLowerCase();
const inputLength = inputValue.length;
return inputLength === 0
? []
: dataState.filter(
(d) => d.name.toLowerCase().slice(0, inputLength) === inputValue
);
}
return dataState;
};
const changeInput = (val, result) => {
setValueState(val);
onChange(val);
};
const onSuggestionsFetchRequested = ({ value: val }) => {
setSuggestions(getSuggestions(val));
};
const onSuggestionsClearRequested = () => {
setSuggestions([]);
};
const inputProps = {
placeholder: placeholder || '',
value: valueState,
onChange: changeInput,
};
const EditorInput = () => {
return (
<ReactQuill
value={valueState}
theme="snow"
name="emailPayload"
onChange={(val) => {
//val is the value generated from react-quil, for example if you
//type s inside react-quill, val would be '<p>s</p>'
let doc = new DOMParser().parseFromString(val, 'text/xml');
let result = doc.firstChild.innerHTML;
//result is the text value extracted from val, for example
//if you type s in react-quill, result would be 's' itself
changeInput(val, result);
}}
modules={quillModules}
formats={quillFormats}
/>
);
};
return (
<Autosuggest
renderInputComponent={EditorInput}
suggestions={suggestions}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={inputProps}
theme={{
container: 'autosuggest',
input: 'form-control',
inputOpen: 'react-autosuggest__input--open',
suggestionsContainer: 'react-autosuggest__suggestions-container',
suggestionsContainerOpen:
'react-autosuggest__suggestions-container--open',
suggestionsList: `react-autosuggest__suggestions-list ${
suggestions.length ? 'show' : ''
}`,
suggestionFocused: 'active',
suggestion: 'react-autosuggest__suggestion',
}}
/>
);
};
export default ReactAutoSuggest;
This is how I used my ReactAutoSuggest component:
<ReactAutoSuggest
value={suggestion}
onChange={(e) => {
setSuggestions(e);
}}
data={[
{
name: 'apple',
},
{
name: 'banana',
},
{
name: 'pear',
},
{
name: 'cherry',
},
]}
/>
where 'suggestion' is a simple state:
const [suggestion, setSuggestions] = useState('');
In case you need to know, inside the ReactAutoSuggest I have used 2 constant values quillModules, quillFormats which are:
export const quillModules = {
toolbar: [
['bold', 'italic', 'underline', 'strike', 'blockquote'],
[
{ list: 'ordered' },
{ list: 'bullet' },
{ indent: '-1' },
{ indent: '+1' },
],
['link', 'image'],
['clean'],
],
};
export const quillFormats = [
'header',
'bold',
'italic',
'underline',
'strike',
'blockquote',
'list',
'bullet',
'indent',
'link',
'image',
];
How do I make the suggestion list appear inside in the react-quill component?
I define a const varible that contains table columns, which was needed to invoke the function in react component. This is my code snippet looks like:
const columns = [
{
title: 'ID',
dataIndex: 'id',
key: 'id'
},
{
title: 'edit',
key: 'action',
render: (text, record) => (
<span>
<Button type='link'>detail</Button>
<Divider type='vertical' />
<Button onClick={this.editApp} type='link'>edit</Button>
</span>
)
}
]
class App extends Component {
state = {
loading: false,
pageNum: 1,
pageSize: 10,
isAddModalVisible: false,
isEditModalVisible: true
}
enterLoading = () => {
this.setState({
loading: true
})
}
editApp = () => {
this.setState({
isAddModalVisible: true
})
}
}
when I run this code, tell me that:
TypeError: Cannot read properties of undefined (reading 'editApp')
What should I do to invoke this function in const columns? I tried to move the columns into the component but still did not work. This is my full code of this component:
import React, { Component } from 'react'
import CustomBreadcrumb from '#/components/CustomBreadcrumb'
import { Layout, Divider, Row, Col, Table, Button, notification, Form, message } from 'antd'
import '#/style/view-style/table.scss'
import { withRouter } from 'react-router-dom'
import { getAppList, addApp } from '#/service/global/AppService'
import moment from 'moment'
import AddApp from './crud/AddApp'
import EditApp from './crud/EditApp'
const columns = [
{
title: 'ID',
dataIndex: 'id',
key: 'id'
},
{
title: '应用名',
dataIndex: 'app_name',
key: 'app_name'
},
{
title: '应用编号',
dataIndex: 'app_id',
key: 'app_id'
},
{
title: '应用英文缩写',
dataIndex: 'app_abbr',
key: 'app_abbr'
},
{
title: '用户数',
dataIndex: 'user_count',
key: 'user_count'
},
{
title: '上线状态',
dataIndex: 'online_status',
key: 'online_status',
render: (text, record) => <span>{record.online_status === 1 ? '已上线' : '未上线'}</span>
},
{
title: '创建时间',
dataIndex: 'created_time',
key: 'created_time',
render: text => <span>{moment.unix(parseInt(text) / 1000).format('YYYY-MM-DD HH:mm:ss')}</span>
},
{
title: '备注',
dataIndex: 'remark',
key: 'remark'
},
{
title: '操作',
key: 'action',
render: (text, record) => (
<span>
<Button type='link'>详情</Button>
<Divider type='vertical' />
<Button onClick={this.editApp} type='link'>编辑</Button>
</span>
)
}
]
class App extends Component {
state = {
loading: false,
pageNum: 1,
pageSize: 10,
isAddModalVisible: false,
isEditModalVisible: true
}
enterLoading = () => {
this.setState({
loading: true
})
}
addApp = () => {
this.setState({
isAddModalVisible: true
})
}
editApp = () => {
this.setState({
isEditModalVisible: true
})
}
onPageChange = current => {
this.setState({
pageNum: current
})
let request = {
pageSize: this.state.pageSize,
pageNum: current
}
getAppList(request)
}
changePageSize(pageSize, current) {
this.setState({
pageSize: pageSize
})
let request = {
pageSize: pageSize,
pageNum: this.state.pageNum
}
getAppList(request)
}
onAddModalCancelClick = (rowData = {}) => {
const { isAddModalVisible } = this.state
this.setState({ isAddModalVisible: !isAddModalVisible })
}
onCreateApp = values => {
let params = {
appName: values.appName,
appAbbr: values.appAbbr
}
addApp(params)
}
componentDidMount() {
let request = {
pageSize: this.state.pageSize,
pageNum: this.state.pageNum
}
getAppList(request)
}
componentWillUnmount() {
notification.destroy()
this.timer && clearTimeout(this.timer)
}
render() {
let data = this.props.app.app.list
let apps = this.props.app.app
if ((data && Object.keys(data).length === 0) || data === undefined) {
return <div></div>
}
let total = parseInt(apps.pagination.total)
const paginationProps = {
showSizeChanger: true,
showQuickJumper: true,
pageSize: apps.pagination.pageSize,
pageSizeOptions: ['10', '20', '30'],
showTotal: () => `共${total}条`,
current: apps.pagination.pageNum,
total: total,
onShowSizeChange: (current, pageSize) => this.changePageSize(pageSize, current),
onChange: current => this.onPageChange(current)
}
return (
<Layout>
<div>
<CustomBreadcrumb arr={['应用', '全局', '应用']}></CustomBreadcrumb>
</div>
<Row>
<Col>
<div className='base-style'>
<h3 id='basic'>应用管理</h3>
<Divider />
<Button
type='primary'
onClick={this.addApp}
shape='round'
style={{ width: 90, marginRight: 8 }}>
添加应用
</Button>
<Table columns={columns} dataSource={data} pagination={paginationProps} rowKey='id' />
<AddApp
visible={this.state.isAddModalVisible}
onVisibleChange={this.onAddModalCancelClick}
onCreate={this.onCreateApp}
{...{ data }}
/>
<EditApp
visible={this.state.isEditModalVisible}
onVisibleChange={this.onAddModalCancelClick}
onCreate={this.onCreateApp}
{...{ data }}
/>
</div>
</Col>
</Row>
</Layout>
)
}
}
export default withRouter(App)
You can't access funtion outside its lexical scope
import React, { Component } from "react";
import CustomBreadcrumb from "#/components/CustomBreadcrumb";
import {
Layout,
Divider,
Row,
Col,
Table,
Button,
notification,
Form,
message,
} from "antd";
import "#/style/view-style/table.scss";
import { withRouter } from "react-router-dom";
import { getAppList, addApp } from "#/service/global/AppService";
import moment from "moment";
import AddApp from "./crud/AddApp";
import EditApp from "./crud/EditApp";
class App extends Component {
state = {
loading: false,
pageNum: 1,
pageSize: 10,
isAddModalVisible: false,
isEditModalVisible: true,
};
enterLoading = () => {
this.setState({
loading: true,
});
};
addApp = () => {
this.setState({
isAddModalVisible: true,
});
};
editApp = () => {
this.setState({
isEditModalVisible: true,
});
};
onPageChange = (current) => {
this.setState({
pageNum: current,
});
let request = {
pageSize: this.state.pageSize,
pageNum: current,
};
getAppList(request);
};
changePageSize(pageSize, current) {
this.setState({
pageSize: pageSize,
});
let request = {
pageSize: pageSize,
pageNum: this.state.pageNum,
};
getAppList(request);
}
onAddModalCancelClick = (rowData = {}) => {
const { isAddModalVisible } = this.state;
this.setState({ isAddModalVisible: !isAddModalVisible });
};
onCreateApp = (values) => {
let params = {
appName: values.appName,
appAbbr: values.appAbbr,
};
addApp(params);
};
componentDidMount() {
let request = {
pageSize: this.state.pageSize,
pageNum: this.state.pageNum,
};
getAppList(request);
}
componentWillUnmount() {
notification.destroy();
this.timer && clearTimeout(this.timer);
}
render() {
let data = this.props.app.app.list;
let apps = this.props.app.app;
if ((data && Object.keys(data).length === 0) || data === undefined) {
return <div></div>;
}
let total = parseInt(apps.pagination.total);
const paginationProps = {
showSizeChanger: true,
showQuickJumper: true,
pageSize: apps.pagination.pageSize,
pageSizeOptions: ["10", "20", "30"],
showTotal: () => `共${total}条`,
current: apps.pagination.pageNum,
total: total,
onShowSizeChange: (current, pageSize) =>
this.changePageSize(pageSize, current),
onChange: (current) => this.onPageChange(current),
};
const columns = [
{
title: "ID",
dataIndex: "id",
key: "id",
},
{
title: "应用名",
dataIndex: "app_name",
key: "app_name",
},
{
title: "应用编号",
dataIndex: "app_id",
key: "app_id",
},
{
title: "应用英文缩写",
dataIndex: "app_abbr",
key: "app_abbr",
},
{
title: "用户数",
dataIndex: "user_count",
key: "user_count",
},
{
title: "上线状态",
dataIndex: "online_status",
key: "online_status",
render: (text, record) => (
<span>{record.online_status === 1 ? "已上线" : "未上线"}</span>
),
},
{
title: "创建时间",
dataIndex: "created_time",
key: "created_time",
render: (text) => (
<span>
{moment.unix(parseInt(text) / 1000).format("YYYY-MM-DD HH:mm:ss")}
</span>
),
},
{
title: "备注",
dataIndex: "remark",
key: "remark",
},
{
title: "操作",
key: "action",
render: (text, record) => (
<span>
<Button type="link">详情</Button>
<Divider type="vertical" />
<Button onClick={this.editApp} type="link">
编辑
</Button>
</span>
),
},
];
return (
<Layout>
<div>
<CustomBreadcrumb arr={["应用", "全局", "应用"]}></CustomBreadcrumb>
</div>
<Row>
<Col>
<div className="base-style">
<h3 id="basic">应用管理</h3>
<Divider />
<Button
type="primary"
onClick={this.addApp}
shape="round"
style={{ width: 90, marginRight: 8 }}
>
添加应用
</Button>
<Table
columns={columns}
dataSource={data}
pagination={paginationProps}
rowKey="id"
/>
<AddApp
visible={this.state.isAddModalVisible}
onVisibleChange={this.onAddModalCancelClick}
onCreate={this.onCreateApp}
{...{ data }}
/>
<EditApp
visible={this.state.isEditModalVisible}
onVisibleChange={this.onAddModalCancelClick}
onCreate={this.onCreateApp}
{...{ data }}
/>
</div>
</Col>
</Row>
</Layout>
);
}
}
export default withRouter(App);
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
I have the following code which renders a table with antd component.
I created a fetchdata that is returning some information correctly
Code:
import React, { Component } from 'react';
import { Table} from 'antd';
import { adalApiFetch } from '../../adalConfig';
class ListTenants extends Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
fetchData = () => {
adalApiFetch(fetch, "/Tenant", {})
.then(response => response.json())
.then(responseJson => {
if (!this.isCancelled) {
this.setState({ data: responseJson });
}
})
.catch(error => {
console.error(error);
});
};
componentDidMount(){
this.fetchData();
}
render() {
const columns = [{
title: 'Tenant Id',
dataIndex: 'TenantId',
key: 'TenantId'
}, {
title: 'Tenant Url',
dataIndex: 'TenantUrl',
key: 'TenantUrl',
}];
const data = [{
TenantId: '1',
TenantUrl: 'John Brown'
}, {
TenantId: '2',
TenantUrl: 'Jim Green'
}, {
TenantId: '3',
TenantUrl: 'Joe Black'
}];
return (
<Table columns={columns} dataSource={data} />
);
}
}
export default ListTenants;
How do I convert the json received to columns and data?
Assuming your question is how to render the object to match the keys in your Table data object, something like this should work:
repl here: https://repl.it/repls/FabulousWiryLicensing
This will give you the idea, but the cleaner solution is to map the responseJson object you're getting back from the API call and setState with that.
```
class App extends Component {
constructor (props) {
super (props)
this.state = {
returnedData: [{
ClientId: '1',
Id: 'abc',
TenantDomainUrl: 'https://example.com'
}, {
ClientId: '2',
Id: 'abc',
TenantDomainUrl: 'https:example2.com'
}]
}
}
render() {
const { returnedData } = this.state;
const data = returnedData.map(row => ({
TenantId: row.Id,
TenantUrl: row.TenantDomainUrl
}))
const columns = [{
title: 'Tenant Id',
dataIndex: 'TenantId',
key: 'TenantId'
}, {
title: 'Tenant Url',
dataIndex: 'TenantUrl',
key: 'TenantUrl',
}];
return (
<div>
<h1>test</h1>
<Table columns={columns} dataSource={data} />
</div>
);
}
}
```
I try to implement global search with new material ui next table component, I have handleSearch method, wich recives event, and than I use regexp to check if event.target.value the same as in table. But when I delete string in search, the columns not update. It starts to search only I start type. How to search by number not only by string in this case
const columns = [
{
dataKey: 'deviceType',
label:'Device Type',
numeric: false,
}, {
dataKey: 'deviceID',
label:'Device ID',
sortable: true,
numeric: true,
// cellRenderer: ({item, key}) =>
// <Button >Default</Button>,
}, {
........
}]
const data = [
{ key: 1, deviceType: 'Tag', deviceID: 1, name:'Tag For sending an ', location: 'Room_104', status: 'assigned'},
{ key: 2, deviceType: 'Tag', deviceID: 2, name:'Tag For sending an ', location: 'Room_104', status: 'assigned'},
{.......},
]
class EnhancedTable extends Component {
state = {
selected: [],
data,
order: {
direction: 'asc',
by: 'deviceID',
},
search: '',
}
handleSearch = event => {
debugger
const {data} = this.state
let filteredDatas = []
filteredDatas = data.filter(e => {
let mathedItems = Object.values(e)
let returnedItems
mathedItems.forEach(e => {
const regex = new RegExp(event.target.value, 'gi')
if (typeof e == 'string')
returnedItems = e.match(regex)
})
return returnedItems
})
this.setState({data: filteredDatas, search: event.target.value})
}
render = () => {
const {data, search} = this.state
return (
<Paper>
<Table
data={data}
search={search}
onSearch={this.handleSearch}
/>
</Paper>)
}
}
export default EnhancedTable
fuzzyContains = (text, search) => {
debugger
if (!text)
return false
if (!search)
return true
search = search.toLowerCase()
text = text.toString().toLowerCase()
let previousLetterPosition = -1
return search.split('').every(s => {
debugger
previousLetterPosition = text.indexOf(s, previousLetterPosition + 1)
return previousLetterPosition !== -1
})
}
handleSearch = search => {
const {data} = this.state
// debugger
let filteredData = data.filter(x => Object.keys(x).some(key =>
// debugger
this.fuzzyContains(x[key], search)
))
console.log(filteredData)
this.setState({filteredData, search})
}