I'm using prime react to create a table, the last column of the table is for the actions that can be performed on the table, however I'm following the docs, but the onClick event is not working on the buttons. When I click on the search button I get the error: "UserList.js:19 Uncaught TypeError: _this2.selectUser is not a function"
Any clues please?
The code:
actionTemplate(rowData, column) {
console.log('column', column);
console.log('rowData', rowData);
return (<div>
<Button
type="button" icon="fa-search"
className="ui-button-success" onClick={() => this.selectUser(1)}
/>
<Button
type="button" icon="fa-edit"
className="ui-button-warning"
/>
</div>);
}
selectUser(userId) {
console.log('selectUser');
userId = 1;
this.props.actions.fetchUser(userId);
}
renderTable() {
const paginatorLeft = <Button icon="fa-refresh" />;
/* const users = [
{ name: '1', email: '1981', updateDate: '', creationDate: '05/03/2016' },
{ name: '2', email: '1982', updateDate: '', creationDate: '04/02/2017' },
]; */
const { users } = this.props;
return (
<DataTable
value={users} paginator paginatorLeft={paginatorLeft}
rows={10} rowsPerPageOptions={[5, 10, 20]}
>
<Column field="name" header="Name" filter style={{ textAlign: 'center', width: '6em' }} />
<Column field="email" header="Email" filter style={{ textAlign: 'center', width: '6em' }} />
<Column field="lastUpdate" header="Last update" style={{ textAlign: 'center', width: '6em' }} />
<Column field="creationDate" header="Creation Date" style={{ textAlign: 'center', width: '6em' }} />
<Column body={this.actionTemplate} header="Actions" style={{ textAlign: 'center', width: '6em' }} />
</DataTable>
);
}
Try:
<Column body={this.actionTemplate.bind(this)} header="Actions" style={{ textAlign: 'center', width: '6em' }} />
My guess is that actionTemplate is called within another object context that's why selectUser is not defined/a function.
Related
it should populate all rows to the table (the rows are from from the api is an array of objects) currently the issue is only render that last object of the array and I have no idea why it keeps on repeating , as you can see on the screenshot it only loads 1 object and then repeats that is why all the rows have the same value.
By the way the rows or the data from the api is an array of objects /
Maybe someone has an idea on how we can address this issue. Thanks.
#rows from the api result from the console log this is the rows that is been feed to the grid
#react code
export const StyledDataGrid = styled(DataGrid)`
.MuiDataGrid-row: nth-of-type(odd) {
background: #E3E0E0
}
.MuiDataGrid-cell {
border-right: 1px solid #C4C4C4;
}
.MuiDataGrid-columnHeader {
border-right: 1px solid #C4C4C4;
}
.MuiDataGrid-columnSeparator--sideRight {
display: none
}
.MuiDataGrid-columnHeaderTitleContainer {
justify-content: space-between;
}
.MuiDataGrid-iconButtonContainer {
visibility: visible;
width: auto;
}
`;
const PortfolioPage: FC = () => {
const router = useRouter();
const dispatch = useAppDispatch();
const { isPending, isError, isSuccess, grid, isSaveSuccess } = useAppSelector(
(state) => state.region
);
const [snackbarOpen, setSnackbarOpen] = useState<boolean>(false);
const [selectedRow, setSelectedRow] = useState<IRegional | null>(null)
const rows = grid ? grid.items : [];
console.log('rows' , rows)
const fetchGridItems = () => {
const payload: IPageListApiRequestPayload = {
accountId: 1,
sortKey: JSON.stringify([]),
sortOrder: JSON.stringify([]),
page: 1,
pageSize: 100,
searchString: '',
};
dispatch(getRegionGrid(payload));
}
useEffect(() => {
// Save success
if (isSaveSuccess) {
setSnackbarOpen(true);
fetchGridItems();
}
}, [isSaveSuccess])
useEffect(() => {
if (router.isReady) {
fetchGridItems();
}
}, [router.isReady]);
const renderList = (data: IEmail) => (
<div style={{display: 'block'}}>
<div>Full Name: {data.firstName} {data.lastName}</div>
<div>Email Address: {data.emailAddress}</div>
</div>
)
const columns: GridColDef[] = [
{
field: "associateDirectorofConstructionOps",
headerName: "Associate Director of Construction Ops",
minWidth: 300,
flex: 0.16,
disableColumnMenu: true,
renderCell: (params: GridRenderCellParams<string>) => (
<>
{
params.row.associateDirectorofConstructionOps ? params.row.associateDirectorofConstructionOps.map((prop: IEmail) => renderList(prop))
: null
}
</>
),
},
];
const fixedColumnLeft: GridColDef[] = [
{
field: "regionName",
headerName: "Region Division",
flex: 0.08,
minWidth: 100,
disableColumnMenu: true,
},
{
field: "subRegionName",
headerName: "Sub-Region",
flex: 0.15,
minWidth: 50,
disableColumnMenu: true,
},
{
field: "marketName",
headerName: "Market",
flex: 0.08,
minWidth: 50,
disableColumnMenu: true,
},
];
const fixedColumnRight: GridColDef[] = [
{
field: "action",
disableColumnMenu: true,
sortable: false,
renderHeader: () => <></>,
renderCell: (params: GridRenderCellParams<string>) => (
<div
style={{
color: "rgb(110 110 110)",
display: "flex",
justifyContent: "space-between",
}}
>
<EditIcon onClick={() => handleClickOpen(params)} />
</div>
),
},
];
const [open, setOpen] = React.useState<boolean>(false);
const handleClickOpen = (data: any) => {
setSelectedRow(data.row);
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<Box sx={{ height: "100vh", background: "#EEEAEA" }}>
<Snackbar
open={snackbarOpen}
autoHideDuration={3000}
onClose={() => setSnackbarOpen(false)}>
<Alert onClose={() => setSnackbarOpen(false)} severity="success" sx={{ width: '100%' }}>
Successfully saved!
</Alert>
</Snackbar>
<EditProperties open={open} handleClose={handleClose} selectedRow={selectedRow} />
<DashboardWrapper seoProps={{
title: "PIM | Regions",
}}
title="Properties"
mainClass="properties-page">
{isError ? <div>Error Loading Regions!</div> : ""}
{isPending ? <>Loading Regions...</> : ""}
{isSuccess ? (
<>
<div
style={{
display: "flex",
justifyContent: "space-between",
width: "636px",
height: "56px",
background: "rgba(37, 36, 41, 0.9)",
padding: "8px 16px 8px 8px",
borderBottomRightRadius: "30px",
}}
>
<Input
size="small"
style={{
width: "461px",
height: "40px",
background: "#FFFFFF",
borderRadius: "4px",
outline: "none",
}}
placeholder="Search by typing property name or address"
startAdornment={
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
}
/>
<Button
variant="contained"
style={{ textTransform: "capitalize" }}
>
Search
</Button>
<div
style={{
display: "flex",
color: "#FFFFFF",
flexDirection: "column",
justifyContent: "space-between",
alignItems: "center",
marginRight: "10px",
}}
>
<TuneIcon style={{ fontSize: "32px" }} />
<span style={{ fontSize: "10px", marginTop: "-5px" }}>
Filters
</span>
</div>
</div>
<TableContainer component={Paper} style={{ marginTop: "24px" }}>
<div
style={{
borderBottom: "1px solid #C4C4C4",
padding: "16px",
display: "flex",
justifyContent: "space-between",
background: "#FFFFFF",
height: "72px",
}}
>
<label
style={{
fontWeight: "600",
fontSize: "24px",
color: "#252429",
alignSelf: "center",
}}
>
{" "}
Regions{" "}
</label>
<div
style={{
alignSelf: "center",
color: "#C4C4C4",
display: "flex",
fontSize: "16px",
}}
>
<IosShareIcon style={{ marginRight: "14px" }} />
Export
</div>
</div>
{/* Table container */}
<div style={{position: "relative", display: 'flex', justifyContent: 'space-between'}}>
{/* Left table */}
<Box
sx={{ boxShadow: 5 }}
style={{
width: "20%",
zIndex: 99,
overflow: "hidden",
background: "#FFFFFF",
}}
>
<StyledDataGrid
autoHeight
getRowId={(row) => row.accountId}
hideFooterPagination={true}
components={{
ColumnSortedAscendingIcon: UnfoldMoreIcon,
ColumnSortedDescendingIcon: UnfoldMoreIcon,
}}
rows={rows}
columns={fixedColumnLeft}
disableSelectionOnClick
experimentalFeatures={{ newEditingApi: true }}
/>
</Box>
{/* Center table */}
<div style={{overflow: 'hidden', width: '70%'}}>
<div style={{ width: '2000px', margin: 'auto', overflow: "hidden"}} >
<StyledDataGrid
autoHeight
getRowId={(row) => row.accountId}
components={{
ColumnSortedAscendingIcon: UnfoldMoreIcon,
ColumnSortedDescendingIcon: UnfoldMoreIcon,
}}
rows={rows}
columns={columns}
pageSize={100}
rowsPerPageOptions={[10, 20, 50, 100]}
disableSelectionOnClick
experimentalFeatures={{ newEditingApi: true }}
/>
</div>
</div>
{/* Right table */}
<Box
sx={{ boxShadow: 5 }}
style={{
width: "10%",
zIndex: 99,
overflow: "hidden",
background: "#FFFFFF",
}}
>
<StyledDataGrid
autoHeight
getRowId={(row) => row.accountId}
hideFooterPagination={true}
components={{
ColumnSortedAscendingIcon: UnfoldMoreIcon,
ColumnSortedDescendingIcon: UnfoldMoreIcon,
}}
rows={rows}
columns={fixedColumnRight}
disableSelectionOnClick
experimentalFeatures={{ newEditingApi: true }}
/>
</Box>
</div>
</TableContainer>
{/* <ActionButtonContainer
btnNameOne="Property"
btnNameTwo="Properties"
btnIconOne={<UploadFileIcon />}
btnIconTwo={<AddIcon />}
/> */}
</>
) : (
""
)}
</DashboardWrapper>
</Box>
Yes because of this
This line is the cause of all these problems
The DataGrid expects a unique key for every row in the table
so it's asking you where it can find that unique key
You're telling it that it can find it inside the accountId prop.
Which is not accurate because it has duplicates
Normally this should be id, but it's null everywhere in your case.
If the data source coming from your API has a property called "id", the MUI DataGrid is automatically going to use it if you didn't set the getRowId prop.
I have array of objects which I'm using map on. But the thing is, in that map I want to search the specific word from object value.
Like I have a array of objects like this:
[
{
"groupName": "TwoFactTest",
"groupId": ""
},
{
"groupName": "OU_AHMEDABAD"
"groupId": ""
}
]
I have done react code like this:
{
importedgroups.map((row, index) => {
return (
<TableRow key={row.name}>
<GroupIcon style={{ marginRight: '5px', display: 'inline-flex', verticalAlign: 'bottom' }} />
{/* <OUIcon style={{ marginRight: '5px', display: 'inline-flex', verticalAlign: 'bottom' }}
/> */}
<TableCell>{row.groupName}</TableCell>
<TableCell
align="left"
style={{ font: "normal normal 600 14px Open Sans" }}
>
{row.groupImportedAs}
</TableCell>
<TableCell>
<Button
href="javascript:void(0)"
color="primary"
disableRipple
onClick={() => removeGroup(row, index)}
style={{ textTransform: "none" }}
>
<div
style={{
display: "flex",
alignItems: "flex-end",
justifyContent: "flex-end",
}}
>
<RemoveCircleOutlineIcon
style={{
marginBottom: "-7px",
width: "14px",
height: "14px",
marginRight: "2px",
}}
/>{" "}
Remove
</div>
</Button>
</TableCell>
</TableRow>
);
});
}
I want to perform operation that when a word of OU is contained in object value, then put <OUIcon> else <GroupIcon>. I have commented out OUIcon.
Any fix?. How to do it in React?
You can render component with conditional rendering.
Try something like below:-
{importedgroups.map((row, index) => {
return (
<TableRow key={row.name}>
{row.groupName.includes('OU') ? (
<OUIcon
style={{
marginRight: '5px',
display: 'inline-flex',
verticalAlign: 'bottom'
}}
/>
) : (
<GroupIcon
style={{
marginRight: '5px',
display: 'inline-flex',
verticalAlign: 'bottom'
}}
/>
)}
<TableCell>{row.groupName}</TableCell>
<TableCell
align="left"
style={{ font: 'normal normal 600 14px Open Sans' }}
>
{row.groupImportedAs}
</TableCell>
<TableCell>
<Button
href="javascript:void(0)"
color="primary"
disableRipple
onClick={() => removeGroup(row, index)}
style={{ textTransform: 'none' }}
>
<div
style={{
display: 'flex',
alignItems: 'flex-end',
justifyContent: 'flex-end'
}}
>
<RemoveCircleOutlineIcon
style={{
marginBottom: '-7px',
width: '14px',
height: '14px',
marginRight: '2px'
}}
/>{' '}
Remove
</div>
</Button>
</TableCell>
</TableRow>
);
})}
Note:- This will render OUIcon if groupName contains OU at any place in string. If you are certain that your data will contain OU_ for all valid names than you need to update condition.
return (
<TableRow key={row.name}>
{
row.groupName.startsWith('OU') ?
<OUIcon style={{ marginRight: '5px', display: 'inline-flex', verticalAlign: 'bottom' }} /> :
<GroupIcon style={{ marginRight: '5px', display: 'inline-flex', verticalAlign: 'bottom' }} />
}
<TableCell>{row.groupName}</TableCell>
<TableCell
Using a conditional rendering, doc: https://reactjs.org/docs/conditional-rendering.html
Example:
{
importedgroups.map((row, index) => {
let icon;
if (/OU_/.test(row.groupName)) {
icon = (<OUIcon style={{ marginRight: '5px', display: 'inline-flex', verticalAlign: 'bottom' }} />);
} else {
icon = (<GroupIcon style={{ marginRight: '5px', display: 'inline-flex', verticalAlign: 'bottom' }} />);
}
return (
<TableRow key={row.name}>
{icon}
<TableCell>{row.groupName}</TableCell>
...
I have custom header which has TextInput for searching in StackNavigator.How can i get result on onChangeText of TextInput on particular class,
here is demo:
const StackNavigator = createStackNavigator({
TABS: {
screen: TabNav,
navigationOptions: ({ navigation }) => {
return {
header:
<View style={{ backgroundColor: '#025281', flexDirection:
'row', alignItems: 'center', height: 60 }}>
<TouchableOpacity
style={{ paddingLeft: 5 }}>
<Image source={require(back_arrowimg)} style={{
width: 25, height: 25, resizeMode: 'contain' }}/>
</TouchableOpacity>
<TextInput
style={{ color: 'white', paddingLeft: 15, }}
type='text'
placeholder={headerTitle}
onChangeText={this.loadUsers}
/>
</View>,
}
} },
[ConstFile.SCREEN_TITLES.WELCOME_SEARCH]: {
screen: WELCOMESEARCH,
navigationOptions: {
header: null
} }, } )
from navigationOption you can not do anything to other screen,
so what you can do is, move your header code into another file and use it as component in TabNav
something like this,
let say Header.js
<View style={{ backgroundColor: '#025281', flexDirection:
'row', alignItems: 'center', height: 60 }}>
<TouchableOpacity
style={{ paddingLeft: 5 }}>
<Image source={require(back_arrowimg)} style={{
width: 25, height: 25, resizeMode: 'contain' }}/>
</TouchableOpacity>
<TextInput
style={{ color: 'white', paddingLeft: 15, }}
type='text'
placeholder={headerTitle}
onChangeText={this.props.loadUsers} // see this change
/>
</View>
and in your TabNav.js use header as component,
<Header
loadUsers={(...your params)=>{
//do your necessary stuffs to display data in this file
}) />
I recently learn react native, but i got problem with input text. When i try to type 1st text field the 2nd text field cannot get focus, when i tap 2nd text field two times text field focus correctly
See video below : https://streamable.com/70njw
My code :
import React, { Component, Fragment } from 'react'
import { View, StyleSheet } from 'react-native'
import { Text, Button, Content, Card, CardItem, Body, Input, Icon, Item} from 'native-base'
import { Grid, Row } from 'react-native-easy-grid'
import ThemeVariable from '../../../native-base-theme/variables/platform'
import AuthHeaderNavigation from '../../components/auth/HeaderNavigation'
class LoginScreen extends Component {
state = {
input: {
email: null,
password: null
}
}
setInputState(key, value) {
this.setState(prevState => ({
input: {
...prevState.input,
[key]: [value]
}
}))
}
render() {
return (
<Fragment>
<AuthHeaderNavigation/>
<Grid>
<Row style={styles.firstRow}></Row>
<View style={styles.authWrapper}>
<Card style={styles.authCard}>
<CardItem>
<Body>
<Item>
<Icon style={{ color: ThemeVariable.footerDefaultBg }} name="person"/>
<Input onChangeText={text => this.setInputState('email', text)} placeholder="Email"/>
</Item>
</Body>
</CardItem>
<CardItem style={{ paddingTop: 0}}>
<Body>
<Item last>
<Icon style={{ color: ThemeVariable.footerDefaultBg }} name="lock"/>
<Input onChangeText={text => this.setInputState('password', text)}
secureTextEntry={true}
placeholder="Password"/>
</Item>
</Body>
</CardItem>
<CardItem>
<Body>
<Button block>
<Text> Login </Text>
</Button>
</Body>
</CardItem>
</Card>
</View>
<Row style={styles.secondRow}></Row>
</Grid>
</Fragment>
)
}
}
const styles = StyleSheet.create({
content: {
height: '100%'
},
firstRow: {
backgroundColor: ThemeVariable.footerDefaultBg
},
secondRow: {
backgroundColor: ThemeVariable.contentBaseBgColor
},
authWrapper: {
position: 'absolute',
width: '100%',
height: '100%',
flex: 1,
alignItems: 'center',
justifyContent: 'center',
flexDirection:'row',
},
authCard: {
width: '90%',
borderRadius: 6,
padding: 5,
}
})
export default LoginScreen
If i change View to ScrollView everything works correctly, but may broken page design
I need send the data line from DataTable to another page and populate the fields with React or Redux... how can i do that?
class Dtable extends Component {
componentWillMount() {
this.props.getList();
}
actionTemplate(rowData, column) {
return <div>
<Button type="button" icon="fa-search" className="ui-button-success"></Button>
<Button type="submit" icon="fa-edit" onClick={console.log(column)} className="ui-button-warning" ></Button>
</div>
}
render() {
return (
<div>
<Form onSubmit={this.props.create} />
<div className="content-section implementation" style={{ paddingTop: 1 + '%' }}>
<DataTable key="idPessoa" value={this.props.list} paginator={true} paginator={true} rows={10} rowsPerPageOptions={[5, 10, 20]} >
<Column field="idPessoa" header="Propriedade" style={{ width: 5 + '%' }} />
<Column field="nome" header="Propriedade" />
<Column field="email" header="Propriedade" />
<Column field="latitude" header="Relatório" style={{ width: 15 + '%' }} />
<Column field="longitude" header="Ativo" style={{ width: 5 + '%' }} />
<Column header="Opções" body={this.actionTemplate} style={{ textAlign: 'center', width: '100px' }} />
</DataTable>
</div>
</div>
)
}
}
const mapStateToProps = state => ({ list: state.upload.list })
const mapDispatchToProps = dispatch => bindActionCreators({ getList, create, showUpdate }, dispatch)
export default connect(mapStateToProps, mapDispatchToProps)(Dtable)
I just add the arrow function on my event ..this solve my problem..thanks guys.
actionTemplate = (rowData, column) => {
return <div>
<Button type="button" icon="fa-search" imediate='true' onClick={() => this.teste(rowData.nome,rowData.email)} className="ui-button-success"></Button>
<Button type="button" icon="fa-edit" imediate='true'
onClick={() => console.log(rowData)} className="ui-button-warning" ></Button>
</div>
}
teste = (nome,mail) => {
console.log(nome)
this.setState({name:nome,email:mail})
}