Implementing pagination in React that displays 15 items per page from a JSON file - javascript

I am having issues on even trying to get started with doing pagination without the use of any packages. I am pulling data from a JSON file that contains about 30-32 quotes. I need 15 quotes per page to be displayed and have no idea how to even do that using React. So far what I have is all the quotes being displayed by default. I have three buttons, each filters through the JSON to provide quotes by the theme of the quote which is displayed by the button. This is how far I got:
class App extends Component {
constructor(props) {
super(props);
this.state ={
results: quotes,
search: ""
}
}
gameFilterClick = event => {
event.preventDefault();
const games = [];
for(let i = 0; i < quotes.length; i++){
if (quotes[i].theme === "games"){
games.push(quotes[i])
}
}
this.setState({results: games})
}
movieFilterClick = event => {
event.preventDefault();
console.log('blah!!')
const movies = [];
for(let i =0; i < quotes.length; i++){
if(quotes[i].theme === 'movies'){
movies.push(quotes[i])
}
}
this.setState({results: movies})
}
allButtonClick = event => {
this.setState({results: quotes})
}
quoteSearch = query => {
let search = quotes.map
}
render() {
return (
<div className="App">
<h1>Quotes</h1>
<Search />
<div id='buttons'>
Filters:
<button onClick={this.allButtonClick}>All Quotes</button>
<button onClick={this.gameFilterClick}>Games</button>
<button onClick={this.movieFilterClick}>Movies</button>
</div>
<div id='resultsDiv'>
<Results
results={this.state.results}
/>
</div>
</div>
);
}
}
export default App;

I would recommend using react-bootstrap for this. You'll need to install two packages (they use to come in one, but now pagination package is separated):
react-bootstrap-table-next
react-bootstrap-table2-paginator
So, let's install them:
npm i --save react-bootstrap-table-next
npm i react-bootstrap-table2-paginator
And here goes a simple example of implementation:
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory from 'react-bootstrap-table2-paginator';
// Let's imagine this is your JSON data
const yourJsonData = [{id: 1, author: "David Goggins", quote: "Life goes on"},
{ id: 2, author: "Robert Green", quote: "yes it does"}]:
// Here we define your columns
const columns = [{
dataField: 'author',
text: 'AUTHOR'
}, {
dataField: 'quote',
text: 'QUOTE'
}];
// Give it an option to show all quotes
let allQuotes = Number(yourJsonData.length);
// Set all of the major pagination options. You can reduce them if you want less
const options = {
paginationSize: 15,
pageStartIndex: 0,
firstPageText: 'First',
prePageText: 'Back',
nextPageText: 'Next',
lastPageText: 'Last',
nextPageTitle: 'First page',
prePageTitle: 'Pre page',
firstPageTitle: 'Next page',
lastPageTitle: 'Last page',
sizePerPageList: [{
text: 'show 15', value: 15
}, {
text: 'show 30', value: 30
}, {
text: 'Show all', value: allQuotes
}]
};
... and then somewhere later in your code where you want to display the table with pagination you just insert this:
<BootstrapTable
keyField='rowNumber'
data={ yourJsonData }
columns={ columns }
pagination={ paginationFactory(options) } />
I hope this solves your problem.

