ag-grid React run on every render - ag-grid

I want to re-run
headerComponentFramework: (params) => {
console.log('xxx');
},
every single time the data value changes
<AgGridReact
defaultColDef={defaultColDef}
rowData={data}
columnDefs={columnDefs}
/>

To refresh a header, you can use the Grid API method refreshHeader.
To refresh a header when the data changes, you can listen to the following Grid Events: onCellValueChanged, onRowDataChanged and onRowDataUpdated.
See this implemented in the following plunkr.
const rowDataChanged = (params) => {
console.log('rowDataChanged');
params.api.refreshHeader();
};
const rowDataUpdated = (params) => {
console.log('rowDataUpdated');
params.api.refreshHeader();
};
const cellValueChanged = (params) => {
console.log('cellValueChanged');
params.api.refreshHeader();
};

Related

RTK query with Storybookjs

I am using RTK query with typescript in my react application and its working fine however storybookjs is not able to mock data for RTK query.
I am trying to mock store object as shown in this storybook document.
example -
export const Test = Template.bind({});
Test.decorators = [
(story) => <Mockstore data={myData}>{story()}</Mockstore>,
];
.
.
.
const customBaseQuery = (
args,
{ signal, dispatch, getState },
extraOptions
) => {
return { data: [] }; // <--- NOT SURE ABOUT THIS
};
const Mockstore = ({ myData, children }) => (
<Provider
store={configureStore({
reducer: {
[myApi.reducerPath]: createApi({
reducerPath: 'myApi',
baseQuery: customBaseQuery,
endpoints: (builder) => ({
getMyData: myData, //<-- my mock data
}),
}).reducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(myApi.middleware),
})}
>
{children}
</Provider>
);
Since RTK query hook is autogenerated, I am not sure how to mock it in storybookjs. Instead of getting mock data storybook if trying to fetch actual data.
Please help me.
You'd do
endpoints: (builder) => ({
getMyData: builder.query({
queryFn: () => { data: myData }, //<-- my mock data
})
}),
alternatively you could leave the store setup just as it is and use msw to mock the real api.

When using <AsyncTypeahead/> I can't use onSearch and onInputChange at the same time

So as I said in the title, I can't use onSearch and onInputChange at the same time. If I try to, onSearch gets ignored. Can you tell me why or is there an alternative to onInputChange? Im using AsyncTypeahead in a Form, so I need the values when I click a button.
const [from, setFrom] = useState('');
const onSearchStart = (query) => {
setTypeAhead({
...typeAhead,
startIsLoading: true
})
setFrom(query)
getStations(query).then(r => {
setTypeAhead({
...typeAhead,
startIsLoading: false,
startOptions: r || []
})
})
}
return(
<AsyncTypeahead
id={"from"}
isLoading={typeAhead.startIsLoading}
options={typeAhead.startOptions}
onInputChange={setFrom}
onSearch={onSearchStart}
/>
)
This isn't the whole code, but it shows everything that is causing the error
As a workaround you can use useRef to not trigger the re-render. Here is the code:
const fromRef = useRef('');
const onSearchStart = (query) => {
...
}
return(
<AsyncTypeahead
...
onInputChange={(text) => {
fromRef.current = text;
}}
onSearch={onSearchStart}
/>
)

Redux toolkit slice. Pure functions inside field reducers

Sup ya. Just wanna specify can we use it? I think we can just wanna be sure 100%
https://codesandbox.io/s/redux-toolkit-state-new-array-4sswi?file=/src/redux/slices/slice.js:111-425
const someSlice = createSlice({
name: "someSlice",
initialState: {
users: [],
status: ""
},
reducers: {
actionSuccess: (state, { payload }) => {
state.users = payload.users;
},
actionFailure: (state) => {
// can we use here function?
statusHandler(state)
}
}
});
A reducer should not trigger any side effects. That is, it should not do anything other than change the contents of the state. So you should not call a statusHandler which would trigger external effects.
If your statusHandler function does nothing but update the state, that does seem to work in my testing and I'm not aware of any reason why it shouldn't be okay.
Redux Toolkit uses Immer behind the scenes to deal with immutable updates, so this question basically boils down to whether these two functions, updatedInline and updatedExternally, are equivalent. They are, as far as I can tell.
const {produce} = immer;
const initialState = {
status: ''
};
const updatedInline = produce( initialState, draft => {
draft.status = 'failed';
})
const mutateStatus = (state) => {
state.status = 'failed';
}
const updatedExternally = produce( initialState, mutateStatus )
console.log("Updated Inline: \n", updatedInline);
console.log("Updated Externally: \n", updatedExternally);
<script src="https://cdn.jsdelivr.net/npm/immer#8.0.1/dist/immer.umd.production.min.js"></script>

ReactDataGrid row selection does not work

I am trying to build data table using react and react-data-grid version "^7.0.0-canary.16",
The render method looks like this:
render() {
return (
<div className={"component"}>
<ReactDataGrid width={600} height={400}
rowKey="id"
columns={this.state.columns}
rows={this.state.rows}
onRowClick={this.onRowClick}
rowSelection={{
showCheckbox: true,
enableShiftSelect: true,
onRowsSelected: this.onRowsSelected,
onRowsDeselected: this.onRowsDeselected,
selectBy: {
indexes: this.state.selectedIndexes
}
}}
/>
</div>
)
}
So following the documentation on page https://adazzle.github.io/react-data-grid/docs/examples/row-selection
it should display checkbox in first column and when I select the checkbox it should call method this.onRowsSelected.
Alas, no checkbox is shown and no matter how I click the this.onRowsSelected method is never called.
On the other hand the method this.onRowClick is called, whenever I click somewhere in the table.
Does anyone have experience with this?
It seems to be showing the checkboxes with "react-data-grid": "6.1.0"
Although, I'm having issue with the checkboxes when we filter the data. The rowIdx changes and we lose context of that was previously selected. We want to make BE calls on selected Data. I tried changing it to use the row.id but no luck. It messes up the selection.
Here is a hook for managing the selection
import {useState} from 'react';
export const useRowSelection = () => {
const [selectedIndexes, setSelectedIndexes] = useState([]);
const onRowsSelected = rows => {
setSelectedIndexes(prevState => {
return prevState.concat(rows.map(r => r.rowIdx));
});
};
const onRowsDeselected = rows => {
let rowIndexes = rows.map(r => r.rowIdx);
setSelectedIndexes(prevState => {
return prevState.filter(i => rowIndexes.indexOf(i) === -1);
});
};
return {
selectedIndexes,
onRowsDeselected,
onRowsSelected,
};
};
Pass them to the RDG
const {selectedIndexes, onRowsDeselected, onRowsSelected} = useRowSelection();
const rowSelectionProps = enableRowSelection
? {
showCheckbox: true,
enableShiftSelect: true,
onRowsSelected: onRowsSelected,
onRowsDeselected: onRowsDeselected,
selectBy: {
indexes: selectedIndexes,
},
}
: undefined;
<ReactDataGrid
columns={columnDefinition}
getValidFilterValues={getFilterValues}
rowGetter={i => filteredData[i]}
rowsCount={filteredData.length}
onAddFilter={filter => handleOnAddFilter(filter)}
onClearFilters={() => handleOnCleanFilters()}
toolbar={toolbar}
contextMenu={contextMenu}
RowsContainer={ContextMenuTrigger}
rowSelection={rowSelectionProps}
rowKey="id"
/>

Telerik MVC Grid not sorting when reloaded

My Telerik MVC grid is Ajax bound and I need to ability to apply custom filtering via two checkboxes (in the DIV at the top). When a checkbox is checked, the parameters would be set and the grid is reloaded. This is working fine. During the initial load the data is sorted based on the sorting settings in Telerik, but after I click a checkbox, the data is ordered by record Id and no longer by Priority. If I then hit F5 the page is reloaded and the data is sorted correct. The sorting might be a parameter for grid.rebind() or provided in OnDataBinding, but so far I have not found what I am looking for.
QUESTION: How do I specify the sorting order in the OnDataBinding or perhaps in another client event.
Here is my code:
<div style="float:right;width:600px;text-align:right">
<span>My Items <%=Html.CheckBox("newItems") %></span>
<span>Closed Items <%=Html.CheckBox("Inactive") %></span>
</div>
<% Html.Telerik().Grid<IssueModel>()
.Name("Grid")
.PrefixUrlParameters(false)
.Columns(col =>
{
col.Bound(o => o.Title);
col.Bound(o => o.Priority).Width(50).Title("Priority ID");
col.Bound(o => o.PriorityName).Width(100).Title("Priority");
col.Bound(o => o.IssueStateName).Width(100).Title("Status");
col.Bound(o => o.AssignedToName).Width(140).Title("Assigned To");
})
.DataBinding(d => d.Ajax().Select("AjaxSelect", "Ticket", new { isNew = false, isInactive = false }))
.ClientEvents(e => e.OnDataBinding("onDataBinding"))
.Sortable(s => s
.SortMode(GridSortMode.MultipleColumn)
.OrderBy(order =>
{
order.Add(o => o.Priority);
order.Add(o => o.Sequence);
})
)
.Pageable(p => p.PageSize(15))
.Filterable()
.Render();
%>
<script type="text/javascript">
function onDataBinding(e) {
e.data = {
isNew: $("#newItems").is(':checked'),
isInactive: $("#Inactive").is(':checked')
};
e.orderBy = "Severity~desc~Ranking~asc";
}
$("input[type='checkbox']").click(function () {
var grid = $('#Grid').data('tGrid');
var param = {
isNew: $("#newItems").is(':checked'),
isInactive: $("#Inactive").is(':checked')
};
grid.rebind(param);
});
</script>
I found the solution in case others need the answer. I used grid.sort() in place of grid.rebind(); The sort method takes a string in the format: column-name dash direction. Example First
<script type="text/javascript">
function onDataBinding(e) {
e.data = {
isNew: $("#newItems").is(':checked'),
isInactive: $("#Inactive").is(':checked')
};
}
$("input[type='checkbox']").click(function () {
var grid = $('#Grid').data('tGrid');
var param = {
isNew: $("#newItems").is(':checked'),
isInactive: $("#Inactive").is(':checked')
};
grid.sort("Severity-desc~Ranking-asc";);
//grid.rebind(param);
});
</script>