Does React-data-grid have a mechanism to handle pagination? - react-data-grid

I didn't see anything in the docs for pagination. Is there a built-in mechanism for this, or would I have to implement it myself?

Here is an example of pagination (Infinite scrolling) in react data grid. I am using the scrollHeight,scrollTop and clientHeight properties to check whether to load next page.You need to modify your API's to support this type of pagination.
let columns = [
{
key: 'field1',
name: 'Field1 ',
},
{
key: 'field2',
name: 'Field2 ',
},
{
key: 'field3',
name: 'Field3',
},
]
export default class DataGrid extends React.Component {
constructor(props) {
super(props)
this.state = {height: window.innerHeight - 180 > 300 ? window.innerHeight - 180 : 300,page:1}
this.rowGetter = this.rowGetter.bind(this)
this.scrollListener = () => {
if (
(this.canvas.clientHeight +
this.canvas.scrollTop) >= this.canvas.scrollHeight) {
if (this.props.data.next !== null) {
let query = {}
let newpage = this.state.page +1
query['page'] = newpage
this.setState({'page':newpage})
this.props.dispatch(fetchData(query)).then(
(res) => {
// make handling
},
(err) => {
// make handleing
}
)
}
}
};
this.canvas = null;
}
componentDidMount() {
this.props.dispatch(fetchData({'page':this.state.page}))
this.canvas = findDOMNode(this).querySelector('.react-grid-Canvas');
this.canvas.addEventListener('scroll', this.scrollListener);
this._mounted = true
}
componentWillUnmount() {
if(this.canvas) {
this.canvas.removeEventListener('scroll', this.scrollListener);
}
}
getRows() {
return this.props.data.rows;
}
getSize() {
return this.getRows().length;
}
rowGetter(rowIndex) {
let rows = this.getRows();
let _row = rows[rowIndex]
return _row
}
render() {
return (
<ReactDataGrid columns={columns}
rowGetter={this.rowGetter}
rowsCount={this.getSize()}
headerRowHeight={40}
minHeight={this.state.height}
rowHeight={40}
/>
)
}
}
Note : Assumed data are taken from redux store

Related

How can I print the table with the checkbox checked using react-data-grid?

