I have the following return method in one of my components (AreaCodesTable):
<>
<Button
id="create-email-template"
className="p-button-rounded p-button-text p-button-icon-only blubicon-plus"
onClick={() => this.toggleCreateAreaCodeModal()}
></Button>
<Tooltip target={'#create-email-template'} content={this.props.t('common.areaCode')} position={'left'} />
<DataTable dataKey="id" id="area-codes-table" value={this.props.rootStore.areaCodeStore.areaCodes}>
<Column key="title" field="title" header={this.props.t('areaCodes.shared.title')} style={{ width: '11rem' }} />
<Column
key="description"
field="description"
header={this.props.t('areaCodes.shared.description')}
style={{ width: '11rem' }}
/>
<Column
body={this.showButtons}
headerStyle={{ width: '10%', minWidth: '8rem' }}
bodyStyle={{ textAlign: 'center' }}
></Column>
</DataTable>
<DeleteModal
deleteMode={this.state.showDeleteModal}
confirmDeleteTemplate={this.confirmDeletion}
discardDeleteTemplate={this.toggleDeleteAreaCodeModal}
header={this.props.t('areaCodes.delete.header')}
/>
{this.state.showEditModal && (
<EditAreaCodeModal
selectedAreaCode={this.state.selectedAreaCode}
confirmEdit={this.confirmEdit}
toggleEditAreaCodeModal={this.toggleEditAreaCodeModal}
visible={this.state.showEditModal}
rootStore={this.props.rootStore}
/>
)}
{this.state.showCreateModal && (
<CreateAreaCodeModal
rootStore={this.props.rootStore}
toggleCreateAreaCode={this.toggleCreateAreaCodeModal}
getAreaCodesRefresh={this.getAreaCodes}
/>
)}
</>
However I can't simulate a click in my unit tests.
describe('area codes table', () => {
const backendBaseUrl = 'http://localhost:8081';
const mockDataProvider = new DataProvider(backendBaseUrl);
const rootStore = new RootStore(mockDataProvider);
const props = {
rootStore: rootStore,
i18n: i18n,
t: t,
};
const initialState = {
showDeleteModal: false,
showEditModal: false,
showCreateModal: false,
selectedAreaCode: null,
};
let reactComponent: ShallowWrapper<IAreaCodesTableProps, IAreaCodesTableState>;
beforeEach(() => {
reactComponent = shallow(<AreaCodesTable {...props} />);
});
afterEach(() => {
reactComponent.unmount();
});
it('should show create modal', () => {
const createButton = reactComponent.find('button');
createButton.simulate('click');
});
});
Either I use reactComponent.find('#create-email-template') or .find('button') I get this error message: Method “simulate” is meant to be run on 1 node. 0 found instead. . For the first one I understand why- because we have to ids create-email-template, but for the second I dont know- I used Button, #button, #Button combinations as well, but didnt work.
This is the result from reactComponent.html():
<button
id="create-email-template"
class="p-button p-component p-button-rounded p-button-text p-button-icon-only blubicon-plus"
>
<span class="p-button-label p-c"> </span>
</button>
<div
id="area-codes-table"
class="p-datatable p-component"
data-scrollselectors=".p-datatable-scrollable-body, .p-datatable-unfrozen-view .p-datatable-scrollable-body"
>
<div class="p-datatable-wrapper">
<table role="grid">
<thead class="p-datatable-thead">
<tr role="row">
<th role="columnheader" class="p-sortable-disabled" style="width:11rem">
<span class="p-column-title"></span>
</th>
<th role="columnheader" class="p-sortable-disabled" style="width:11rem">
<span class="p-column-title"></span>
</th>
<th role="columnheader" class="p-sortable-disabled" style="width:10%;min-width:8rem">
<span class="p-column-title"></span>
</th>
</tr>
</thead>
<tbody class="p-datatable-tbody">
<tr role="row" class="p-datatable-emptymessage">
<td role="cell" colSpan="3">
No records found
</td>
</tr>
</tbody>
</table>
</div>
</div>
Everything is here.
Related
My problem is not able render the html code in the editor.
Here is my code for your reference :
const divRef = useRef(null);
const [contentState, setContentState] = useState(); // ContentState JSON
const blocksFromHTML = convertFromHTML(divRef.current.innerHTML);
const state = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
);
this.state = {
editorState: EditorState.createWithContent(state)
}
I want to render the table data on the editor. Here is my html code for your reference.
<div className='row' ref={divRef}>
<div className='col-lg-12'>
<table id="checklist">
<tr>
<th>Task List</th>
<th>Assignee</th>
<th>Status</th>
<th>Comments</th>
</tr>
{
ViewChecklistItem.map((row, index) => (
<tr key={row.TaskId}>
<td width="45%">{row.TaskName}</td>
<td>{row.AssigneeName}</td>
<td>
<FormControl sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-controlled-open-select-label">Status</InputLabel>
<Select
className={"copy "+(row.AllowStatusChange === 'Y' ? 'allowed' : 'not-allowed')}
labelId="demo-controlled-open-select-label"
id="demo-controlled-open-select"
open={open[index]}
onClose={() => { handleClose(index) }}
onOpen={() => { handleOpen(index) }}
value={status[index] || row.StatusId}
label="Status"
onChange={(event, newValue) => {
setStatusId(event.target.value);
setTaskId(row.TaskId);
setStatusPopup(true);
}}
>
{StatusList?.map(status => {
return (
<MenuItem value={status.StatusId}>{status.Status}</MenuItem>
);
})}
</Select>
</FormControl>
</td>
<td><a href="javascript:;" onClick={() => viewLogs(row.TaskId, row.TaskName, row.AssigneeName)} className='view-log'><img src={view_log} /> View Log</a></td>
</tr>
))
}
</table>
</div>
</div>
But am getting the output in console.log(divRef.current.innerHTML);
Please help me out. where I missed.
I have upated Editior code below:
<Editor
editorState={editorState}
defaultContentState={contentState}
onContentStateChange={setContentState}
wrapperClassName="wrapper-class"
editorClassName="editor-class"
toolbarClassName="toolbar-class"
/>
I have a form with a social object, I want to add an icon to the social notification that has a boolean value and also want to toggle the icon and update the form.
export default function UserProfile(props) {
const form = useForm({
initialValues: {
name: props.userProfile.name,
socials: {
email: {
notifications: true,
},
facebook: {
notifications: false,
},
twitter: {
notifications: false,
},
},
},
});
return (
<>
<form
method="post"
className="pt-5"
key={props.userProfile.id}
onSubmit={form.onSubmit(handleSubmit)}
>
<TextInput
label="Name"
placeholder={props.userProfile.name}
{...form.getInputProps("name")}
/>
<Tabledata
socials={{ ...form.getInputProps("socials") }}
session={session}
/>
<button type="submit">Save</button>
</form>
</>
)
}
The table data component is :
function Tabledata({ socials }) {
// console.log(socials.value["email"]["notifications"]);
function ToggleButton() {
const [isChecked, setIsChecked] = useState(true);
return isChecked? <CheckCircleIcon
className="h-6 w-6 text-green-500"
onClick={() => setIsChecked(!isChecked)}
/>
: <XCircleIcon
className="h-6 w-6 text-red-500"
onClick={() => setIsChecked(!isChecked)}
/>
}
return (
<>
<Table>
<thead>
<tr>
<th>Social channel</th>
<th>Notifications</th>
</tr>
</thead>
<tbody>
{Object.keys(socials.value).map((data, index) => (
<tr key={index}>
<td>{data}</td>
<td>
{socials.value[data]["notifications"]? (
<ToggleButton />
) : (
"Null"
)}
</td>
</tr>
))}
</tbody>
</Table>
</>
);
}
But I'm unable to toggle the value of the notification. How can I approach that? I was trying the above method and also I tried the below method, but not getting the desired result. I'm not sure how to do that.
function Tabledata({ socials }) {
return (
<>
<Table>
<thead>
<tr>
<th>Social channel</th>
<th>Notifications</th>
</tr>
</thead>
<tbody>
{Object.keys(socials.value).map((data, index) => (
<tr key={index}>
<td>{data}</td>
<td>
{socials.value[data]["notifications"]? (
<CheckCircleIcon
className="h-6 w-6 text-green-500"
onClick={() =>
console.log(`change the notification to false`)
}
/>
) : (
<XCircleIcon
className="h-6 w-6 text-red-500"
onClick={() =>
console.log(`change the notification to true`)
}
/>
)}
</td>
</tr>
))}
</tbody>
</Table>
</>
);
}
Please leave you suggestions. I tried different StackOverflow suggestions but could not able to solve my problem.
I refactored your code, I think you are on the right track, your mistake is that you are creating a function toggleButton and you call the function like a component <toggleButton />, I just updated your code . I hope it works.
function Tabledata({ socials }) {
// console.log(socials.value["email"]["notifications"]);
const [isChecked, setIsChecked] = useState(true);
function toggleButton() {
return isChecked ? (
<CheckCircleIcon
className="h-6 w-6 text-green-500"
onClick={() => setIsChecked(false)}
/>
) : (
<XCircleIcon
className="h-6 w-6 text-red-500"
onClick={() => setIsChecked(true)}
/>
);
}
return (
<>
<Table>
<thead>
<tr>
<th>Social channel</th>
<th>Notifications</th>
</tr>
</thead>
<tbody>
{Object.keys(socials.value).map((data, index) => (
<tr key={index}>
<td>{data}</td>
<td>
{communications.value[data]["notifications"] ? (
<>{toggleButton()}</>
) : (
"Null"
)}
</td>
</tr>
))}
</tbody>
</Table>
</>
);
}
And if you want to make component, then you have to make the toggleButton func outside the TableData, as you can see the below code.
function ToggleButton() {
const [isChecked, setIsChecked] = useState(true);
return isChecked ? (
<CheckCircleIcon
className="h-6 w-6 text-green-500"
onClick={() => setIsChecked(!isChecked)}
/>
) : (
<XCircleIcon
className="h-6 w-6 text-red-500"
onClick={() => setIsChecked(!isChecked)}
/>
);
}
function Tabledata({ socials }) {
// console.log(socials.value["email"]["notifications"]);
return (
<>
<Table>
<thead>
<tr>
<th>Social channel</th>
<th>Notifications</th>
</tr>
</thead>
<tbody>
{Object.keys(socials.value).map((data, index) => (
<tr key={index}>
<td>{data}</td>
<td>
{communications.value[data]["notifications"] ? (
<ToggleButton />
) : (
"Null"
)}
</td>
</tr>
))}
</tbody>
</Table>
</>
);
}
The infinite scroll component is in a table and its inside a scrollable page. i tried giving
id="scrollableDiv" to every div in the page and also <html> in index.html still no use. when i remove the scrollableTarget="scrollableDiv" the fetchdata works untill the parent scroll bar in the bottom. after that fetchData function not working. when i forcefully scroll the parent scroll fetchdata works.
But i want it to work on scrolling the table. Not when scrolling the parent(i mean the whole page), anyone tell me where should i assingn id="scrollableDiv". There is no div with height specified
Here is the code,
const fetchMoreData = () => {
console.log("new more data");
const temp = [...ingestStats];
setTimeout(() => {
setIngestStats((prev) => prev.concat(temp));
}, 1500);};
<div className="row">
<div className="col-xl-12">
<div className="card dashboard-table">
{/* /.card-header */}
<div className="card-body p-0" id="collapse1">
<InfiniteScroll
dataLength={ingestStats.length}
next={fetchMoreData}
hasMore={ingestStats.length < 40 ? true : false}
loader={
<p style={{ textAlign: "center" }}>
<b>Loading...</b>
</p>
}
endMessage={
<p style={{ textAlign: "center" }}>
<b>Yay! You have seen it all</b>
</p>
}
scrollableTarget="scrollableDiv"
>
<table className="table table-hover table-borderless text-center table-sm table-responsive">
<thead>
<tr>
<th>Activity</th>
<th>
Time Stamp{" "}
<span href="#0">
<i className="fas fa-angle-down" />
</span>
</th>
<th>
Status{" "}
<span href="#0">
<i className="fas fa-angle-down" />
</span>
</th>
</tr>
</thead>
<tbody>
{ingestStats &&
ingestStats.map((item, index) => (
<tr key={`${item.time}-${index}`}>
<td>{item.activity}</td>
<td>{item.time}</td>
<td>
{item.isActive ? (
<span className="status-success">
Success
</span>
) : (
<span className="status-failed">
Success
</span>
)}
</td>
</tr>
))}
</tbody>
</table>
</InfiniteScroll>
</div>
{/* /.card-body */}
</div>
</div>
</div>
I was encountering a similar problem where the infinitescroll element would take the whole window in order to scroll... However, there is a small fix for this. You actually just need to add 'height' to the InfiniteScroll element and all your problems will be gone. That is the reason why it won't trigger your fetch data. See down for an example:
const [fetchIsLoading, setFetchIsLoading] = useState(false);
const [contacts, setContacts] = useState([]);
const loadMoreData = () => {
if (fetchIsLoading) {
return;
}
setFetchIsLoading(true);
fetch('https://randomuser.me/api/?results=10&inc=name,gender,email,nat,picture&noinfo')
.then((res) => res.json())
.then((body) => {
setContacts([...contacts, ...body.results]);
setFetchIsLoading(false);
})
.catch(() => {
setFetchIsLoading(false);
});
};
useEffect(() => {
loadMoreData();
}, []);
<div // < ------------- top level div with id 'scrollableDiv' is not even needed... but it works (if you use it or not)
// id="scrollableDiv"
// style={{height: 400}}
>
<InfiniteScroll style={{
// height: 400 <-------- this does not work!
}}
dataLength={contacts.length}
next={loadMoreData}
hasMore={true}//contacts.length < 15
loader={
<Skeleton
avatar
paragraph={{
rows: 1,
}}
active
/>
}
height={400} // <--------- however, this works through the way this infinite scroll is set up.
endMessage={<Divider plain>It is all, nothing more 🤐</Divider>}
//scrollableTarget="scrollableDiv" <-------- this is not even needed the way this infinite scroll is set up. Even though you point it to the top level div it works either way...
>
<List
dataSource={contacts}
renderItem={(item) => (
<List.Item key={item.email}>
<List.Item.Meta
avatar={<Avatar src={item.picture.large} />}
title={<div style={{ color: '#54BEC6', cursor: 'pointer' }}>{item.name.last}</div>}
description={item.email}
onClick={(event) => onClickContactsTab(event, item.name.last)}
/>
{
// Use this section to put extra information about the user
//<div>Extra info?</div>
}
</List.Item>
)}
/>
</InfiniteScroll>
</div>
TableItem component added without any data in UI. Could somebody help on this. On refereshing the UI, added data is shown with details in TableItem component.
Table Component Code
import TableItem from "./TableItem";
function Table({ searchWord }) {
const dispatch = useDispatch();
const dictData = useSelector((state) => state.dictionary);
useEffect(() => {
dispatch(getDictionaryAsync());
}, [dispatch]);
return (
<table className="table table-striped">
<thead>
<tr>
<th scope="col">Word</th>
<th scope="col">Description</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{dictData &&
dictData
.filter((e) =>
searchWord === ""
? e
: e.word &&
e.word.toLowerCase().includes(searchWord.toLowerCase())
)
.map((item) => (
<TableItem item={item} key={item.id} searchWord={searchWord} />
))}
</tbody>
</table>
);
}
export default Table;
Below is the TableItem Component Code which i am trying to update,
When i add a word to dictionary it will fetch the details from the server and display it in the React app.
function TableItem({ item }) {
const [modal, setModal] = useState(false);
const openModal = () => {
setModal(true);
};
return (
<>
<tr key={item.id}>
<td style={{ textTransform: "capitalize" }}>{item.word}</td>
<td>
<b style={{ textTransform: "capitalize" }}>
{item.items && item.items[0].category} -{" "}
</b>
{item.items && truncate(item.items[0].definitions[0])}
</td>
<td>
<button className="btn btn-danger btn-sm " onClick={openModal}>
View
</button>
</td>
</tr>
<Modal isOpen={modal} ariaHideApp={true}>
<div className="modal-header">
<h3 className="modal-word-header">
{item.word && item.word.toUpperCase()}
</h3>
<button
className="btn btn-danger btn-sm"
onClick={() => setModal(false)}
>
<i class="fa fa-times" aria-hidden="true"></i>
</button>
</div>
<div className="model-content">
<p>
{item.items &&
item.items.map((e) => {
return (
<>
<i>{e.category}</i>
<ul>
{e.definitions.map((def) => {
return <li>{def}</li>;
})}
</ul>
</>
);
})}
</p>
</div>
</Modal>
</>
);
}
Better add your TableItem component code!
Below code works fine and updated the UI on change in the Data in TableItem,
useEffect(() => {
dispatch(getDictionaryAsync());
}, [dispatch, dictData]); *<--updated code*
I've made a table with one column as checkbox to select that row. So if the user checks this row's checkbox, I'll add isChecked : true property in state and on uncheck will change isChecked: false of that in state. Each page is having 10rows. The issue is when I checked the 1st row checkbox of 1st page and when I go to Next Page somehow the 1st row of next page checkbox also appears checked. However only 1st row is set to true in state. Whats the issue? What wrong I'm doing can anyone tell? Thanks in advance!
import React,{Component} from 'react';
import { Table,Button,Input } from 'reactstrap';
import SelectedUsers from './SelectedUsers';
import { yellow } from '#material-ui/core/colors';
import Icon from '#material-ui/core/Icon';
class Users extends Component {
constructor(props) {
super(props);
this.state = {
users : [],
pageSize: 10,
pageIndex: 0,
selectedUsers : [],
filterCandidate : '',
searchVal : ""
};
}
componentDidMount() {
const userLink = 'api';
fetch(userLink, {
method: 'GET'
})
.then(res => res.json())
.then(data => {
this.setState({
users : data
})
console.log(data)
})
}
onSelectUser = (e,i) => {
const copy_users = this.state.users.slice() ;
const checked = e.target.checked
copy_users[i].isChecked = checked
this.setState({ copy_users})
// console.log( e.target.value)
}
handlePrevPageClick = (event) => {
this.setState(prevState => ({
pageIndex: prevState.pageIndex > 0 ? prevState.pageIndex - 1 : 0
}));
}
handleNextPageClick = (event) => {
this.setState(prevState => ({
pageIndex:
prevState.pageIndex <
Math.floor(prevState.users.length / prevState.pageSize)
? prevState.pageIndex + 1
: prevState.pageIndex
}));
}
render() {
let profile = 'Profile Image';
return (
<div className="bets_page">
<Table striped responsive>
<thead>
<tr>
<th>Select</th>
<th>Player Name</th>
<th>Level<Icon style={{ color: yellow[800] }} fontSize="small">star</Icon></th>
<th>Avatar</th>
<th>BET</th>
<th>Wins<Icon style={{ color: yellow[800] }} fontSize="small">euro</Icon></th>
<th>Lost</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{this.state.users.slice(
this.state.pageIndex * this.state.pageSize,
this.state.pageIndex * this.state.pageSize + this.state.pageSize
).map((data,i) => (
<tr key={i}>
<td>
<label className="checkbox">
<input type="checkbox"
checked={data.isChecked}
key={i}
value={data.Name}
onChange={(e) => this.onSelectUser(e,i)}/>
</label>
</td>
<td>{data.Name}</td>
<td></td>
<td><img src={data[profile]} alt={data.Name}
className="avatar"/></td>
<td>{data.Bet}</td>
<td></td>
<td></td>
<td>{data.Price}</td>
</tr>
))}
</tbody>
</Table>
<div>
<Button onClick={event => this.handlePrevPageClick(event)} className="m-2">
{"<"}
</Button>Page {this.state.pageIndex+1}
<Button onClick={event => this.handleNextPageClick(event)} className="m-2">
{">"}
</Button>
</div>
</div>
}
}
export default Users;
when you slice the users and apply map on them the 'i' variable starts from 0 for each page. you should add 'this.state.pageIndex * this.state.pageSize' to 'i' variable whenever you set it for key and you send that to onSelectUser
render() {
return (
<div className="bets_page">
<Table striped responsive>
<thead>
<tr>
<th>Select</th>
<th>Player Name</th>
</tr>
</thead>
<tbody>
{this.state.users
.slice(
this.state.pageIndex * this.state.pageSize,
this.state.pageIndex * this.state.pageSize + this.state.pageSize
)
.map((data, i) => {
const index = i + this.state.pageIndex * this.state.pageSize;
return (
<tr key={index}>
<td>
<label className="checkbox">
<input
type="checkbox"
checked={data.isChecked}
key={i}
value={data.Name}
onChange={(e) => this.onSelectUser(e, index)}
/>
</label>
</td>
<td>{data.Name}</td>
</tr>
);
})}
</tbody>
</Table>
<div>
<Button
onClick={(event) => this.handlePrevPageClick(event)}
className="m-2"
>
{"<"}
</Button>
Page {this.state.pageIndex + 1}
<Button
onClick={(event) => this.handleNextPageClick(event)}
className="m-2"
>
{">"}
</Button>
</div>
</div>
);
}
I simplified your code and I created the online demo here