I have the following material-table and trying to use custom button (Add New) instead of default (+) one.
However, I could not manage to trigger the same method using Add New button. Here is the related part in my code:
component.js:
<MaterialTable
components={{
Toolbar: (props) => (
<Button onClick={handleRowAdd(newData, resolve)} // <-- ????
>Add New
</Button>
<div style={{ width: "13rem" }}>
<MTableToolbar {...props} />
</div>
</div>
),
Container: (props) => <Paper {...props} elevation={8} />,
}}
columns={columns}
data={data}
editable={{
onRowAdd: (newData) => // <------------------------------- ????
new Promise((resolve) => {
handleRowAdd(newData, resolve);
}),
}}
actions={
[
// {
// icon: () => <GetAppIcon />,
// tooltip: "Click me",
// onClick: (e, data) => console.log(data),
// },
]
}
onSelectionChange={(selectedRows) => console.log(selectedRows)}
options={{
toolbar: true,
addRowPosition: "first",
actionsColumnIndex: -1
}}
title=""
// icons={{ Add: () => <AddIcon /> }}
icons={{
Add: () => <AddIcon />,
// Add: props => <Icon data-mycustomid={"add-icon-handler"} />
}}
/>
And the add method:
const handleRowAdd = (newData, resolve) => {
PostWithAuth("/v1/ingredients", newData)
.then((res) => {
let dataToAdd = [...data];
dataToAdd.push(newData);
setData(dataToAdd);
resolve();
handleMessage("success", "Ingredient created successfully");
})
.catch((error) => {
resolve();
});
};
SO, how can I sole this problem?
Related
I am working on react-native-swipeout, but second time I swipe then Swipeout is not working
const SwipeableRow = ({ item, isOpen, onOpen, onPress }) => {
return (
<Swipeout
openRight={isOpen == item.id}
close={true}
onOpen={onOpen}
style={styles.background}
right={[
{
text: 'Delete',
backgroundColor: 'red',
onPress,
},
]}
>
<Row item={item} />
</Swipeout>
)}
In menu/ the name of my invited people are not diplayed there is only the InfoIcon in the Cell. I want to create a Popover, when you click on the InfoIcon, you get all the info of the invited people(name and location).
export default function Display() {
const { dishes } = JsonData;
const [anchor, setAnchor] = useState(null);
const openPopover = (event) => {
setAnchor(event.currentTarget);
};
const data = useMemo(
() => [
...
{
//Problem: participants not displayed and click not working
Header: "Invited",
id: "invited",
accessor: (row) => row.invited.map(({ name }) => name).join(", "),
Cell: (props) => (
<div>
<InfoIcon />
<Popover
open={Boolean(anchor)}
anchorEl={anchor}
anchorOrigin={{
vertical: "top",
horizontal: "left"
}}
transformOrigin={{
vertical: "bottom",
horizontal: "right"
}}
>
<Typography variant="h1">{props.participants}</Typography>
</Popover>
</div>
)
},
],
[]
);
return (
<Table
data={dishes}
columns={data}
/>
);
}
Here is my code
In addition to saving the clicked element into state so the Popover component has an element ref it needs to also store in state which specific row's participants to render into the popover. Currently the code is using a singular boolean value for all the popovers. Use the row.id to open a specific popover.
Don't forget to add the "anchor" state to the dependency array so the popover gets the latest state.
function Display() {
const { menus } = JsonData;
const [anchorId, setAnchorId] = useState(null);
const [anchorEl, setAnchorEl] = useState(null);
const openPopover = id => (event) => {
setAnchorId(id);
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorId(null);
setAnchorEl(null);
};
const data = useMemo(
() => [
{
Header: "Id",
accessor: (row) => row.id
},
{
Header: "Invited",
id: "invited",
accessor: (row) => row.invited,
Cell: (props) => (
<div>
{props.value.map(({ name }) => name).join(", ")}
<InfoIcon onClick={openPopover(props.row.id)} />
<Popover
open={anchorId === props.row.id}
onClose={handleClose}
anchorEl={anchorEl}
anchorOrigin={{
vertical: "top",
horizontal: "left"
}}
transformOrigin={{
vertical: "bottom",
horizontal: "right"
}}
>
<Typography variant="h6">
{props.value.map(({ name, location }) => (
<div key={name}>
<p>{name}</p>
<p>Location: {location}</p>
</div>
))}
</Typography>
</Popover>
</div>
)
},
{
Header: "Title",
accessor: (row) => ({ title: row.title, id: row.id }),
Cell: ({ value }) => (
<Link to={{ pathname: `/menu/${value.id}` }}>{value.title}</Link>
)
}
],
[anchorEl, anchorId]
);
const initialState = {
sortBy: [
{ desc: false, id: "id" },
{ desc: false, id: "invited" },
{ desc: false, id: "title" }
]
};
return (
<Table
data={menus}
columns={data}
initialState={initialState}
withCellBorder
withRowBorder
withSorting
withPagination
/>
);
}
The child component will add data and the parent component will display the latest data that the child component inserted, my problem is the useState didnt work properly, because the data is successfully saved but i cant see the data inserted in the parent component, need to refresh or load the page to see the latest data.
Parent component
const fetchData = async () => {
const response = await getDepartment('fmDepartments', 'fmDepartmentsId', 'All', 100, 0);
console.log(response)
response.data.map(function(u){
newUsers.push({
sequence:u.sequence,
name: u.name,
datecreated: u.datecreated,
dateupdated: u.dateupdated,
status: u.status,
actions: ([
<div className={classes.root}>
{u.status !== 1 ?(
<Tooltip title={<span style={{fontSize: 15, fontWeight: 600,}}>Deactivate</span>} arrow>
<IconButton
aria-label="Deactivate"
color="primary"
size="small"
className={classes.deactivateButton}
onClick={() => {handleActivate(u.id)}}
>
<HighlightOffIcon />
</IconButton>
</Tooltip>
):(
<Tooltip title={<span style={{fontSize: 15, fontWeight: 600,}}>Activate</span>} arrow>
<IconButton
aria-label="Active"
color="primary"
size="small"
className={classes.activateButton}
onClick={() => {handleDeactivate(u.id)}}
>
<CheckCircleOutlineIcon />
</IconButton>
</Tooltip>
)
}
</div>
])
})
})
setNewUserLists(newUsers)
}
useEffect(() => {
fetchData();
}, [reRender]);
const options = {
filter: true,
filterType: 'checkbox',
selectableRows: 'none',
print: false,
customToolbar: () => {
return (
<CustomToolbar/> //here is the link to the child component
)
},
setFilterChipProps: (colIndex, colName, data) => {
return {
color: 'primary',
variant: 'outlined',
className: 'testClass123',
};
}
};
return (
<>
<MUIDataTable
title={"Department"}
data={newUserLists}
columns={columns}
options={options}
/>
</>
)
child component
class CustomToolbar extends React.Component {
constructor(props) {
super(props)
this.HandleAdd = this.HandleAdd.bind(this);
this.state =false //here
}
HandleAdd = () => {
Swal.fire({
title: 'Add Department',
text: "Input department name below.",
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Save',
html: generateInputForms({
strname: '',
intsequence: ''
}),
preConfirm: () => {
let strname = document.getElementById('strname').value;
let intsequence = document.getElementById('intsequence').value;
if (!strname) {
Swal.showValidationMessage('The Department field is required.')
}
if (!intsequence) {
Swal.showValidationMessage('The Sequence field is required.')
}
return {
strname: document.getElementById('strname').value,
intsequence: document.getElementById('intsequence').value
}
}
}).then((result) => {
if (result.isConfirmed) {
let request = {
strresourcename: "Richard",
strapplicationcode: "SchoolApp",
strmodulename: "Department",
strtablename: "fmDepartments",
strfieldid: "fmDepartmentsId",
strname:document.getElementById('strname').value,
intsequence:document.getElementById('intsequence').value
}
addDepartment(request).then(res =>{
if (res.status == 200){
Swal.fire({
icon: 'success',
title: 'Department',
text: 'New Department has been added successfully.',
}).then(res => {
this.setState(!this.state); //here
})
}else{
Swal.fire({
icon: 'error',
title: 'Oops',
text: 'Something went wrong.',
})
}
})
}
})
}
render() {
const { classes } = this.props;
return (
<React.Fragment>
<Tooltip title={"Add"}>
<Button
variant="contained"
color="primary"
size="small"
style={{
textTransform: 'unset',
outline: 'none',
marginLeft: 20,
backgroundColor: '#00B029',
}}
onClick={this.HandleAdd}
className={classes.button}
startIcon={<AddIcon className={classes.addIcon} style={{color: '#fff',}} />}
>
Add
</Button>
</Tooltip>
</React.Fragment>
);
}
}
Is there any way to retrieve the dropdown items value? when the on-click handler gets called it doesn't the value, Instead, it returns the text and IMG component.
And also the on onchange handler attached to dropdown never gets triggered
import React from "react";
import { Dropdown, Item } from "semantic-ui-react";
import { connect } from "react-redux";
import "./currency.style.css";
const CurrencyConverter = ({ currencyDetails, initialData }) => {
const handleSelection = (e) => {
alert();
};
return (
<div className="currency-form">
<div className="selected-Country">
<img src={initialData.flag} width="30px" height="30px" />
</div>
<Dropdown
inline
text={initialData.currency}
>
<Dropdown.Menu
>
{currencyDetails.map((item) => (
<Dropdown.Item
key={Math.random()}
text={item.currencyName}
image={item.flag}
style={{ height: "70px", fontSize: "17px" }}
onClick={(event, item) => {
console.log(item);
}}
/>
))}
</Dropdown.Menu>
</Dropdown>
</div>
);
};
const mapStateToProps = ({ currency: { currencyDetails } }) => ({
currencyDetails,
});
export default connect(mapStateToProps, null)(CurrencyConverter);
First step is to assign the 'value' as part of the Dropdown.Item:
<Dropdown.Item
key={Math.random()}
text={item.currencyName}
image={item.flag}
value={item.value}
style={{ height: "70px", fontSize: "17px" }}
onClick={(event, item) => {
console.log(item);
}}
/>
Then you can grab the 'value' from item passed by the onClick event.
onClick={(event, item) => console.log(item.value)}
So long as you set the 'value' and not the 'text' in the initial Dropdown this will also let the Dropdown handle displaying the correct value when it isn't active
Here's a slightly simplified version of your code:
const currencyDetails = [
{currencyName: 'United States Dollars', value: 'USD'},
{currencyName: 'Canadian Dollars', value: 'CDN'}
]
const initialData = {currency: 'USD'}
const CurrencyConverter = () => {
const handleSelection = (e, value) => {
console.log(value)
alert(`"I Chose the value ${value.value}`)
}
return (
<div className="currency-form">
<Dropdown
inline
value={initialData.currency}
>
<Dropdown.Menu
>
{currencyDetails.map((item) => (
<Dropdown.Item
key={item.currencyName}
value={item.value}
text={item.currencyName}
style={{ height: "70px", fontSize: "17px" }}
onClick={handleSelection}
/>
))}
</Dropdown.Menu>
</Dropdown>
</div>
)
}
To read more check out the documentation:
https://react.semantic-ui.com/modules/dropdown/#usage-controlled
i'm using react navigation v5,
i'm trying to navigate to login screen from alert when user press Ok,
but currently not working with error >>
can't find variable: navigation
The function is below :
async function handleSubmit(navigation) {
try {
const value = await AsyncStorage.getItem('storage_useremail');
if (value !== null) {
fetch('https://xxxxxx/logout', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: value,
}),
}).then(res => res.json())
.then(res => {
// console.log(res.err_code)
if (res.err_code == '0000') {
Alert.alert('Notice',res.message + " (" + res.err_code + ")",[{ text: 'Yes', onPress: () => navigation.navigate('Login')} ]);
} else {
Alert.alert("Response: " + res.err_code + " - " + res.message);
}
})
}
} catch (error) {
// Error retrieving data
}
}
function HomeNavigator() {
return (
<AppStack.Navigator mode="modal" initialRouteName="Login" screenOptions={({ route, navigation }) => ({
headerStyle: {
backgroundColor: '#fb5b5a',
borderBottomWidth: 0,
},
headerRight: () => (
<Button
onPress={() => handleSubmit()}
// onPress={() => navigation.navigate('Login')}
title="Logout"
color="#fff"
/>
),
})}>
<AppStack.Screen
name="Home"
component={HomeScreen}
options={{
title: 'Home',
}}
/>
<AppStack.Screen
name="Memory"
component={MemoryScreen}
options={{
title: 'Memory',
}} />
</AppStack.Navigator>
);
}
navigation.navigate('Login') << this the part where can't navigate.
Can somebody help this?
Thanks before
Because you don't pass navigation to handleSubmit
function HomeNavigator() {
return (
<AppStack.Navigator mode="modal" initialRouteName="Login" screenOptions={({ route, navigation }) => ({
headerStyle: {
backgroundColor: '#fb5b5a',
borderBottomWidth: 0,
},
headerRight: () => (
<Button
onPress={() => handleSubmit(navigation)} // <<<<<<<<<<<< Here
// onPress={() => navigation.navigate('Login')}
title="Logout"
color="#fff"
/>
),
})}>
<AppStack.Screen
name="Home"
component={HomeScreen}
options={{
title: 'Home',
}}
/>
<AppStack.Screen
name="Memory"
component={MemoryScreen}
options={{
title: 'Memory',
}} />
</AppStack.Navigator>
);
}
onPress should be a function declaration that will be triggered when pressed
onPress: () => navigation.navigate('Login')