How to render custom header in react-virtualized Table - react-virtualized

In docs - headerRowRenderer, but can anyone share simple example with some custom header markup, for example with custom title attr + all 'default' virtualized features, like sortable...

Your question mentions headerRowRenderer but I think you might actually be asking about how to render a custom header cell based on the rest of your statement. Anyway, I'll show both.
// This is a custom header row rendered
// You should used all of the specified params,
// But you can also add your own decorated behavior.
const headerRowRenderer = ({
className,
columns,
style
}) => (
<div
className={className}
role='row'
style={style}
>
{columns}
</div>
)
// This is a custom header example for a single cell
// You have access to all of the named params,
// But you don't necessarily need to use them all.
const headerRenderer = ({
columnData,
dataKey,
disableSort,
label,
sortBy,
sortDirection
}) => (
<div>#</div>
)
const renderTable = (props) => (
<Table
{...props}
headerRowRenderer={headerRowRenderer}
>
<Column
dataKey='number'
headerRenderer={headerRenderer}
width={100}
/>
<Column
dataKey='name'
label='Name'
width={200}
/>
</Table>
)
Here's a Plnkr example for you: https://plnkr.co/edit/eHr3Jr?p=preview

To render a custom header, you can use React-Virtualized's Column component by passing headerRenderer prop to it.
headerRenderer is a callback responsible for rendering a cell's header column.
Here is an example showing implementation:
Method to create a custom header by returning JSX; to be declared above the render method.
You can return JSX, according to your requirements. In this example we return a paragraph (p tag).
formatCheckboxHeader = () => {
return (
<p>Custom Header</p>
)
}
In the render method, where the react-virtualized table is initialized.
<Column
width={100}
headerRenderer={this.formatCheckboxHeader}
label='#'
dataKey='id'
cellRenderer={({ rowData }) => this.formatIdColumn(rowData)}
/>
Additionally, you can pass rowData to the headerRenderer as done in the cellRenderer
Read more about headerRenderer here.

Related

How to update Svelte writable store values with input tag

