React toggle hyperlink of grid header - reactjs

I am working with react with Web API. I need one solution where I wanted to have one Hyperlink for once of the headers of Grid. And once I click's over the hyperlink, I wanted to hide this hyperlink and show other hyperlink (toggle). For Ex-
Those Hyperlinks are not directing anywhere. These are in use to select all Radiobuttons and another Hyperlink is used for unselecting all the Radiobuttons for Grid rows.

It's easy to toggle. But it's a hyperlink, which makes it a little tricky. Does the hyperlink links to anywhere?
Anyway, you can toggle the href in onClick, in order for 'href' take effect before 'href' itself is changed, use setTimeout (10 milliseconds should be enough):
import React from 'react'
const ToggleLinks = () => {
const google = {href:"https://google.ca", text:"google"};
const yahoo = {href:"https://yahoo.ca", text:"yahoo"};
const [link, setLink] = React.useState(google);
const toggleLink = e => {
console.log('clicked')
console.log(e.target)
setTimeout(() => {
setLink(p => {
return p.href === "https://google.ca" ? yahoo : google;
})
}, 10);
}
return (
<div>
<h1>ToggleLinks</h1>
{link.text}
</div>
)
}
export default ToggleLinks

Related

Link not opening in React admin's list - makes edit instead

I have a Resource of campaigns; id field of each campaign linked to a standalone page of URLs, belonging to that campaign. (I still don't know how I'll do it).
I use custom field
import { useRecordContext, useGetOne } from 'react-admin';
import { Link } from 'react-router-dom';
export default () => {
const campaign = useRecordContext();
const { data, isLoading } = useGetOne('campaign', { id: campaign.campaign_id });
const campaignUrlsPage = `/campaign/${campaign.id}/urls/`;
return /*isLoading ? null : */ <Link to={campaignUrlsPage}>{campaign.id}</Link>;
};
Why I commented out isLoading? Strange thing but it's always true, after all I don't notice any artefact that way.
Links are shown in the corresponding ceils, thay are actually ancor tags, but clicking them causes record edit. Yes, I have rowClick="edit" and I really need it.
Additionally, I have UrlField in the grid, and clicking it first shows record edit page but next it directs to the URL.
Can it be fixed?
Thanks in advance.
To support rowClick="edit", each datagrid row has a click handler.
If you put your button in a datagrid, when users click on the button, the click even propagates down to the datagrid row, and the row click event handler fires.
So you must stop event propagation in your link:
export default () => {
const campaign = useRecordContext();
const { data, isLoading } = useGetOne('campaign', { id: campaign.campaign_id });
const campaignUrlsPage = `/campaign/${campaign.id}/urls/`;
return isLoading ? null : (
<Link
to={campaignUrlsPage}
onClick={e => e.stopPropagation()}
>
{campaign.id}
</Link>
);
};

How to handle onClick event to display text after the click

Using react typescript and I’m confused that when I click a button I want some text to appear below the button or at-least anywhere so I made a function to handle the onClick from the button and returned a h1 from the function but turns out no h1 appears on screen after button click. Any idea why?
const handleOnClick=(id:any)=>{
console.log("button clicked" + id)
return(
<h1>Clicked it</h1>
);
}
My Function is this and in another function I have
<button onClick={()=>{handleOnClick(someId)}}>a</button>
I can see the console log but the h1 doesn’t work. Any ideas?
If you think about it, what your handleOnClick doing is returning a bunch of jsx, where do you think these jsx will appear since we didn't specify any location for them? Now if you try something like this:
<button>{ handleOnClick('someId') }</button>
You will see the h1 on the screen because you specify that's where you want to render it, right inside the button element.
A classic way in js to render out something on button click is like this:
const handleOnClick=(e)=>{
// create the element
const newEle = document.createElement('h1');
newEle.innerText = 'Hello';
// append it inside the button
e.target.appendChild(newEle);
}
export default function App() {
const [nameId, setNameId] = useState<String>("");
const handleClick = (id: String) => () => {
console.log("button clicked: ", id);
setNameId(nameId ? "" : id);
};
return (
<>
<button onClick={handleClick("Rohan")}>
{nameId ? "Hide" : "Greet"}
</button>
{!!nameId && <h1>Hello {nameId} Haldiya</h1>}
</>
);
}
When the click is triggered, you need to add the <h1> element into your JSX code, and returning it from the click handler is not enough because you need to tell it where is should be added.
A good way of doing that in React is by using a state which tells you if the button was clicked or not, and if it was, then you display the <h1> element onto the screen. See the code below:
const [isActive, setIsActive] = useState(false);
const handleOnClick = (id) => {
console.log("button clicked" + id);
setIsActive(true);
};
and in your JSX code, below the button, you just need to add the second line of the following:
<button onClick={()=>{handleOnClick(someId)}}>a</button>
{isActive && <h1>Button was clicked.</h1>}
And if you want to toggle the click, So the first time you click the <h1> is showing , but if you click again it disappears, then you could simply do this in the handleOnClick function instead of the above:
const handleOnClick = (id) => {
console.log("button clicked" + id);
setIsActive((prevState) => (prevState === false ? true : false));
};
Hope this helps!

