React To Print not triggered when custom button is clicked - reactjs

I have the following code to use React To print, a library to print a component:
<ReactToPrint
trigger={() =>
<SqIconButton action={(e)=>e} color={"success"}>
<AiIcons.AiFillPrinter style={{color: 'black',fontSize:'1rem'}}/>
</SqIconButton>
}
content={() => componentRef.current}
/>
And my custom Button SqIconButton reads as follows:
export default function SqIconButton({children,color="primary",fontColor="#000000",action,tip="",disableElevation=false,sxstyle={},classes}){
return(
<Tooltip title={tip}>
<Button
color={color}
variant="contained"
onClick={action}
disableRipple={disableElevation}
className={`TBButton ${classes}`}
sx={sxstyle}
>
{children}
</Button>
</Tooltip>
)
}
In the examples of React To Print code for its trigger nothing is referencing "onclick" property on buttons, examples mostly look like this: <button>print this</button> and if I use this element it actually works. But my custom button does not work as is, so I think I have to pass the onclick event over my action custom property, so I'm trying with action={(e)=>e}, but the button does nothing when I press it.
Documentation says about trigger:
A function that returns a React Component or Element. Note: under the hood, we inject a custom onClick prop into the returned Component/Element. As such, do not provide an onClick prop to the root node returned by trigger, as it will be overwritten
So I don't know if onclick will be overwritten how could I pass this event to a child button component.

Related

React onClick custom function

I want to have a function that can return a button with onClick equal to some custom function you can pass in. Here's what I have so far. When I click on it, nothing happens. Here is the code that for the button
function Button({text,bgcolor,func}){
return <button onClick={func} style={{backgroundColor:bgcolor, color:"white"}}>{text}</button>
}
and here's the code I'm using to make it
<Button text="alert" bgcolor="red" value="()=>alert('test')" />
You're passing a string, not a function. Also, the prop value doesn't equal to the prop func, expected by Button. Just write:
<Button text="alert" bgcolor="red" func={()=>alert('test')} />

How to use override Button using Box component in Material-UI?

I've been trying to understand and write code on the Box component in material-UI. (https://material-ui.com/components/box/#box)
I've been trying to override a Button component the two ways it describes in the documentation, but I have no idea how. When I run the code segment using both methods, the button appears but no color change. Then when I try to add an extra Button underneath the clone element code segment I get an error saying 'Cannot read property 'className' of undefined'.
<Box color="primary" clone>
<Button>Click</Button>
<Button>Click</Button>
</Box>
When I add a Button component underneath in the second render props way, the first button just disappears from the DOM completely.
<Box color="secondary">
{props => <Button {...props} > Click </Button>}
<Button color="secondary">Click</Button>
</Box>
Would appreciate an explanation of how overriding underlying DOM elements work.
There are a few issues with the code you've shown in your question.
primary and secondary are not valid colors within the palette. They are valid options for the color prop of Button, but here you are trying to reference colors within the theme's palette object. For this purpose, you need primary.main and secondary.main (which is what Button uses when you specify <Button color="primary">).
Box only supports a single child when using the clone property and it only supports a single child when using the render props approach. In both of your examples you have two children.
Here is the Material-UI source code that deals with the clone option:
if (clone) {
return React.cloneElement(children, {
className: clsx(children.props.className, className),
...spread,
});
}
This is creating a new child element that combines the className generated by Box with any existing class name on the child. It gets at this existing class name via children.props.className, but when there are multiple children then children will be an array of elements and will not have a props property so you get the error:
Cannot read property 'className' of undefined
Here is the Material-UI source code that deals with the render props approach:
if (typeof children === 'function') {
return children({ className, ...spread });
}
When you have more than one child, then typeof children === 'function' will not be true and it won't use the render props approach. In this case, both children just get normal react rendering and trying to render a function doesn't render anything.
Below is a working example that fixes all of these problems by using a single Button child in the clone case and a single function child in the render props case (a function that then renders two Button elements).
import React from "react";
import Button from "#material-ui/core/Button";
import Box from "#material-ui/core/Box";
export default function App() {
return (
<>
<Box color="primary.main" clone>
<Button>Click</Button>
</Box>
<Box color="secondary.main">
{props => (
<>
<Button {...props}> Click </Button>
<Button color="secondary">Click</Button>
</>
)}
</Box>
</>
);
}

