How to do search in table? - reactjs

I want to search with all the pagination and sorter field on place.
That is i want to call handleChange with searchkeyword.
So how can i call handleSearch and than call handleChange from within handleSearch?
import React from "react";
import { withRouter } from "react-router-dom";
import { Table, Button, Icon, Row, Col, Input } from "antd";
import axios from "axios";
const Search = Input.Search;
class App extends React.Component {
state = {
data: [],
searchValue: "",
loading: false,
visible: false,
pagination: {}
};
componentDidMount() {
this.fetch();
}
handleTableChange = (pagination, filter, sorter, value) => {
console.log(pagination, value, sorter, "Table Change");
let sorterOrder = "";
let sorterField = "";
let searchVal = "";
const pager = { ...this.state.pagination };
pager.current = pagination.current;
this.setState({
pagination: pager
});
if (value) {
console.log("inside if");
searchVal = undefined;
} else {
console.log("inside else");
searchVal = value;
}
if (sorter) {
if (sorter.order === "ascend") {
sorterOrder = "ASC";
}
if (sorter.order === "descend") {
sorterOrder = "DESC";
}
sorterField = sorter.field;
}
this.fetch({
page: pagination.current,
sortField: sorterField,
sortOrder: sorterOrder,
...filter,
value: searchVal
});
};
fetch = (params = {}) => {
this.setState({ loading: true });
axios.post("***/****", params).then(res => {
const pagination = { ...this.state.pagination };
let apiData = res.data.result;
if (res.data.status === 1) {
const objects = apiData.map(row => ({
key: row.id,
id: row.id,
firstName: row.firstName,
lastName: row.lastName,
status: row.status,
email: row.email
}));
console.log(res.data);
pagination.total = res.data.count;
this.setState({
loading: false,
data: objects,
pagination
});
} else {
console.log("Database status is not 1!");
}
});
};
handleSearch = value => {
console.log("value", value);
this.setState({
searchValue: value
});
let searchkey = this.state.searchValue;
const pagination = { ...this.state.pagination };
const sorter = { ...this.state.sorter };
console.log("search", value, pagination, sorter);
this.handleTableChange({
value
});
};
render() {
const columns = [
{
title: "First Name",
dataIndex: "firstName",
sorter: true
},
{
title: "Email",
dataIndex: "email",
sorter: true
}
];
return (
<div>
<Search
placeholder="input search text"
className="searchBut"
onSearch={value => this.handleSearch(value)}
/>
<Button
className="addBut"
style={{ marginTop: "0" }}
type="primary"
onClick={() => this.openForm()}
>
+ Add Admin
</Button>
</div>
<Table
bordered
columns={columns}
dataSource={this.state.data}
pagination={{ total: this.state.pagination.total, pageSize: 4 }}
loading={this.state.loading}
onChange={this.handleTableChange}
/>
);
}
}
export default withRouter(App);
here when i give value in search field it will call post request with request payload as follows:
{sortField: "", sortOrder: ""}
sortField: ""
sortOrder: ""
So how can i do that?

I'm not sure what you trying of achieve it here.
But you can always filter the source data of the table. Like following
<Table
bordered
columns={columns}
dataSource={this.state.data.filter(data=> Object.keys(data).filter(key => data[key].includes(searchValue)).length > 0 ? true: false)}
pagination={{ total: this.state.pagination.total, pageSize: 4 }}
loading={this.state.loading}
onChange={this.handleTableChange}
/>
let me know if it helps.

Related

Adding a Modal Instead of "prompt" in react app