I have a writable store in Svelte with an object. I'd like to display the properties and be able to change the property values as a user.
I'm able to get the properties and values to display in input tags with an on:input event to update the value in the store, but I get an error saying the sampleStore.set isn't a function. I tried to add a custom update function to the store, but I'm getting the same error.
What's the best way to do this?
Sample code below
Store.js
import { writable } from 'svelte/store';
function createSampleStore() {
const sampleStore = writable({
property1a: 'value1a',
property1b: 'value1b',
etc...
}
return {
subscribe: sampleStore.subscribe,
updateValue: (propertyName, propertyValue) =>
sampleStore.update((o) => {
o[propertyName] = propertyValue;
return o;
}),
};
}
export const sampleStore = createSampleStore();
InfoDisplay.svelte
<script>
import {sampleStore} from './sampleStore.js';
const propertyNames = Object.keys($sampleStore);
$: console.log($sampleStore);
</script>
<ul>
{#each propertyNames as propertyName}
<li>
{propertyName}:
<input
on:input={(value) =>
sampleStore.updateValue(propertyName, propertyValue)}
bind:value={$sampleStore[propertyName]}
/>
</li>
{/each}
</ul>
I tried to adjust the values shown in the input tag and have the values in the store be updated, but I kept getting the .set is not a function.
The binding on the input value creates a get/set relationship, you should only pass the value in and use the event to get it out:
<input
on:input={e => sampleStore.updateValue(propertyName, e.target.value)}
value={$sampleStore[propertyName]} /> <!-- no bind here -->
You also do not need a custom store to do this and could just use a writable directly:
<input bind:value={$store[propertyName]} />
REPL

Using Material UI's Autocomplete with Formik Field to display different value with formik state

I am trying to use Material UI's Autocomplete with Formik Field custom component. Here is a custom Autocomplete component I wrote to use with Formik Field.
import { getIn } from 'formik';
import { Autocomplete, TextField } from '#mui/material';
export const CustomAutocomplete = ({
field,
form,
textFieldProps,
...props
}) => {
const errorText =
getIn(form.touched, field.name) && getIn(form.errors, field.name);
return (
<Autocomplete
{...props}
{...field}
onChange={(_, value) => form.setFieldValue(field.name, value)}
onBlur={() => form.setTouched({ [field.name]: true })}
renderInput={(props) => (
<TextField
{...props}
{...textFieldProps}
helperText={errorText}
error={errorText}
/>
)}
/>
);
};
Here is how components called
<Field
options={users}
label='Receiver'
name='receiver'
component={CustomAutocomplete}
textFieldProps={{
fullWidth: true,
margin: 'normal',
variant: 'outlined',
}}
/>
Now what I intend to do is: If I have an object like:
users=[{_id:"62b73809c2ca370bcbb0715b",name:"James"},{_id:"62b739c8c2ca370bcbb07186",name:"David"},
{_id:"62b739c8c2ca3738dbb07101",name:"Steven"}]
I want the Autocomplete dropdown to show options James, David and Steven. But I want the Formik state to save _id respectively once selected from the dropdown because I need to send that _id back to the backend. Currently, the entire object gets saved.
How can this be done?

Passing useState value through parent component using react hooks (getting = undefined)

I'm working in a project already began that's using react class version. I plan to work with react hooks, so to don't refactor all the classes, as I write new codes, I'm trying to mix those react versions (idk if it's a good idea and I should refactor all).
I'm creating a list with pagination and search. The pagination and search are in an unique component.
To this component a need pass the search character value input by user, and here is where I'm facing problem. In other words, I need pass a value to the parent component.
Code is below:
useState hook:
const [search, setSearch] = useState('');
Filter component, that change the search value:
const Filter = () => {
return (
<Card>
<Form.Group label="Filtro">
<Grid.Row gutters="xs">
<Grid.Col>
<Form.Input
name='search'
placeholder='Filtro'
autoFocus
value={search}
onChange={e => setSearch(e.target.value)}
/>
</Grid.Col>
<Grid.Col auto>
<Button
color="success"
icon="search"
onClick={filtrar}
>
</Button>
</Grid.Col>
</Grid.Row>
</Form.Group>
</Card>
);
}
function getSearchDB() {
setSearch((search) => {
return search;
})
}
Pagination component, that receive the props:
<Pagination
baseUrl={'vehicles/toUse'}
updateState={setStateDB}
getSearch={getSearchDB}
fields={'license_plate'}
/>
Printing search value pass through Pagination component:
console.log(this.props.getSearch()) //print undefined
OBS: updateState={setStateDB} is working fine.
Things done to make this work (no success):
In getSearch={getSearchDB} directly pass search value. Result: this.props.getSearch() print undefined
Defined getSearchDB() to be like:
function getSearchDB() {
return search;
}
Result: this.props.getSearch() print undefined.
Is there a way to put it to work?
Guys, let me know if the post is confusion or the English is poorly written.
Instead of passing down a function that returns search, why not just pass down search itself as a prop?
<Pagination
search={search}
const Pagination = (props) => {
console.log(props.search);
add :
<Pagination
search={search}
/>
In component Pagination :
const Pagination = ({search}) => {
console.log(search);
return {
//...
}
}

Styled Components - why does prop position affect styling?

I'm using styled-components to style a parent and child element in a component:
function StyledDemo({
name,
light,
...props
}) {
return (
<Parent {...props}>
<Child>{name}</Child>
</Parent>
);
}
I have a light prop which is true/false - but I'm having an issue with styling the elements based on the value of that property:
const Parent = styled.div`
background-color: #000;
width: 100%;
${props => props.light && `
background-color: #ccc;
`}
`;
The styling only seems to work when I remove the prop being passed into the function individually.
Parent element uses correct styling based on light prop value when:
function StyledDemo({ name, ...props })
Parent element does NOT use correct styling based on light prop value when:
function StyledDemo({ name, light, ...props })
I can get it all working by setting the prop on the Parent and Child component, but this doesn't seem like it's the best way:
return (
<Parent {...props} light={light}>
<Child light={light}>{name}</Child>
</Parent>
);
Is this the correct way to apply styles to components based on props, or is there an issue with my approach?
I have a demo to tinker with if it helps:
https://www.webpackbin.com/bins/-Kfcsujw99cjU7ttqgTz
This is not related to styled-components but to the rest parameter.
When you do the rest operator, any property you "pick" out by name won't be contained in the ...rest variable. So when you do
const Button = ({ light, ...rest }) => ()
<Button light primary />
rest will only contain the primary property, but not light, that's now it's own variable.
If you did
const Button = ({ ...rest }) => ()
<Button light primary />
instead rest would also contain light.
So in your example, you're picking out light from ...props, so when you pass {...props} on to the parent it doesn't contain light anymore, so styled-components doesn't know it exists! Either you go with your first version, or you have to manually apply it to each component.
See MDN for more information about the rest parameter!

Does react-virtualized work with airbnb/enzyme?

Is it possible to use react-virtualized and enzyme together? When I try to use them together I seem to get an empty list of items in the grid.
The 2 should work together, yes. I believe the likely problem is that the react-virtualized component is being given a width or height of 0 which causes it not to render anything. (It only renders enough to fill the "window" it has.)
Assuming you're using the AutoSizer HOC- (most people do)- then one pattern I've found helpful is to export 2 versions of components- one that expects explicit width/height properties and one that wraps the other with an AutoSizer. Pseudo code would be:
import { AutoSizer, VirtualScroll } from 'react-virtualized'
// Use this component for testing purposes so you can explicitly set width/height
export function MyComponent ({
height,
width,
...otherProps
}) {
return (
<VirtualScroll
height={height}
width={width}
{...otherProps}
/>
)
}
// Use this component in your browser where auto-sizing behavior is desired
export default function MyAutoSizedComponent (props) {
return (
<AutoSizer>
({ height, width }) => (
<MyComponent
height={height}
width={width}
{...props}
/>
)
</AutoSizer>
)
}
as of react-virtualized 9.12.0 the Autosizer has defaultWidth and defaultHeight properties.
I found setting those meant enzyme tests ran correctly - rendering the child rows as expected.
<AutoSizer disableHeight defaultWidth={100}>
{({ width }) => (
....
)}
</AutoSizer>
Putting this in my test case worked for me:
import { AutoSizer } from 'react-virtualized';
// ...
it('should do something', function() {
spyOn(AutoSizer.prototype, 'render').and.callFake(function render() {
return (
<div ref={this._setRef}>
{this.props.children({ width: 200, height: 100 })}
</div>
);
});
// do something...
I use Jasmine's spyOn here, but other libraries have their own ways of overwriting functions.
Keep in mind that this is pretty fragile against future changes to the react-virtualized library (this._setRef was just yanked from the source code), and may give you false positives.

Resources