When printing a table using react-data-grid
I am trying to make the background color of a specific row be blue and the checkbox to be checked.
code:
if (res) {
// alert("hi")
if (searchModalInit.excelColumnType === "toolProduct") {
setSearchList([...SearchResultSort(!column.noSelect ? [null, ...res] : res, searchModalInit.excelColumnType)])
setPageInfo({ page: res.page, total: res.totalPages });
Notiflix.Loading.remove()
} else
if (res.page !== 1) {
console.log("hihi");
setSearchList([...searchList, ...SearchResultSort(!column.noSelect ? [{ noneSelected: true }, ...custom_info_list] : custom_info_list, searchModalInit.excelColumnType)])
setPageInfo({ page: res.page, total: res.totalPages });
Notiflix.Loading.remove()
} else {
// console.log(custom_info_list)
// console.log("custom_info_list : ", custom_info_list);
console.log("selector.product_ids_for_selected_rows : ", selector.product_ids_for_selected_rows);
console.log("custom_info_list : ", custom_info_list);
let tmp: Set<any> = selectList
const new_rows = custom_info_list.map((row, index) => {
if (selector.product_ids_for_selected_rows.includes(row.product_id)) {
// alert("실행이 되나? : " + row.product_id)
tmp.add(row.product_id)
tmp.add(index)
return {
...row,
border: true
}
} else {
return {
...row
}
}
})
console.log("new_rows ::::", new_rows);
setSearchList([...SearchResultSort(!column.noSelect ? [{ id: null, noneSelected: false }, ...new_rows] : new_rows, searchModalInit.excelColumnType)])
Notiflix.Loading.remove()
}
}
color has been set
checkbox check doesn't work
let tmp: Set<any> = selectList
const new_rows = custom_info_list.map((row, index) => {
if (selector.product_ids_for_selected_rows.includes(row.product_id)) {
// alert("Is it running? : " + row.product_id)
tmp.add(row.product_id)
tmp.add(index)
If you know a way to make the checkbox of each row in the table be checked, please let me know. thank you
Reference:
https://github.com/adazzle/react-data-grid
test:

Rendering a menu in vue 3 after ajax method

I've gotten this menu to work without filtering it, but now I'm doing an ajax request to filter out menu items the user isn't supposed to see, and I'm having some trouble to figure out how to set the resulting menu data, the line that is not working is commented below:
<script>
import { ref } from 'vue';
import axios from 'axios';
var currentSelected = 'device_access';
var menuData = [
{
text: 'Device Access',
id: 'device_access',
children: [
{
text: 'Interactive',
link: '/connection_center'
},{
text: 'Reservation',
link: '/reserve_probe'
}, {
text: 'Reservation Vue',
link: '/reservation.html'
}
]
}, {
text: 'Automation',
id: 'automation',
show: ['is_mxadmin', 'can_schedule_scripts'],
children: [
{
text: 'Builder',
link: '/builder',
},{
text: 'Execution Results',
link: '/test_suite_execution_results'
},
]
}
];
function hasMatch(props, list) {
var match = false;
for (var i=0; i < list.length && !match; i++) {
match = props[list[i]];
}
return match;
}
export default {
name: 'Header',
setup() {
const cursorPosition = ref('0px');
const cursorWidth = ref('0px');
const cursorVisible = ref('visible');
//the menu is zero length until I get the data:
const menu = ref([]);
return {
menu,
cursorPosition,
cursorWidth,
cursorVisible
}
},
created() {
let that = this;
axios.get('navigation_props')
.then(function(res) {
var data = res.data;
var result = [];
menuData.forEach(function(item) {
if (!item.show || hasMatch(data, item.show)) {
var children = [];
item.children.forEach(function (child) {
if (!child.show || hasMatch(data, child.show)) {
children.push({ text: child.text, link: child.link });
}
});
if (children.length > 0) {
result.push({ text: item.text,
children: children, lengthClass: "length_" + children.length });
}
}
});
//continues after comment
this is probably the only thing wrong, I've run this in the debugger and I'm getting the
correct data:
that.$refs.menu = result;
since the menu is not being rebuilt, then this fails:
//this.restoreCursor();
})
.catch(error => {
console.log(error)
// Manage errors if found any
});
},
this.$refs is for template refs, which are not the same as the refs from setup().
And the data fetching in created() should probably be moved to onMounted() in setup(), where the axios.get() callback sets menu.value with the results:
import { onMounted, ref } from 'vue'
export default {
setup() {
const menu = ref([])
onMounted(() => {
axios.get(/*...*/).then(res => {
const results = /* massage res.data */
menu.value = results
})
})
return {
menu
}
}
}
I finally figured out the problem.
This code above will probably work with:
that.menu = result;
You don't need: that.$refs.menu
You can't do it in setup because for some reason "that" is not yet defined.
In my working code I added a new method:
methods: {
setMenuData: function() {
this.menu = filterMenu();
},
}
And "this" is properly defined inside them.

Redux Toolkit - action from one slice to be caught in another slice

There's an action (addOrder) in an orderSlice
orderSlice.js
import { createSlice } from '#reduxjs/toolkit';
const initialState = {
orders: []
};
const ordersSlice = createSlice({
name: 'orders',
initialState,
reducers: {
addOrder: {
reducer: (state, action) => {
state.orders.push(action.payload)
},
prepare: (orderItems, orderTotal) => {
const orderDate = new Date().toDateString();
return { payload: { orderDate, orderItems: orderItems, orderTotal: orderTotal }}
}
}
}
})
export const { addOrder } = ordersSlice.actions;
export default ordersSlice.reducer;
I'd like it to also affect the state in another slice (cartSlice). Once the 'addOrder' is fired, it should also bring the cartReducer to its initial state. Some googling suggested that I should use extrareducers for that but I'm really not getting its syntax. See below (not valid code in extrareducers)
cartSlice
import { createSlice } from '#reduxjs/toolkit';
import { addOrder } from './ordersSlice';
const initialState = {
items: {},
totalAmount: 0
};
const cartSlice = createSlice({
name: 'cart',
initialState: initialState,
reducers: {
addToCart: (state, action) => {
// p = product to be added or amended
const p = action.payload;
if (state.items[p.id]) {
// already exists
state.items[p.id].quantity += 1;
state.items[p.id].sum += p.price;
state.totalAmount += p.price;
} else {
state.items[p.id] = { price: p.price, quantity: 1, title: p.title, sum: p.price};
state.totalAmount += p.price;
}
},
removeFromCart: (state, action) => {
console.log('remove from cart');
console.log(action.payload);
const currentQuantity = state.items[action.payload].quantity;
console.log(currentQuantity);
if (currentQuantity > 1) {
state.items[action.payload].quantity -= 1;
state.items[action.payload].sum -= state.items[action.payload].price;
state.totalAmount -= state.items[action.payload].price;
} else {
state.totalAmount -= state.items[action.payload].price;
delete state.items[action.payload];
}
}
},
extraReducers: (builder) => {
builder
.addCase(addOrder(state) => {
return initialState;
})
}
});
export const { addToCart, removeFromCart } = cartSlice.actions;
export default cartSlice.reducer;
You're almost there! The builder.addCase function takes two arguments. The first is the action creator and the second is the case reducer. So you need a comma after addOrder.
extraReducers: (builder) => {
builder.addCase(addOrder, (state) => {
return initialState;
});
}

How to implement an ag-grid custom floating filter with material-ui withStyles HoC?

Created an ag-grid custom floating filter with validation and need to style the filter when the validation fails with material-ui themed class using withStyles higher order component (HoC). However, when you wrap the custom floating filter with HoC onParentModelChanged doesn't get called at all.
Used hard-coded style to set the element style property but this is not allowed in the themed project using #material-ui/core v1.4.0.
Below is the custom floating filter that I created with validation and hard-coded style.
import { PropTypes } from 'prop-types';
import styles from './styles';
const DEFAULT_MIN_CHARS = 3;
const ENTER_KEY = 13;
export class CustomFloatingFilter extends Component {
constructor(props) {
super(props);
this.state = {
currentValue: '',
minChars: props.minChars ? props.minChars : DEFAULT_MIN_CHARS,
invalidFilter: false,
styles: styles()
};
this.keyPressed = this.keyPressed.bind(this);
this.valueChanged = this.valueChanged.bind(this);
this.onParentModelChanged = this.onParentModelChanged.bind(this);
this.onFloatingFilterChanged = change => {
const { minChars } = this.state;
if(change && change.model && (!change.model.filter || change.model.filter.length >= minChars)) {
return props.onFloatingFilterChanged(change);
}
return false;
};
}
keyPressed(event) {
this.setState(
{ enterPressed: event.which === ENTER_KEY },
() => {
const { enterPressed } = this.state;
if(enterPressed) { //update filter only when enter. valueChanged will handle all other cases
this.onFloatingFilterChanged(this.buildChanged());
}
}
);
}
valueChanged(event) {
const { minChars } = this.state;
this.setState(
{
currentValue: event.target.value,
invalidFilter: !!event.target.value && event.target.value.length < minChars
},
() => {
this.onFloatingFilterChanged(this.buildChanged());
}
);
}
onParentModelChanged(parentModel) {
this.setState({ currentValue: parentModel ? parentModel.filter : '' });
}
buildChanged() {
const { currentValue, enterPressed, invalidFilter } = this.state;
return {
model: {
filterType: 'text',
type: 'equals',
filter: currentValue
},
apply: !invalidFilter && (enterPressed || currentValue === '') //for applyButton:true case
};
}
render() {
const { currentValue, invalidFilter, styles } = this.state;
return (
<div style={invalidFilter ? styles.invalid : {} //eslint-disable-line
//withStyles HoC doesn't work with ag-grid floating filter component
}
>
<input className='ag-floating-filter-input' onKeyPress={this.keyPressed} onChange={this.valueChanged} value={currentValue} />
</div>
);
}
}
CustomFloatingFilter.propTypes = {
minChars: PropTypes.number,
onFloatingFilterChanged: PropTypes.func
};
export default CustomFloatingFilter;

hash format error! using routing

I have developed an OpenUI5 app ant it works fine!
But every time that I invoke the routing I have this message:
2015-07-15 16:15:45 hash format error! The current Hash: /line/01 -
log
error
onHashChange
detectHashChange
jQuery.event.dispatch
jQuery.event.add.elemData.handle
It is not a blocking problem but it is annoying because it dirty and fills thi debug console..!
To call the router I write:
this.router = sap.ui.core.UIComponent.getRouterFor(this);
this.router.navTo("activities", {
"id_line": '01'
});
and this is the routing file:
routes: [
...
{
pattern: "line/{id_line}",
name: "activities",
target: ["master_search", "detail_activities"]
},
...
],
targets: {
master_search: {
viewName: "UniversalMenu",
viewLevel: 1,
controlAggregation: "masterPages"
}
,
detail_activities: {
viewName: "DetailActivity",
viewLevel: 4
}
...
}
Edit: this is a snippet where I use jQuery.sap.history
jQuery.sap.require("jquery.sap.history");
jQuery.sap.require("sap.m.InstanceManager");
sap.ui.controller("ui5bp.view.App", {
getDefaultPage : function () {
return "Menu";
},
onInit : function () {
var historyDefaultHandler = function (navType) {
if (navType === jQuery.sap.history.NavType.Back) {
//this.navBack(this.getDefaultPage());
} else {
this.navTo(this.getDefaultPage(), null, false);
}
};
var historyPageHandler = function (params, navType) {
if (!params || !params.id) {
jQuery.sap.log.error("invalid parameter: " + params);
} else {
if (navType === jQuery.sap.history.NavType.Back) {
this.navBack(params.id);
} else {
this.navTo(params.id, params.data, false);
}
}
};
jQuery.sap.history({
routes: [{
// This handler is executed when you navigate back to the history state on the path "page"
path : "page",
handler : jQuery.proxy(historyPageHandler, this)
}],
// The default handler is executed when you navigate back to the history state with an empty hash
defaultHandler: jQuery.proxy(historyDefaultHandler, this)
});
// subscribe to event bus
var bus = sap.ui.getCore().getEventBus();
bus.subscribe("nav", "to", this.navHandler, this);
bus.subscribe("nav", "back", this.navHandler, this);
bus.subscribe("nav", "virtual", this.navHandler, this);
},
navHandler: function (channelId, eventId, data) {
if (eventId === "to") {
this.navTo(data.id, data.data, true);
} else if (eventId === "back") {
//**************************************************
// if(data && data.id){
// this.navBack(data.id);
// } else {
// jQuery.sap.history.back();
// }
var app = this.getView().app;
if(data.type==="master"){
app.backMaster();
}else if(data.type==="detail"){
app.backDetail();
}else{alert("back to master o detail?");};
//**************************************************
} else if (eventId === "virtual") {
jQuery.sap.history.addVirtualHistory();
} else {
jQuery.sap.log.error("'nav' event cannot be processed. There's no handler registered for event with id: " + eventId);
}
},
navTo : function (id, data, writeHistory) {
if (id === undefined) {
// invalid parameter
jQuery.sap.log.error("navTo failed due to missing id");
} else {
var app = this.getView().app;
// navigate in the app control
app.to(id, "slide", data);
}
},
/*
navBack : function (id) {
if (!id) {
// invalid parameter
jQuery.sap.log.error("navBack - parameters id must be given");
} else {
// close open popovers
if (sap.m.InstanceManager.hasOpenPopover()) {
sap.m.InstanceManager.closeAllPopovers();
}
// close open dialogs
if (sap.m.InstanceManager.hasOpenDialog()) {
sap.m.InstanceManager.closeAllDialogs();
jQuery.sap.log.info("navBack - closed dialog(s)");
}
// ... and navigate back
var app = this.getView().app;
var currentId = (app.getCurrentPage()) ? app.getCurrentPage().getId() : null;
if (currentId !== id) {
app.backToPage(id);
jQuery.sap.log.info("navBack - back to page: " + id);
}
}
}
*/
});
In Component.js I had 2 rows where I set up custom myNavBack and myNavToWithoutHash functions:
// 3a. monkey patch the router
var oRouter = this.getRouter();
oRouter.myNavBack = ui5bp.MyRouter.myNavBack; //to comment
oRouter.myNavToWithoutHash = ui5bp.MyRouter.myNavToWithoutHash; //to comment
I have started from an example of app skeleton for my app and then I have implemented the routing with the logic suggested from the framework.
This coexistence of two different methods to navigate produced the error in console. Tahnkyou #TimGerlach
After the comment of the two rows errors have vanished.