Adding a Modal Instead of "prompt" in react app
Hi Iam creating a menu builder with react-sortable-tree. I want to add a Modal when clicked on Add or Edit Task. prompt is working fine here but i want Modal to be opened. I have created state and finctions for modal but unable to render on UI when clicked. anybody help
import React, { Component } from "react";
import "bootstrap/dist/css/bootstrap.css";
import "react-sortable-tree/style.css";
import { Button } from "react-bootstrap";
import "./MenuBuilder.css";
import { Modal } from "react-responsive-modal";
import "react-responsive-modal/styles.css";
import treeData from "./MenuBuilderData";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faTrashAlt, faPlus, faPen } from "#fortawesome/free-solid-svg-icons";
import SortableTree, {
toggleExpandedForAll,
getNodeAtPath,
addNodeUnderParent,
removeNode,
changeNodeAtPath,
} from "react-sortable-tree";
const maxDepth = 5;
export default class MenuBuilder extends Component {
constructor(props) {
super(props);
this.state = {
treeData: treeData,
searchString: "",
searchFocusIndex: 0,
searchFoundCount: null,
openModal: false,
};
}
onOpenModal = (e) => {
e.preventDefault();
this.setState({ openModal: true });
};
onCloseModal = () => {
this.setState({ openModal: false });
};
handleTreeOnChange = (treeData) => {
this.setState({ treeData });
};
selectPrevMatch = () => {
const { searchFocusIndex, searchFoundCount } = this.state;
this.setState({
searchFocusIndex:
searchFocusIndex !== null
? (searchFoundCount + searchFocusIndex - 1) % searchFoundCount
: searchFoundCount - 1,
});
};
selectNextMatch = () => {
const { searchFocusIndex, searchFoundCount } = this.state;
this.setState({
searchFocusIndex:
searchFocusIndex !== null
? (searchFocusIndex + 1) % searchFoundCount
: 0,
});
};
toggleNodeExpansion = (expanded) => {
this.setState((prevState) => ({
treeData: toggleExpandedForAll({
treeData: prevState.treeData,
expanded,
}),
}));
};
getNodeKey = ({ treeIndex: number }) => {
if (number === -1) {
number = null;
}
return number;
};
handleSave = () => {
console.log(JSON.stringify(this.state.treeData));
};
editTask = (path) => {
let editedNode = getNodeAtPath({
treeData: this.state.treeData,
path: path,
getNodeKey: ({ treeIndex }) => treeIndex,
ignoreCollapsed: true,
});
let newTaskTitle = prompt("Task new name:", editedNode.node.title);
if (newTaskTitle === null) return false;
editedNode.node.title = newTaskTitle;
let newTree = changeNodeAtPath({
treeData: this.state.treeData,
path: path,
newNode: editedNode.node,
getNodeKey: ({ treeIndex }) => treeIndex,
ignoreCollapsed: true,
});
// console.log(newTree);
this.setState({ treeData: newTree });
};
addTask = (path) => {
let parentNode = getNodeAtPath({
treeData: this.state.treeData,
path: path,
getNodeKey: ({ treeIndex }) => treeIndex,
ignoreCollapsed: true,
});
let newTaskTitle = parentNode.node.children ? prompt("Task name:", "default") && prompt("form ID:", "default") : prompt("Task name:", "default") // let newFormId = prompt("Form Id:", "");
if (newTaskTitle === null) return false;
let NEW_NODE = { title: newTaskTitle };
// let NEW_ID = { id: newFormId };
let parentKey = this.getNodeKey(parentNode);
let newTree = addNodeUnderParent({
treeData: this.state.treeData,
newNode: NEW_NODE,
// newId: NEW_ID,
expandParent: true,
parentKey: parentKey,
getNodeKey: ({ treeIndex }) => treeIndex,
});
this.setState({ treeData: newTree.treeData });
};
removeTask = (path) => {
let newTree = removeNode({
treeData: this.state.treeData,
path: path,
ignoreCollapsed: true,
getNodeKey: ({ treeIndex }) => treeIndex,
});
this.setState({ treeData: newTree.treeData });
};
renderTasks = () => {
const { treeData, searchString, searchFocusIndex } = this.state;
return (
<>
<SortableTree
treeData={treeData}
onChange={this.handleTreeOnChange}
maxDepth={maxDepth}
searchQuery={searchString}
searchFocusOffset={searchFocusIndex}
canDrag={({ node }) => !node.noDragging}
canDrop={({ nextParent }) => !nextParent || !nextParent.noChildren}
searchFinishCallback={(matches) =>
this.setState({
searchFoundCount: matches.length,
searchFocusIndex:
matches.length > 0 ? searchFocusIndex % matches.length : 0,
})
}
isVirtualized={true}
generateNodeProps={(taskInfo) => ({
buttons: [
<Button
variant="link"
onClick={() => this.editTask(taskInfo.path)}
>
<FontAwesomeIcon icon={faPen} color="#28a745" />
</Button>,
<Button
variant="link"
onClick={() => this.addTask(taskInfo.path)}
>
<FontAwesomeIcon icon={faPlus} color="#007bff" />
</Button>,
<Button
variant="link"
onClick={() => this.removeTask(taskInfo.path)}
>
<FontAwesomeIcon icon={faTrashAlt} color="#dc3545" />
</Button>,
],
})}
/>
<Button style={{ width: "100px" }} onClick={this.handleSave}>
save
</Button>
</>
);
};
render() {
return (
<>
<div className="wrapper">{this.renderTasks()}</div>
{/* <div>
<button onClick={this.onOpenModal}>Click Me</button>
<Modal open={this.state.openModal} onClose={this.onCloseModal}>
<input type="text" />
</Modal>
</div> */}
</>
);
}
}
treeData.js
const treeData = [
{
expanded: true,
title: "Contact HR",
children: [
{
expanded: true,
title: "Build relationships"
},
{
expanded: true,
title: "Take a test assignment"
}
]
},
{
expanded: true,
title: "Complete a test assignment",
children: [
{
expanded: true,
title: "Send link to this doc through LinkedIn"
}
]
},
{
expanded: true,
title: "Discuss Proposal details",
children: [
{
expanded: true,
title: "Prepare list of questions."
},
{
expanded: true,
title: "Other coming soon..."
}
]
},
{
expanded: true,
title: "Make an appointment for a technical interview",
children: [
{
expanded: true,
title: "Discuss details of the technical interview"
},
{
expanded: true,
title: "Prepare to Technival Interview"
}
]
},
{
expanded: true,
title: "Accept or Decline Offer"
}
];
export default treeData;

calling setState from onClick JavaScript function not working