I've simplified your filtering logic and added client side pagination. Check out this simple working example (i've set item per page to 3, you can add more data and change it to 15 const QUOTES_PER_PAGE = <number of quotes per page>;)
const QUOTES_PER_PAGE = 3;
const Quote = ({text}) => <li>{text}</li>;
const Pagination = ({pages, goTo}) => (
<div>
{pages.map((p, i) => (
<button key={i} onClick={goTo} value={i}>{i+1}</button>
))}
</div>
)
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
page: 0,
pagedQuoutes: this.divideQuoutesIntoPages(props.quotes)
};
}
divideQuoutesIntoPages = (quotes => {
const pagedQuotes = [];
[...Array(Math.ceil(quotes.length/QUOTES_PER_PAGE))].forEach((q, i) => {
pagedQuotes.push(quotes.slice(0 + QUOTES_PER_PAGE*i, QUOTES_PER_PAGE + QUOTES_PER_PAGE*i))
})
return pagedQuotes;
})
filterQuoutes = (evt) => {
const filterValue = evt.target.value;
const filteredQuoutes = this.props.quotes.filter(q => !filterValue || q.theme === filterValue);
this.setState({
pagedQuoutes: this.divideQuoutesIntoPages(filteredQuoutes)
})
}
goToPage = (evt) => {
this.setState({
page: evt.target.value
})
}
render() {
return (
<div>
<h1>Quotes</h1>
<div>
Filters:
<button onClick={this.filterQuoutes}>All Quotes</button>
<button onClick={this.filterQuoutes} value="games">Games</button>
<button onClick={this.filterQuoutes} value="movies">Movies</button>
</div>
{this.state.pagedQuoutes[this.state.page]
.map(q => (
<ul>
<Quote {...q} />
</ul>
))}
<Pagination pages={this.state.pagedQuoutes} goTo={this.goToPage} />
</div>
);
}
}
const exampleQuotes = [{
theme: 'games',
text: 'games q1'
}, {
theme: 'games',
text: 'games q2'
}, {
theme: 'games',
text: 'games q3'
}, {
theme: 'games',
text: 'games q4'
}, {
theme: 'games',
text: 'games q5'
}, {
theme: 'movies',
text: 'movies q1'
}, {
theme: 'movies',
text: 'movies q2'
}, {
theme: 'movies',
text: 'movies q3'
}]
ReactDOM.render(<App quotes={exampleQuotes} />, document.getElementById("el"))
<div id="el"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Related

React JS Filter Methods: Hiding table columns using array filters and state