Pass Accessibility Props to Material UI Button

I want to add accessibility features to the Material UI Button.
I expect to use this custom button as follows:
import Button from '#material-ui/core/Button';
function AccessibleButton(props) {
const { accessKey, ariaLabel, isDisabled, label, onClick, tabIndex, variant, size} = props;
return (
<Button
accesskey={accessKey}
aria-label={ariaLabel}
disabled={isDisabled}
className={componentCls}
onClick={onClick}
tabindex={tabIndex}
variant={variant}
size={size}
>
{label}
</Button>
);
};
Aria labels are available for inputs, but don't seem to be for buttons. How do I pass the additional props (accessKey, ariaLabel) into the Material UI Button. How do I do this?
This should work since most of our components forward their excess props. On the corresponding api pages (here https://material-ui.com/api/button/) you will find a table with the apparent props. Below that is a note that tells you what happens with excess props.
It's a bit iffy to navigate (we're working on it) but in the end you'll see that excess props are forwarded to the native element. So <Button aria-label="ariaLabel" /> will render a <button aria-label="ariaLabel" />.
Your code should work.
I have created sandbox where you can inspect the button and see the button will have aria-label and accesskey attribute.
<Button
aria-label="This is aria label"
accessKey="Key"
variant="contained"
color="primary"
>
I'm a button
</Button>
Try inspecting button in below sandbox.

material UI CardHeader action drop-down

I am trying to add a FormControl, a Select component and a MenuItem to the action prop of the CardHeader IconButton.
Currently the code looks like this:
Rendering:
<CardHeader
action={
<IconButton
onClick={this.renderFilterRequest()}
>
<Edit />
</IconButton>
}
/>
onClick method:
renderFilterRequest() {
const { selection } = this.state;
return (
<div>
<FormControl>
<Select
value={selection}
onChange={this.handleFilterChange}
>
<MenuItem value='1'>January</MenuItem>
<MenuItem value='2'>February</MenuItem>
</Select>
</FormControl>
</div>
);
}
The error I get is onClick listener to be a function, instead got a value of object type. What is the right way to render the dropdown menu on CardHeader action click?
You are returning some div from from this.renderFilterRequest, And you are also calling the function, so the value of onClick becomes the div. But they were meant to be functions, right?
So it should have been just: onClick={this.renderFilterRequest}.
This function also returned a div but there is no way to attach it to rendering logic in render.
You need to put the MenuItems in your render method and show/hide them depending on the state.
Your onClick listener should be a function that changes the state so that the MenuItems become visible.
Here is a simple demo how this should be done:

Can I pass the selected tab back from onTouchTap event of Material-UI Tabs component?

I'm using the Material-UI Tabs component in my ReactJS app.
I'm handling the onTouchTap event of the Tabs component. I'd like to pass the currently selected tab back as a parameter to the event handler.
Is this possible?
So something like this
<Tabs onChange={props.onChangePosition}
onTouchTap={e => {/* What */}>
I know that the onChange handler returns it, but I'd like to use onTouchTap in this instance.
Yes, this can be done. You need to capture a "ref" to your Tabs control, and then call getSelectedIndex() on it, inside your onTouchTap. getSelectedIndex is somewhat internal, so it has an unexpected method signature in that you must also pass it in its own props.
<Tabs
ref={ref => (this.tabs = ref)}
onTouchTap={(e) => console.log(this.tabs.getSelectedIndex(this.tabs.props))}
>
...

Resources