I am trying to create a button that will make visible a form to edit any contact on my list. However, when I press the button, nothing happens.
I have the initial state set to
this.state = {
contacts: [],
showEditWindow: false,
EditContactId: ''
};
I added a function:
editContact = (id) => {
this.setState({
showEditWindow: true, EditContactId: {id}
});
};
and a column:
{
title: "",
key: "action",
render: (record) => (
<button onClick={() => this.editContact(record.id)}
>
Edit
</button>
)
},
I imported EditContactModal and call it as
<EditContactModal reloadContacts={this.reloadContacts}
showEditWindow={this.state.showEditWindow}
EditContactId={this.state.EditContactId}/>
If I manually set this.state to showEditWindow:true, the window appears; however, either this.editContact(id) is not being called or it is not changing the state.
Calling this.deleteContact(id) works fine, as does setState in loadContacts() and reloadContacts()
What I am doing wrong?
Below are the full components.
Contacts.jsx
import { Table, message, Popconfirm } from "antd";
import React from "react";
import AddContactModal from "./AddContactModal";
import EditContactModal from "./EditContactModal";
class Contacts extends React.Component {
constructor(props) {
super(props);
this.state = {
contacts: [],
showEditWindow: false,
EditContactId: ''
};
this.editContact = this.editContact.bind(this);
};
columns = [
{
title: "First Name",
dataIndex: "firstname",
key: "firstname"
},
{
title: "Last Name",
dataIndex: "lastname",
key: "lastname"
},{
title: "Hebrew Name",
dataIndex: "hebrewname",
key: "hebrewname"
},{
title: "Kohen / Levi / Yisroel",
dataIndex: "kohenleviyisroel",
key: "kohenleviyisroel"
},{
title: "Frequent",
dataIndex: "frequent",
key: "frequent",
},{
title: "Do Not Bill",
dataIndex: "donotbill",
key: "donotbill"
},
{
title: "",
key: "action",
render: (record) => (
<button onClick={() => this.editContact(record.id)}
>
Edit
</button>
)
},
{
title: "",
key: "action",
render: (_text, record) => (
<Popconfirm
title="Are you sure you want to delete this contact?"
onConfirm={() => this.deleteContact(record.id)}
okText="Yes"
cancelText="No"
>
<a type="danger">
Delete{" "}
</a>
</Popconfirm>
),
},
];
componentDidMount = () => {
this.loadContacts();
}
loadContacts = () => {
const url = "http://localhost:3000/contacts";
fetch(url)
.then((data) => {
if (data.ok) {
return data.json();
}
throw new Error("Network error.");
})
.then((data) => {
data.forEach((contact) => {
const newEl = {
key: contact.id,
id: contact.id,
firstname: contact.firstname,
lastname: contact.lastname,
hebrewname: contact.hebrewname,
kohenleviyisroel: contact.kohenleviyisroel,
frequent: contact.frequent.toString(),
donotbill: contact.donotbill.toString(),
};
this.setState((prevState) => ({
contacts: [...prevState.contacts, newEl],
}));
});
})
.catch((err) => message.error("Error: " + err));
};
reloadContacts = () => {
this.setState({ contacts: [] });
this.loadContacts();
};
deleteContact = (id) => {
const url = `http://localhost:3000/contacts/${id}`;
fetch(url, {
method: "delete",
})
.then((data) => {
if (data.ok) {
this.reloadContacts();
return data.json();
}
throw new Error("Network error.");
})
.catch((err) => message.error("Error: " + err));
};
editContact = (id) => {
this.setState({
showEditWindow: true, EditContactId: {id}
});
};
render = () => {
return (
<>
<Table
className="table-striped-rows"
dataSource={this.state.contacts}
columns={this.columns}
pagination={{ pageSize: this.pageSize }}
/>
<AddContactModal reloadContacts={this.reloadContacts} />
<EditContactModal reloadContacts={this.reloadContacts}
showEditWindow={this.state.showEditWindow}
EditContactId={this.state.EditContactId}/>
</>
);
}
}
export default Contacts;
EditContactModal.jsx
import { Button, Form, Input, Modal, Select } from "antd";
import React from "react";
import ContactForm from './ContactForm';
const { Option } = Select;
class EditContactModal extends React.Component {
formRef = React.createRef();
state = {
visible: this.props.showEditWindow,
};
onFinish = (values) => {
const url = `http://localhost:3000/contacts/${this.props.EditContactId}`;
fetch(url, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(values),
})
.then((data) => {
if(data.ok) {
this.handleCancel();
return data.json();
}
throw new Error("Network error.");
})
.then(() => {
this.props.reloadContacts();
})
.catch((err) => console.error("Error: " + err))
};
showModal = () => {
this.setState({
visible: true,
});
};
handleCancel = () => {
this.setState({
visible: false,
});
};
render() {
return (
<>
{/*<Button type="primary" onClick={this.showModal}>
Create New +
</Button>*/}
<Modal
title="Edit Contact"
visible={this.state.visible}
onCancel={this.handleCancel}
footer={null}
>
<ContactForm />
</Modal>
</>
);
}
}
export default EditContactModal;
if your aim is to perform an update to the state object, you must not pass mutable data, but copy it instead into a new object.
this will allow the state changes to be picked up.
so, prefer setState({ ...state, ...someObject }) over setState(someObject).

fluent ui details List implementation in Functional component