This is the code I am trying to rebuild using functional component, but my arrays do not behave correctly.
EXPECTED RESULT: https://stackblitz.com/edit/antd-showhidecolumns
My forked functional component version:
MY WORK https://stackblitz.com/edit/antd-showhidecolumns-rdyc8h
Main issue here is I am not able to show/hide column cells, I am not sure why my array is different when I use the same method as the original code.
My code:
const onChange = (e) => {
let { checkedColumns } = colmenu;
if (e.target.checked) {
checkedColumns = checkedColumns.filter((id) => {
return id !== e.target.id;
});
console.log('if checked columns is', checkedColumns);
} else if (!e.target.checked) {
checkedColumns.push(e.target.id);
console.log('elseif checked columns', checkedColumns);
}
const filtered = checkedColumns.filter((el) => {
return el.dataIndex !== checkedColumns.el;
});
console.log('filtered items', filtered);
setColmenu({ ...colmenu, columns: filtered });
};
working version from the old code (class component)
onChange = (e) => {
var checkedColumns = this.state.checkedColumns
if(e.target.checked){
checkedColumns = checkedColumns.filter(id => {return id !== e.target.id})
}
else if(!e.target.checked){
checkedColumns.push(e.target.id)
}
var filtered = this.state.initialColumns;
for(var i =0;i< checkedColumns.length; i++)
filtered = filtered.filter(el => {return el.dataIndex !== checkedColumns[i]})
this.setState({columns: filtered, checkedColumns: checkedColumns})
}
Something really went wrong with your code (or homework i guess?)
Please have a look at least at the docs for React.useState to set some basics.
First you should init your initalColumns and later you should filter on them.
Additional i init the checkColumns with the correct values and changed the wrong logic for changing them.
Have a look how the filtering is done via Array.includes maybe someone will ask for this ;-)
Another point is that you may split the state object in separate primitive states.
Nevertheless here is a working stackblitz and the depending code.
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Table, Button, Dropdown, Menu, Checkbox } from 'antd';
const App = () => {
const columns = [
{
title: 'Description',
dataIndex: 'description',
},
{
title: 'Employees',
dataIndex: 'employees',
},
];
const [colmenu, setColmenu] = React.useState({
value: false,
checkedColumns: ['description', 'employees'],
visibleMenuSettings: false,
columns,
initialColumns: columns,
});
const onChange = (e) => {
let { checkedColumns, columns, initialColumns } = colmenu;
if (!e.target.checked) {
checkedColumns = checkedColumns.filter((id) => {
return id !== e.target.id;
});
console.log('if checked columns is', checkedColumns);
} else if (e.target.checked) {
checkedColumns.push(e.target.id);
console.log('elseif checked columns', checkedColumns);
}
console.log(columns);
columns = initialColumns.filter((col) =>
checkedColumns.includes(col.dataIndex)
);
setColmenu({ ...colmenu, columns, checkedColumns });
};
const handleVisibleChange = (flag) => {
setColmenu({ ...colmenu, visibleMenuSettings: flag });
};
const menu = (
<Menu>
<Menu.ItemGroup title="Columns">
<Menu.Item key="0">
<Checkbox id="description" onChange={onChange} defaultChecked>
Description
</Checkbox>
</Menu.Item>
<Menu.Item key="1">
<Checkbox id="employees" onChange={onChange} defaultChecked>
Employees
</Checkbox>
</Menu.Item>
</Menu.ItemGroup>
</Menu>
);
const dataSource = [
{
key: '1',
description: 'Holiday 1',
employees: '79',
},
{
key: '2',
description: 'Holiday 2',
employees: '12',
},
{
key: '3',
description: 'Holiday 3',
employees: '0',
},
];
return (
<div>
<div className="row">
<div className="col-12 mb-3 d-flex justify-content-end align-items-center">
<Dropdown
overlay={menu}
onVisibleChange={handleVisibleChange}
visible={colmenu.visibleMenuSettings}
>
<Button>Show/Hide Columns</Button>
</Dropdown>
</div>
</div>
<div className="row">
<div className="col-12">
<Table
columns={colmenu.columns}
dataSource={dataSource}
size="small"
pagination={{
pageSizeOptions: ['20', '50'],
showSizeChanger: true,
}}
/>
</div>
</div>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('container'));

Multiple array check react js

I have an array of objects which I'm rendering by section - see title of each object "Price", "Sectors and Charges" etc.
This populates a mini modal where users can select options to update rendered columns basically a filter.
The selection of the items are working however if I make a selection of the first item "0" all sections with the first option are selected.
How can I store the selection from each object into the selectedOptions array?
Please note I'm using react js and styled components, I've not added the styled component code.
Data:
const columnsData = [
{
title: 'Price',
options: [
{
label: 'Daily Change'
},
{
label: 'Price'
},
{
label: 'Price Date'
},
{
label: 'Volatility Rating'
}
],
},
{
title: 'Sectors and Charges',
options: [
{
label: 'Sector'
},
{
label: 'Asset Class'
},
{
label: 'AMC'
},
],
},
{
title: 'Cumulative Performance',
options: [
{
label: '1 month'
},
{
label: '6 months'
},
{
label: '1 year'
},
],
},
]
Code:
const EditColumns = ({active, onClick}) => {
const [selectedOptions, setSelectedOptions] = useState([0, 1, 2]);
const update = () => {
onClick();
}
const updateSelection = (z) => {
setSelectedOptions(selectedOptions.includes(z) ? selectedOptions.filter(j => j !== z) : [...selectedOptions, z]);
}
return (
<Wrap onClick={() => update()}>
<CTA>
<SVG src="/assets/svgs/btns/edit.svg" />
<span>Columns</span>
</CTA>
{active &&
<Dropdown>
<Head>
<span className="title">Edit Columns</span>
<span>Select the columns you would like to see</span>
</Head>
<Body>
{columnsData.map((item, i) => {
return (
<Section key={i}>
<SectionHead>
<span className="title">{item.title}</span>
<span>Select all</span>
</SectionHead>
<SectionList>
{item.options.map((child, z) => {
const selected = selectedOptions.includes(z);
return (
<li key={z} className={classNames({selected})} onClick={() => updateSelection(z)}>
<span>{child.label}</span>
</li>
)
})}
</SectionList>
</Section>
)
})}
</Body>
</Dropdown>
}
</Wrap>
)
}
export default EditColumns;
Your section lists are all sharing the same state variable, so any changes will be applied to all of them. You could fix this either by constructing a more complex state object which more closely resembles the structure of columnsData, or making each SectionList its own component with its own state. What you decide to do will depend on the degree to which the EditButtons component actually needs access to the whole state.
The second approach might look something like this:
const EditColumns = ({active, onClick}) => {
const update = () => {
onClick();
}
return (
<Wrap onClick={() => update()}>
<CTA>
<SVG src="/assets/svgs/btns/edit.svg" />
<span>Columns</span>
</CTA>
{active &&
<Dropdown>
<Head>
<span className="title">Edit Columns</span>
<span>Select the columns you would like to see</span>
</Head>
<Body>
{columnsData.map((item, i) => {
return (
<Section key={i}>
<SectionHead>
<span className="title">{item.title}</span>
<span>Select all</span>
</SectionHead>
<SectionList options={item.options}/>
</Section>
)
})}
</Body>
</Dropdown>
}
</Wrap>
)
}
const SectionList = ({options}) => {
const [selectedOptions, setSelectedOptions] = useState([0, 1, 2]);
const updateSelection = (z) => {
setSelectedOptions(selectedOptions.includes(z) ? selectedOptions.filter(j => j !== z) : [...selectedOptions, z]);
}
return (
<SectionListContainer>
{options.map((child, z) => {
const selected = selectedOptions.includes(z);
return (
<li key={z} className={classNames({selected})} onClick={() => updateSelection(z)}>
<span>{child.label}</span>
</li>
)
})}
</SectionListContainer>
)
}

How can you access the constant variables of one Component in another Component - React

I am working on React Table. I am basically a beginner in React. I have a dashboard page where I display a React Table of 8 columns. I have a customize button which will open a popup page, this popup page has 8 check boxes allows me to show/hide those React columns. Initially all the check boxes in this popup page is set to true. When I uncheck a column that particular column get disabled.
There are images in the end to see what I am trying to do.
I will be using this logic for show hide columns (this question was asked by me two days back) - You can see how this is done using a React Table attribute/property called show. When show is true that column/sub column is shown and When show is false that column/sub column is hidden.
The React Table data is like this
const columns = [
{
Header: 'Column 1',
accessor: 'firstName',
// show: true // shows the particular column (true is default)
// show: false // hides the particular column
},
{
Header: 'Column 2',
accessor: 'firstName',
},
{
Header: 'Column 3',
accessor: 'firstName',
},
{
Header: 'Column 4',
accessor: 'firstName',
},
{
Header: 'Column 5',
accessor: 'firstName',
},
{
Header: 'Column 6',
accessor: 'firstName',
},
{
Header: 'Column 7',
accessor: 'firstName'
},
{
Header: 'Column 8',
accessor: 'firstName',
}
];
Now have a look at this image. The image shows my dashboard page along with the checkbox popup page which can turn my column on/off (or show/hide)
This is the code for the popup page for checkbox
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { ActionCreators } from '../../../actions';
import ButtonComponent from '../../common/button/ButtonComponent';
import { CheckBox } from '../../common/chkbox/CheckBox';
class CustomizedView extends Component {
constructor(props) {
super(props);
this.handleCheckChildElement = this.handleCheckChildElement.bind(this);
this.state = {
items: [
{ id: 1, value: 'Column 1', isChecked: true },
{ id: 2, value: 'Column 2', isChecked: true },
{ id: 3, value: 'Column 3', isChecked: true },
{ id: 4, value: 'Column 4', isChecked: true },
{ id: 5, value: 'Column 5', isChecked: true },
{ id: 6, value: 'Column 6', isChecked: true },
{ id: 7, value: 'Column 7', isChecked: true },
{ id: 8, value: 'Column 8', isChecked: true },
]
};
}
handleClick() {
this.setState({ isChecked: !this.state.isChecked });
}
handleCheckChildElement(event) {
const { items } = this.state; //extract state values like this to a const variable
const newItems = items.map((item) => { //do map on items because map returns a new array. It’s good practice to use .map than forEach in your case
if(item.value === event.target.value) {
item.isChecked = event.target.checked;
return item; //return updated item object so that it will be pushed to the newItems array
}
return item; // return item because you need this item object as well
});
this.setState({ items: newItems }); //finally set newItems array into items
const column1checked = items[0].isChecked;
console.log('column1checked ' + column1checked);
const column2checked = items[1].isChecked;
console.log('column2checked ' + column2checked);
const column3checked = items[2].isChecked;
console.log('column3checked ' + column3checked);
const column4checked = items[3].isChecked;
console.log('column4checked ' + column4checked);
const column5checked = items[4].isChecked;
console.log('column5checked ' + column5checked);
const column6checked = items[5].isChecked;
console.log('column6checked ' + column6checked);
const column7checked = items[6].isChecked;
console.log('column7checked ' + column7checked);
const column8checked = items[7].isChecked;
console.log('column8checked ' + column8checked);
}
render() {
return (
<div className='div-container-custom' >
<div className='bottomBar'>
<ButtonComponent
text='Apply'
className='activeButton filterMargin-custom'
width='100'
display='inline-block'
onClick={() => { this.props.applyFilter(this.state, false); }}
/>
<ButtonComponent
text='Clear Filter'
className='greyedButton clear-custom-filter'
width='100'
display='block'
marginTop='60'
onClick={() => { this.props.applyFilter(this.state, true); }}
/>
</div>
<div>
<div className='data-points-text'>
<span> Columns </span>
</div>
<div className="App">
<ul>
{
this.state.items.map((item, i) => {
return (<div key={i} ><CheckBox handleCheckChildElement={this.handleCheckChildElement} {...item} /></div>);
})
};
</ul>
</div>
</div>
</div>
);
}
}
CustomizedView.propTypes = {
applyFilter: PropTypes.func.isRequired
};
CustomizedView.defaultProps = {
};
function mapStateToProps(state) {
return {
auth: state.auth
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(ActionCreators, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(CustomizedView);
Now my point is when I only uncheck 4th column in the checkbox popup page I get the desired values (the above code)
column1checked true
column2checked true
column3checked true
column4checked false
column5checked true
column6checked true
column7checked true
column8checked true
And ultimately this is my checkbox page
import React from 'react';
import PropTypes from 'prop-types';
export const CheckBox = (props) => {
// super(props);
return (
<li>
<input key={props.id} onClick={props.handleCheckChildElement} type="checkbox" checked={props.isChecked} value={props.value} /> {props.value}
</li>
);
};
CheckBox.propTypes = {
id: PropTypes.string,
handleCheckChildElement: PropTypes.func,
isChecked: PropTypes.bool,
value: PropTypes.string,
};
export default CheckBox;
Now my question is I have the constants in CustomizedView Component. I need those const variables available in ReactTable Component (path is like this - '../../common/chkbox/CheckBox')
In the main dashboard page I import the React Table
import ReactTableComponent from '../common/react_table/ReactTableComponent';
and just use it in the render function of the main dashboard page in this way.
<ReactTableComponent />
So I need to use all those const variables of Customized variables in ReactTable Component to show/hide tables.
Also here I have to use show: some_const (I cannot use true or false)
I am a complete beginner in React and I need help from this community. Kindly help to implement this idea.
All I want to know the best/easiest (may be great way or dumb way) way to transfer those 8 const variables from components\abcdashboard\customized_view\Customizedview to components\common\react_table\ReactTableComponent
Generally, when you want to share data across components like this, what you want is to consolidate the data in a higher-up component, and use functions to modify it.
Here's a contrived example (CodeSandbox here):
import React from "react";
import ReactDOM from "react-dom";
class Parent extends React.Component {
state = {
name: "Bill"
};
changeName = name => {
this.setState({ name });
};
render() {
return (
<React.Fragment>
<h1>name is: {this.state.name}</h1>
<ChildA changeName={this.changeName} />
<ChildB changeName={this.changeName} />
</React.Fragment>
);
}
}
class ChildA extends React.Component {
state = {
nameA: "Steve"
};
render() {
return (
<button onClick={() => this.props.changeName(this.state.nameA)}>
change to my name
</button>
);
}
}
class ChildB extends React.Component {
state = {
nameB: "Elon"
};
render() {
return (
<button onClick={() => this.props.changeName(this.state.nameB)}>
change to my name
</button>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Parent />, rootElement);
Here, the Parent can access the value of the names of the children through the changeName function which is passed down.
If you just want to share variables and not data per se, you could just define a whole file and export various variables like:
export const PI = 3.14
and so on, then do like:
import { PI } from './variables'
in other files, for example.

Using JsonSchemaForm on change to update field's content

I am trying to use JsonSchema-Form component but i ran into a problem while trying to create a form that, after choosing one of the options in the first dropdown a secondary dropdown should appear and give him the user a different set o options to choose depending on what he chose in the first dropdown trough an API call.
The thing is, after reading the documentation and some examples found here and here respectively i still don't know exactly how reference whatever i chose in the first option to affect the second dropdown. Here is an example of what i have right now:
Jsons information that are supposed to be shown in the first and second dropdowns trough api calls:
Groups: [
{id: 1,
name: Group1}
{id: 2,
name: Group2}
]
User: [User1.1,User1.2,User2.1,User2.2,User3.1,User3.2, ....]
If the user selects group one then i must use the following api call to get the user types, which gets me the the USER json.
Component That calls JSonChemaForm
render(){
return(
<JsonSchemaForm
schema={someSchema(GroupOptions)}
formData={this.state.formData}
onChange={{}}
uiSchema={someUiSchema()}
onError={() => {}}
showErrorList={false}
noHtml5Validate
liveValidate
>
)
}
SchemaFile content:
export const someSchema = GroupOptions => ({
type: 'object',
required: [
'groups', 'users',
],
properties: {
groups: {
title: 'Group',
enum: GroupOptions.map(i=> i.id),
enumNames: GroupOptions.map(n => n.name),
},
users: {
title: 'Type',
enum: [],
enumNames: [],
},
},
});
export const someUISchema = () => ({
groups: {
'ui:autofocus': true,
'ui:options': {
size: {
lg: 15,
},
},
},
types: {
'ui:options': {
size: {
lg: 15,
},
},
},
});
I am not really sure how to proceed with this and hwo to use the Onchange method to do what i want.
I find a solution for your problem.There is a similar demo that can solve it in react-jsonschema-form-layout.
1. define the LayoutField,this is part of the demo in react-jsonschema-form-layout.To make it easier for you,I post the code here.
Create the layoutField.js.:
import React from 'react'
import ObjectField from 'react-jsonschema-form/lib/components/fields/ObjectField'
import { retrieveSchema } from 'react-jsonschema-form/lib/utils'
import { Col } from 'react-bootstrap'
export default class GridField extends ObjectField {
state = { firstName: 'hasldf' }
render() {
const {
uiSchema,
errorSchema,
idSchema,
required,
disabled,
readonly,
onBlur,
formData
} = this.props
const { definitions, fields, formContext } = this.props.registry
const { SchemaField, TitleField, DescriptionField } = fields
const schema = retrieveSchema(this.props.schema, definitions)
const title = (schema.title === undefined) ? '' : schema.title
const layout = uiSchema['ui:layout']
return (
<fieldset>
{title ? <TitleField
id={`${idSchema.$id}__title`}
title={title}
required={required}
formContext={formContext}/> : null}
{schema.description ?
<DescriptionField
id={`${idSchema.$id}__description`}
description={schema.description}
formContext={formContext}/> : null}
{
layout.map((row, index) => {
return (
<div className="row" key={index}>
{
Object.keys(row).map((name, index) => {
const { doShow, ...rowProps } = row[name]
let style = {}
if (doShow && !doShow({ formData })) {
style = { display: 'none' }
}
if (schema.properties[name]) {
return (
<Col {...rowProps} key={index} style={style}>
<SchemaField
name={name}
required={this.isRequired(name)}
schema={schema.properties[name]}
uiSchema={uiSchema[name]}
errorSchema={errorSchema[name]}
idSchema={idSchema[name]}
formData={formData[name]}
onChange={this.onPropertyChange(name)}
onBlur={onBlur}
registry={this.props.registry}
disabled={disabled}
readonly={readonly}/>
</Col>
)
} else {
const { render, ...rowProps } = row[name]
let UIComponent = () => null
if (render) {
UIComponent = render
}
return (
<Col {...rowProps} key={index} style={style}>
<UIComponent
name={name}
formData={formData}
errorSchema={errorSchema}
uiSchema={uiSchema}
schema={schema}
registry={this.props.registry}
/>
</Col>
)
}
})
}
</div>
)
})
}</fieldset>
)
}
}
in the file, you can define doShow property to define whether to show another component.
Next.Define the isFilled function in JsonChemaForm
const isFilled = (fieldName) => ({ formData }) => (formData[fieldName] && formData[fieldName].length) ? true : false
Third,after you choose the first dropdown ,the second dropdown will show up
import LayoutField from './layoutField.js'
const fields={
layout: LayoutField
}
const uiSchema={
"ui:field": 'layout',
'ui:layout': [
{
groups: {
'ui:autofocus': true,
'ui:options': {
size: {
lg: 15,
},
},
}
},
{
users: {
'ui:options': {
size: {
lg: 15,
},
},
doShow: isFilled('groups')
}
}
]
}
...
render() {
return (
<div>
<Form
schema={schema}
uiSchema={uiSchema}
fields={fields}
/>
</div>
)
}

React data components table does not render HTML

https://github.com/carlosrocha/react-data-components package does not allow sending html into a td cell. See:
My goal is hyperlink to that product.
My use is:
import React from 'react';
var DataTable = require('react-data-components').DataTable;
import PlainTable from './PlainTable'
class ReduxDataTable extends React.Component {
constructor(props) {
super(props);
}
processHeaders(){
var columns = [];
for (let i = 0; i < this.props.data.headers.length; i++){
var header = this.props.data.headers[i];
var item = {title: header, prop: header};
columns.push(item);
}
return columns;
}
render() {
var dataList = this.props.data.data;
console.log("datalist is", dataList);
console.log("datalist length is", dataList.length);
var headerList = this.processHeaders();
if(dataList.length > 2) {
return (
<DataTable
keys="name"
columns={headerList}
initialData={dataList}
initialPageLength={20}
initialSortBy={{ prop: headerList[0].title, order: 'descending' }}
pageLengthOptions={[ 20, 60, 120 ]}
/>
);
}
else {
return (
<PlainTable
headers={headerList}
rows={dataList}
/>
);
}
}
}
export { ReduxDataTable as default };
then just
return (
<div className="card">
<h2 className="style-1">Detailed Report</h2>
<br/>
<h2 className="style-1:after">Data about products </h2>
<ReduxDataTable data={data}/>
</div>
)
Plain table is a <table> in case there's few products.
The package does not show any "htmlTrue" option, as searching "html" show nothing useful. I'm getting the same issue with any html at all:
I'm not opposed to forking it, but is there a simple way to use this package and declare html here?
I didn't use that component, but looking through the code, it seems that you can use a render function to do what you need. See here: https://github.com/carlosrocha/react-data-components/blob/3d092bd375da0df9428ef02f18a64d056a2ea5d0/src/Table.js#L13
See the example here https://github.com/carlosrocha/react-data-components/blob/master/example/table/main.js#L17
Relevant code snippet:
const renderMapUrl =
(val, row) =>
<a href={`https://www.google.com/maps?q=${row['lat']},${row['long']}`}>
Google Maps
</a>;
const tableColumns = [
{ title: 'Name', prop: 'name' },
{ title: 'City', prop: 'city' },
{ title: 'Street address', prop: 'street' },
{ title: 'Phone', prop: 'phone', defaultContent: '<no phone>' },
{ title: 'Map', render: renderMapUrl, className: 'text-center' },
];
return (
<DataTable
className="container"
keys="id"
columns={tableColumns}
initialData={data}
initialPageLength={5}
initialSortBy={{ prop: 'city', order: 'descending' }}
pageLengthOptions={[ 5, 20, 50 ]}
/>
);
Try adding the render property to your dataList. Maybe something like this
var dataList = this.props.data.data;
for (let i=0; i<dataList.length; i++)
dataList[i].render = function(val, row) {return (
<a href={row.href}>row.title</a>
)}

Categories