React (Next.js) hook useOutsideClick cancels my links

i'm using the following hook to handle "click away" feature to show/hide a dropdown:
const useOutsideClick = (ref: NonNullable<RefObject<HTMLButtonElement>>) => {
const [outsideClick, setOutsideClick] = useState<boolean | null>(null)
useEffect(() => {
const handleClickOutside = (e: React.MouseEvent | Event) => {
if (
ref &&
!(ref?.current as unknown as RequiredCurrentRef).contains(
e?.target as Node
)
) {
setOutsideClick(true)
} else {
setOutsideClick(false)
}
setOutsideClick(null)
}
document.addEventListener('mousedown', handleClickOutside)
return () => {
document.removeEventListener('mousedown', handleClickOutside)
}
}, [ref])
return outsideClick
}
export default useOutsideClick
the hook works fine but once i click on <a href> links (separated component from the dropdown) it does not redirect, so links don't work
how do i solve this?
Edit i'm using bulma.css for dropdowns
I think you dont need to create an extra hook at all.
If you want do du something if the user clicks on or out of the element you can use the onBlur and onFocus callbacks.
If you want to blur it for some other reason (like on the click of a button) you can use the reference of the anchor and call the blur() method whenever you like.

How to trigger a cell change from within a component to update the grid data? (AG Grid - React)

I have a dropdown component within an Ag Grid. But when I change the value, the client-side data object doesn't change.
I'm triggering a function within the component when the dropdown is changed - but how can I tell the "parent" AG Grid to update it's data for that cell? (AG Grid automatically updates it's data when you're just changing text directly in a cell, not using a custom component.)
It seems to have something to do with using getValue(), but I can't seem to find the proper call in the documentation.
Are you using a Cell Renderer or Cell Editor to build the dropdown component?
If using a Custom Cell Editor, you must implement the getValue method otherwise the grid will not insert the new value into the row after editing is done.
See this implemented here:
const CustomCellEditor = forwardRef((props, ref) => {
const [selectedValue, setSelectedValue] = useState('United States');
const values = ['United States', 'Russia', 'Canada'];
/* Component Editor Lifecycle methods */
useImperativeHandle(ref, () => {
return {
getValue() {
return selectedValue;
},
};
});
const onChangeHandler = (event) => {
setSelectedValue(event.target.value);
};
return (
<div>
<select value={selectedValue} onChange={onChangeHandler}>
{values.map((item) => (
<option>{item}</option>
))}
</select>
</div>
);
});
Plunkr example
Documentation on Custom Cell Editors

React Toggle Functionality

Current Project Image
I have a Content component that renders 2 Panel components. The Content component passes its state to panel 1 and passes !state to panel 2. (Panel 1 is initially visible and panel 2 is not)
Desired Functionality:
When the user clicks the "hidden" component, it sets it to visible and hides the visible one.
If the user clicks the now visible component, nothing happens but if the now hidden component is clicked, it should become visible and the visible one goes back to being hidden.
Content.jsx
import React, { useState } from "react";
import Panel from "../panel/Panel";
import "./content.styles.css";
const Content = ({ selected, panelA, panelB }) => {
const [active, setActive] = useState(true);
return (
<div className={`content-wrapper ${selected ? "visible" : "hidden"}`}>
<Panel active={active} panelText={panelA} setActive={setActive} />
<Panel active={!active} panelText={panelB} setActive={setActive} />
</div>
);
};
export default Content;
Panel.jsx
import React from "react";
import "./panel.styles.css";
const Panel = ({ panelText, active, setActive }) => {
const handleClick = () => {
if(!active){
setActive(false);
}
};
return (
<div
onClick={handleClick}
className={`panel-wrapper ${
active ? "active-component" : "hidden-component"
}`}
>
{panelText}
</div>
);
};
export default Panel;
I really hope I'm just missing something or I'm not understanding how React is working under the hood. I really appreciate any help or advice you could give me to get me going down the right path.
Thank you so much!
If I understood your question correctly, this codesandbox that I created should help.
Issues
You are almost there, but you have a couple of issues here:
Using only one state variable for both child components.
Since you are setting active to true and false, and passing the same state variable to both panels, panels will affect each other.
Setting active to false if panel isn't active
const handleClick = () => {
if(!active){
setActive(false); // If the panel is not active, no reason to setActive(false)
}
};
Solution
You need to have separate identifiers for panels, that is why I used an array to keep track of active panels (if you have only two a string will also be fine)
const [activePanels, setActivePanels] = useState([/* initial active panels */])
You can add and remove to this array based on your panel's condition:
const handleClick = () => {
if (!active) setActivePanels([panelText]);
};

Resources