Can anybody send code on how to implement fluent UI details List in Functional Component(https://developer.microsoft.com/en-us/fluentui#/controls/web/detailslist/basic) and how to fetch data from API to details List
That's a start you will need to "refact" this code by the way this is a really good practice :
import * as React from "react";
import { Announced } from "office-ui-fabric-react/lib/Announced";
import {
TextField,
ITextFieldStyles
} from "office-ui-fabric-react/lib/TextField";
import {
DetailsList,
DetailsListLayoutMode,
Selection,
IColumn
} from "office-ui-fabric-react/lib/DetailsList";
import { MarqueeSelection } from "office-ui-fabric-react/lib/MarqueeSelection";
import { Fabric } from "office-ui-fabric-react/lib/Fabric";
import { mergeStyles } from "office-ui-fabric-react/lib/Styling";
import { Text } from "office-ui-fabric-react/lib/Text";
const exampleChildClass = mergeStyles({
display: "block",
marginBottom: "10px"
});
const textFieldStyles: Partial<ITextFieldStyles> = {
root: { maxWidth: "300px" }
};
export interface IDetailsListBasicExampleItem {
key: number;
name: string;
value: number;
}
export interface IDetailsListBasicExampleState {
items: IDetailsListBasicExampleItem[];
selectionDetails: string;
}
export const DetailsListBasicExampleFunction: React.FunctionComponent<
{} | IDetailsListBasicExampleState
> = () => {
const _allItems: IDetailsListBasicExampleItem[] = [];
const [selection, setSelection] = React.useState<Selection | undefined>();
function _getSelectionDetails(): string {
const selectionCount = selection ? selection.getSelectedCount() : 0;
switch (selectionCount) {
case 0:
return "No items selected";
case 1:
return (
"1 item selected: " +
(selection.getSelection()[0] as IDetailsListBasicExampleItem).name
);
default:
return `${selectionCount} items selected`;
}
}
const [state, setState] = React.useState({
items: _allItems,
selectionDetails: _getSelectionDetails()
});
React.useEffect(() => {
const _selection: Selection = new Selection({
onSelectionChanged: () =>
setState((prev) => {
return { ...prev, selectionDetails: _getSelectionDetails() };
})
});
setSelection(_selection);
for (let i = 0; i < 200; i++) {
_allItems.push({
key: i,
name: "Item " + i,
value: i
});
}
setState((prev) => {
return { ...prev, items: _allItems };
});
}, []);
const _columns: IColumn[] = [
{
key: "column1",
name: "Name",
fieldName: "name",
minWidth: 100,
maxWidth: 200,
isResizable: true
},
{
key: "column2",
name: "Value",
fieldName: "value",
minWidth: 100,
maxWidth: 200,
isResizable: true
}
];
// Populate with items for demos.
const _onFilter = (
ev: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>,
text: string
): void => {
console.log(text);
setState((prev) => {
return {
...prev,
items: text
? _allItems.filter((i) => i.name.toLowerCase().indexOf(text) > -1)
: _allItems
};
});
};
const _onItemInvoked = (item: IDetailsListBasicExampleItem): void => {
alert(`Item invoked: ${item.name}`);
};
return selection ? (
<Fabric>
<div className={exampleChildClass}>{state.selectionDetails}</div>
<Text>
Note: While focusing a row, pressing enter or double clicking will
execute onItemInvoked, which in this example will show an alert.
</Text>
<Announced message={state.selectionDetails} />
<TextField
className={exampleChildClass}
label="Filter by name:"
onChange={(e, t) => _onFilter(e, t ?? "")}
styles={textFieldStyles}
/>
<Announced
message={`Number of items after filter applied: ${state.items.length}.`}
/>
<MarqueeSelection selection={selection}>
<DetailsList
items={state.items}
columns={_columns}
setKey="set"
layoutMode={DetailsListLayoutMode.justified}
selection={selection}
selectionPreservedOnEmptyClick={true}
ariaLabelForSelectionColumn="Toggle selection"
ariaLabelForSelectAllCheckbox="Toggle selection for all items"
checkButtonAriaLabel="select row"
onItemInvoked={_onItemInvoked}
/>
</MarqueeSelection>
</Fabric>
) : (
<div>Loading</div>
);
};
UPDATE
To pass this sample of code in JSX this is pretty easy you just need to remove all type thing.
And to fetch data I use axios.
see the code below:
import * as React from "react";
import { Announced } from "office-ui-fabric-react/lib/Announced";
import { TextField } from "office-ui-fabric-react/lib/TextField";
import {
DetailsList,
DetailsListLayoutMode,
Selection
} from "office-ui-fabric-react/lib/DetailsList";
import { MarqueeSelection } from "office-ui-fabric-react/lib/MarqueeSelection";
import { Fabric } from "office-ui-fabric-react/lib/Fabric";
import { mergeStyles } from "office-ui-fabric-react/lib/Styling";
import { Text } from "office-ui-fabric-react/lib/Text";
import axios from "axios";
const exampleChildClass = mergeStyles({
display: "block",
marginBottom: "10px"
});
const textFieldStyles = {
root: { maxWidth: "300px" }
};
export const DetailsListBasicExampleFunction = () => {
const _allItems = [];
const [selection, setSelection] = React.useState();
function _getSelectionDetails() {
const selectionCount = selection ? selection.getSelectedCount() : 0;
switch (selectionCount) {
case 0:
return "No items selected";
case 1:
return "1 item selected: " + selection.getSelection()[0].name;
default:
return `${selectionCount} items selected`;
}
}
const [state, setState] = React.useState({
items: _allItems,
selectionDetails: _getSelectionDetails()
});
React.useEffect(() => {
const _selection = new Selection({
onSelectionChanged: () =>
setState((prev) => {
return { ...prev, selectionDetails: _getSelectionDetails() };
})
});
setSelection(_selection);
//********************** */fetch data from api***************************************
axios
.get("/data.json") //pass your url in param
.then((res) =>
setState((prev) => {
return { ...prev, items: res.data };
})
); //pass data in setState
}, []);
const _columns = [
{
key: "column1",
name: "Name",
fieldName: "name",
minWidth: 100,
maxWidth: 200,
isResizable: true
},
{
key: "column2",
name: "Value",
fieldName: "value",
minWidth: 100,
maxWidth: 200,
isResizable: true
}
];
// Populate with items for demos.
const _onFilter = (ev, text) => {
console.log(text);
setState((prev) => {
return {
...prev,
items: text
? _allItems.filter((i) => i.name.toLowerCase().indexOf(text) > -1)
: _allItems
};
});
};
const _onItemInvoked = (item) => {
alert(`Item invoked: ${item.name}`);
};
return selection ? (
<Fabric>
<div className={exampleChildClass}>{state.selectionDetails}</div>
<Text>
Note: While focusing a row, pressing enter or double clicking will
execute onItemInvoked, which in this example will show an alert.
</Text>
<Announced message={state.selectionDetails} />
<TextField
className={exampleChildClass}
label="Filter by name:"
onChange={(e, t) => _onFilter(e, t ?? "")}
styles={textFieldStyles}
/>
<Announced
message={`Number of items after filter applied: ${state.items.length}.`}
/>
<MarqueeSelection selection={selection}>
<DetailsList
items={state.items}
columns={_columns}
setKey="set"
layoutMode={DetailsListLayoutMode.justified}
selection={selection}
selectionPreservedOnEmptyClick={true}
ariaLabelForSelectionColumn="Toggle selection"
ariaLabelForSelectAllCheckbox="Toggle selection for all items"
checkButtonAriaLabel="select row"
onItemInvoked={_onItemInvoked}
/>
</MarqueeSelection>
</Fabric>
) : (
<div>Loading</div>
);
};

React: disable a filtered item

I am creating an activity, where a user needs to match two words on click. Like on the picture below.
If words match they should get disabled.
My state is following
this.state = {
data: [],
mixedWords: [],
myanswers: [],
allPairs: [],
checked: false,
isCorrect: false,
isIncorrect: false
};
For example myanswers array maybe like this.
["more than", "более"]
mixedWords array is the following
[{translation: "more than", disabled: false},
{translation: "capital", disabled: false},
{word: "более", disabled: false},
{translation: "famous", disabled: false},
{word: "проживает", disabled: false},
{translation: "is living", disabled: false},
{word: "известный", disabled: false},
{word: "столице", disabled: false}
]
This function is responsible for modifying disabled property. But the problem is that it outputs only filtered items. How can I output mixedWords array with modifyed disabled property for specific items
const myFunction = (value) => {
const mixedWords = [...this.state.mixedWords]
const result = mixedWords.filter(word => word.translation === value || word.word === value );
const newResult = Object.assign({}, result[0], { disabled:true })
this.setState({
mixedWords:[newResult]
})
}
this.state.myanswers.forEach(myFunction)
Full code
/* eslint-disable no-extend-native */
import React, { Component } from "react";
//import click from "../data/media/click.wav";
//import correct from "../data/media/correct.wav";
//import denied from "../data/media/denied.mp3";
let _ = require("lodash");
class Quiz extends Component {
constructor (props) {
super(props);
this.state = {
data: [],
mixedWords: [],
myanswers: [],
allPairs: [],
checked: false,
isCorrect: false,
isIncorrect: false
};
}
componentDidMount() {
let mixedWords = [];
let allPairs = [];
this.props.data.quiz && this.props.data.quiz.map((item) => {
mixedWords.push({word:item.word, disabled:false},{ translation:item.translation,disabled:false});
allPairs.push(item.pair);
return (mixedWords, allPairs);
});
this.setState({
data: this.props.data.quiz,
mixedWords: _.shuffle(mixedWords),
allPairs
});
//console.log(this.props.data);
}
selectWords = (e) => {
let items = e.target.value;
let myanswers = this.state.myanswers.concat(items);
this.setState({ myanswers }, () => {
if (this.state.myanswers.length === 2) {
if (this.checkAnswers(this.state.myanswers, this.state.allPairs)) {
console.log("correct");
const myFunction = (value) => {
const mixedWords = [...this.state.mixedWords]
const result = mixedWords.filter(word => word.translation === value || word.word === value );
const newResult = Object.assign({}, result[0], { disabled:true })
this.setState({
mixedWords:[newResult]
})
}
this.state.myanswers.forEach(myFunction)
this.setState({
myanswers:[]
})
} else {
console.log("incorrect");
this.setState({
myanswers:[]
})
}
} else {
console.log('choose a pair');
}
});
};
checkAnswers = (answersArr, allPairs) => {
let bools = []
allPairs.forEach((arr) => {
this.arraysEqual(answersArr, arr);
//console.log(this.arraysEqual(answersArr, arr));
//console.log(arr, this.state.myanswers);
bools.push(this.arraysEqual(answersArr, arr))
});
if (bools.includes(true)) {
return true
}
};
arraysEqual = (a, b) => {
return a.sort().toString() === b.sort().toString()
};
render() {
console.log(this.state.mixedWords);
console.log(this.state.myanswers);
//console.log(this.state.allPairs);
//console.log(this.state.myanswers.join(" ") === this.state.answers.join(" "));
return (
<div>
<div className="tags are-medium">
{ this.state.mixedWords.map((item) => (
<button disabled={item.disabled} value={ item.word || item.translation } onClick={ (e) => { this.selectWords(e); } } className="tag is-warning">{ item.word || item.translation }</button>
)) }
</div>
</div>
);
}
}
export default Quiz;
selectWords = (e) => {
let items = e.target.value;
let myanswers = this.state.myanswers.concat(items);
this.setState({ myanswers }, () => {
if (this.state.myanswers.length === 2) {
if (this.checkAnswers(this.state.myanswers, this.state.allPairs)) {
console.log("correct");
const myFunction = (value) => {
this.setState({
mixedWords:this.state.mixedWords.map(word => word.translation === value || word.word === value ? Object.assign({}, word, { disabled:true }) : word)
})
}
this.state.myanswers.forEach(myFunction)
this.setState({
myanswers:[]
})
} else {
console.log("incorrect");
this.setState({
myanswers:[]
})
}
} else {
console.log('choose a pair');
}
});
};

React MenuItem event.target.value not working in one, but works for the other MenuItem

I have two MenuItem drop down menus. The first is for selecting between two items (not working) and the second drop down menu has a list of years, which is working.
The following are the functions that I have created to capture the event.target.value for each of them:
handleYrChange = (event) => {
console.log('handleYrChange: ' + event.target.value);
this.setState({ data: [] });
getPartIdUpperSa(event.target.value).subscribe((res) => {
this.setState({ data: res });
this.setState({ isLoading: false });
});
this.props.isLoading ? this.setState({ isLoading: false }) : this.setState({ isLoading: true });
this.setState({ yrValue: event.target.value });
this.onCloseYr();
}
handleSaChange = (event) => {
console.log('handleSaChange: ' + event.target.value);
if(event.target.value === 'notSa') {
this.setState({ isPartIdUpperSa: false });
} else {
this.setState({ isPartIdUpperSa: true });
}
setBaseUrl(event.target.value);
this.setState({ saValue: event.target.value });
this.onCloseSa();
}
handleYrClick = (event) => {
this.setState({ yrAnchorEl: event.target })
this.setState({ yrOpen: true });
}
handleSaClick = (event) => {
this.setState({ saAnchorEl: event.target })
this.setState({ saOpen: true });
}
The following is a screen shot of when I have tried to click on the items. As you can see, the drop down for years is working as expected, yet the other is capturing "0"
The following is the full component, along with the service that it is subscribed:
First the component:
import React from "react";
import { FormGroup, FormControl, Button, Menu, MenuItem } from '#material-ui/core';
import MUIDataTable from "mui-datatables";
import { MuiThemeProvider } from '#material-ui/core/styles';
import { getPartIdUpperSa } from '../services/part-id-upper-sa-service';
import { setBaseUrl } from '../services/part-id-upper-sa-service'
import theme from '../theme';
export default class ParIdUpperSaComponent extends React.Component {
state = {
data: [],
Header: [],
totalCount: 10,
options: {
pageSize: 16,
page: 0,
filterType: "dropdown",
selectableRows: false,
responsive: "scroll",
resizableColumns: true,
className: this.name,
textLabels: {
body: {
noMatch: this.props.isLoading ?
'' :
'Please wait while processing...',
},
},
},
divAnchorEl: null,
yrValue: '2020',
yrOpen: false,
yrAnchorEl: null,
yrs: [],
saValue: 'sa',
saOpen: false,
saAnchorEl: null,
sa: ["sa","notSa"],
isLoading: true,
isPartIdUpperSa: true
}
componentDidMount() {
// create array of years for the past 18 years
const currentYr = new Date().getFullYear();
for(let x = 0; x < 18; x++) {
this.state.yrs.push(currentYr - x );
}
this.subscription = getPartIdUpperSa().subscribe((res) => {
this.setState({ data: res });
this.props.isLoading ? this.setState({ textLabels: '' }) : this.setState({ textLabels: 'Please wait while processing...' });
this.setState({ isLoading: false });
this.setState({ Header: [
{
label: "Part ID",
name: 'part_id_upper',
options: {
className: 'first-col'
}
},
{
label: "Seq",
name: 'sequence',
options: {
className: 'sec-col'
}
},
{
label: "Qty",
name: 'quantity',
options: {
className: 'sm-col'
}
},
{
label: "Dt Orig",
name: 'date_originated',
options: {
className: 'mid-col'
}
},
{
label: "Div",
name: 'code_division',
options: {
className: 'sm-col'
}
},
]});
this.setState({
totalCount: Math.ceil(this.state.data.length / this.state.pageSize)
});
})
}
componentWillUnmount() {
// unsubscribe to ensure no memory leaks
this.subscription.unsubscribe();
}
handleYrChange = (event) => {
console.log('handleYrChange: ' + event.target.value);
// this.setState({value: event.target.value ? event.target.value : ''});
this.setState({ data: [] });
getPartIdUpperSa(event.target.value).subscribe((res) => {
this.setState({ data: res });
this.setState({ isLoading: false });
});
this.props.isLoading ? this.setState({ isLoading: false }) : this.setState({ isLoading: true });
this.setState({ yrValue: event.target.value });
this.onCloseYr();
}
handleSaChange = (event) => {
console.log('handleSaChange: ' + event.target.value);
if(event.target.value === 'notSa') {
this.setState({ isPartIdUpperSa: false });
} else {
this.setState({ isPartIdUpperSa: true });
}
setBaseUrl(event.target.value);
this.setState({ saValue: event.target.value });
this.onCloseSa();
}
handleYrClick = (event) => {
this.setState({ yrAnchorEl: event.target })
this.setState({ yrOpen: true });
}
handleSaClick = (event) => {
this.setState({ saAnchorEl: event.target })
this.setState({ saOpen: true });
}
onCloseYr = () => {
this.setState({ yrOpen: false });
}
onCloseSa = () => {
this.setState({ saOpen: false });
}
render() {
let arrayofSa = this.state.sa;
let saDropDown = arrayofSa.map((sa) =>
<MenuItem onClick={(event) => this.handleSaChange(event)} value={sa} key={sa}>
{sa}
</MenuItem>
);
let arrayOfYrs = this.state.yrs;
let yrDropDown = arrayOfYrs.map((yrs) =>
<MenuItem onClick={(event) => this.handleYrChange(event)} value={yrs} key={yrs}>
{yrs}
</MenuItem>
);
return (
<div>
<MuiThemeProvider theme={theme}>
<FormGroup column='true'>
<FormControl>
<Button aria-controls="simple-menu" aria-haspopup="true" onClick={this.handleSaClick}>
Select Sa or NotToSa
</Button>
<Menu id="sa-menu" open={this.state.saOpen}
anchorEl={this.state.saAnchorEl} onClose={this.onCloseSa}
defaultValue={this.state.saValue ? this.state.saValue : ''} >
{saDropDown}
</Menu>
<Button aria-controls="simple-menu" aria-haspopup="true" onClick={this.handleYrClick}>
Select Year
</Button>
<Menu id="yrs-menu" open={this.state.yrOpen}
anchorEl={this.state.yrAnchorEl} onClose={this.onCloseYr}
defaultValue={this.state.yrValue ? this.state.yrValue : ''} >
{yrDropDown}
</Menu>
</FormControl>
</FormGroup>
</MuiThemeProvider>
{this.state.isLoading ? <img src="ajax-loader.gif" alt="loading gif" /> : ''}
<MUIDataTable
title="Part ID Upper Sa / Not Sa Report"
data={ this.state.data }
columns={ this.state.Header }
options={ this.state.options }
/>
</div>
);
}
}
The following is the service:
import { ajax } from "rxjs/ajax";
import { Observable } from "rxjs";
let base_url = 'https://localhost:5001/PartIdUpperSa';
export const getBaseUrl = () => {
return base_url;
}
export const setBaseUrl = (param) => {
console.log("from within setBaseUrl: " + param);
if(param === 'notSa') {
base_url = 'https://localhost:5001/PartIdUpperNotSa';
} else {
base_url = 'https://localhost:5001/PartIdUpperSa';
}
}
let state = {
data: []
}
export const getPartIdUpperSa = (yr) => {
return new Observable(observe => {
let mYr = new Date().getFullYear();
let tempYr = (yr)? yr : mYr;
state.data = ajax
.get(base_url + "/" + tempYr)
.subscribe(resu => {
state.data = resu.response ;
// console.log("from within getPartIdUpperSa: " + JSON.stringify(resu.response));
observe.next(resu.response);
});
});
}
As usual, thanks in advance
I was able to find a work around. If someone could explain why this works, then I would appreciate it.
The component now uses numbers instead of characters in the array called "sa," which made it function as expected.
I used this:
sa: ["1","2"],
instead of this:
sa: ["sa","notSa"],
And it worked, the following is the complete component:
import React from "react";
import { FormGroup, FormControl, Button, Menu, MenuItem } from '#material-ui/core';
import MUIDataTable from "mui-datatables";
import { MuiThemeProvider } from '#material-ui/core/styles';
import { getPartIdUpperSa } from '../services/part-id-upper-sa-service';
import { setBaseUrl } from '../services/part-id-upper-sa-service'
import theme from '../theme';
export default class ParIdUpperSaComponent extends React.Component {
state = {
data: [],
Header: [],
totalCount: 10,
options: {
pageSize: 16,
page: 0,
filterType: "dropdown",
selectableRows: false,
responsive: "scroll",
resizableColumns: true,
className: this.name,
textLabels: {
body: {
noMatch: this.props.isLoading ?
'' :
'Please wait while processing...',
},
},
},
divAnchorEl: null,
yrValue: '2020',
yrOpen: false,
yrAnchorEl: null,
yrs: [],
saValue: '1',
saOpen: false,
saAnchorEl: null,
sa: ["1","2"],
isLoading: true,
isPartIdUpperSa: true
}
componentDidMount() {
// create array of years for the past 18 years
const currentYr = new Date().getFullYear();
for(let x = 0; x < 18; x++) {
this.state.yrs.push(currentYr - x );
}
this.subscription = getPartIdUpperSa().subscribe((res) => {
this.setState({ data: res });
this.props.isLoading ? this.setState({ textLabels: '' }) : this.setState({ textLabels: 'Please wait while processing...' });
this.setState({ isLoading: false });
this.setState({ Header: [
{
label: "Part ID",
name: 'part_id_upper',
options: {
className: 'first-col'
}
},
{
label: "Seq",
name: 'sequence',
options: {
className: 'sec-col'
}
},
{
label: "Qty",
name: 'quantity',
options: {
className: 'sm-col'
}
},
{
label: "Dt Orig",
name: 'date_originated',
options: {
className: 'mid-col'
}
},
{
label: "Div",
name: 'code_division',
options: {
className: 'sm-col'
}
},
]});
this.setState({
totalCount: Math.ceil(this.state.data.length / this.state.pageSize)
});
})
}
componentWillUnmount() {
// unsubscribe to ensure no memory leaks
this.subscription.unsubscribe();
}
handleYrChange = (event) => {
console.log('handleYrChange: ' + event.target.value);
this.setState({ data: [] });
getPartIdUpperSa(event.target.value).subscribe((res) => {
this.setState({ data: res });
this.setState({ isLoading: false });
});
this.props.isLoading ? this.setState({ isLoading: false }) : this.setState({ isLoading: true });
this.setState({ yrValue: event.target.value });
this.onCloseYr();
}
handleSaChange = (event) => {
console.log('handleSaChange: ' + event.target.value);
if(event.target.value === '2') {
this.setState({ isPartIdUpperSa: false });
} else {
this.setState({ isPartIdUpperSa: true });
}
setBaseUrl(event.target.value);
this.setState({ saValue: event.target.value });
this.onCloseSa();
}
handleYrClick = (event) => {
this.setState({ yrAnchorEl: event.target })
this.setState({ yrOpen: true });
}
handleSaClick = (event) => {
this.setState({ saAnchorEl: event.target })
this.setState({ saOpen: true });
}
onCloseYr = () => {
this.setState({ yrOpen: false });
}
onCloseSa = () => {
this.setState({ saOpen: false });
}
render() {
let arrayofSa = this.state.sa;
let saDropDown = arrayofSa.map((sa) =>
<MenuItem onClick={(event) => this.handleSaChange(event)} value={sa} key={sa}>
{sa}
</MenuItem>
);
let arrayOfYrs = this.state.yrs;
let yrDropDown = arrayOfYrs.map((yrs) =>
<MenuItem onClick={(event) => this.handleYrChange(event)} value={yrs} key={yrs}>
{yrs}
</MenuItem>
);
return (
<div>
<MuiThemeProvider theme={theme}>
<FormGroup column='true'>
<FormControl>
<Button aria-controls="simple-menu" aria-haspopup="true" onClick={this.handleSaClick}>
Select Sa or NotToSa
</Button>
<Menu id="sa-menu" open={this.state.saOpen}
anchorEl={this.state.saAnchorEl} onClose={this.onCloseSa}
defaultValue={this.state.saValue ? this.state.saValue : ''} >
{saDropDown}
</Menu>
<Button aria-controls="simple-menu" aria-haspopup="true" onClick={this.handleYrClick}>
Select Year
</Button>
<Menu id="yrs-menu" open={this.state.yrOpen}
anchorEl={this.state.yrAnchorEl} onClose={this.onCloseYr}
defaultValue={this.state.yrValue ? this.state.yrValue : ''} >
{yrDropDown}
</Menu>
</FormControl>
</FormGroup>
</MuiThemeProvider>
{this.state.isLoading ? <img src="ajax-loader.gif" alt="loading gif" /> : ''}
<MUIDataTable
title="Part ID Upper Sa / Not Sa Report"
data={ this.state.data }
columns={ this.state.Header }
options={ this.state.options }
/>
</div>
);
}
}
The following is the service that the component is subscribed to it:
import { ajax } from "rxjs/ajax";
import { Observable } from "rxjs";
let base_url = 'https://localhost:5001/PartIdUpperSa';
export const getBaseUrl = () => {
return base_url;
}
export const setBaseUrl = (param) => {
console.log("from within setBaseUrl: " + param);
if(param == '1') {
base_url = 'https://localhost:5001/PartIdUpperSa';
} else {
base_url = 'https://localhost:5001/PartIdUpperNotSa';
}
}
let state = {
data: []
}
export const getPartIdUpperSa = (yr) => {
return new Observable(observe => {
let mYr = new Date().getFullYear();
let tempYr = (yr)? yr : mYr;
state.data = ajax
.get(base_url + "/" + tempYr)
.subscribe(resu => {
state.data = resu.response ;
observe.next(resu.response);
});
});
}
Once more, if someone could explain why numbers work with event.target.value and characters do not, then I would appreciate it.

Resources