I am trying to change and wrap another component "Modal" to my conversations panel.
My last component's name was SlidingPanel which had a different functionality. I am trying to pass my onClickOutside, open and or onCloseClick prop to the modal so that when clicking the close button or clicking outside the modal, the modal closes and opens again. Somehow I pass the props and they are not working.
I have a ChatModuleContainer which returns my ChatModule component:
const onOpenChat = () => {
if (props.onOpenChatModal) props.onOpenChatModal();
};
return (
<ChatModule
fetching={!ready}
notifications={notifications}
unreadMessages={unreadMessages}
panelTitle={panelTitle}
panelTitleIcon={MODAL_TITLE_ICON}
emptyMessage={emptyMessage}
top={panelTop}
bottom={panelBottom}
chatButtonTop={chatButtonTop}
chatButtonBottom={chatButtonBottom}
floatingButtonRef={floatingButtonRef}
onNavigateToItem={onNavigateToItem}
onOpenChat={onOpenChat}
{...props}
/>
);
Inside my ChatModule component I return my chatting float button that opens my ChatNotificationsPanel component:
const closePanelClicked = (e) => {
closeChatNotificationsPanel();
};
return (
<div
className={chatNotificationsPanelClassName}
style={chatNotificationsPanelContainerStyle}
>
{!showCloseButton && renderFloatingChatButton()}
<ChatNotificationsPanel
fetching={fetching}
open={chatNotificationsPanelOpen}
isMobile={isMobileWidth}
notifications={notifications}
panelTitle={panelTitle}
panelTitleIcon={panelTitleIcon}
emptyMessage={emptyMessage}
onNavigateToItem={notificationClicked}
onCloseClick={closePanelClicked}
onClickOutside={closePanelClicked}
width={chatNotificationsPanelWidth}
/>
{showCloseButton && renderFloatingButtons()}
</div>
);
in my ChatNotificationsPanel is where I want to change my SlidingPanel component to my Modal component.
This is how it looks now:
return (
<SlidingPanel
width={width}
open={open}
top={top}
bottom={bottom}
onClickOutside={onClickOutside}
side="right"
>
<div className={listClassName}>
<CuaddsWindow
title={panelTitle}
icon={panelTitleIcon}
showCloseButton={true}
onClose={onCloseClick}
className={usesHelpCenter ? "chatContainerStyle" : "oldChatStyle"}
classNameToAdd={"titleStyle"}
headerBackgroundColor={usesHelpCenter ? "#474747" : ""}
></CuaddsWindow>
{this.renderNotificationsList()}
</div>
</SlidingPanel>
);
I am trying to Change SlidingPanel to Modal, like this:
return (
<Modal
onClickOutside={onClickOutside}
style={{ width: width, top: top, bottom: bottom }}
onClick={open}
>
<div className={listClassName}>
<Window
title={panelTitle}
icon={panelTitleIcon}
showCloseButton={true}
onClose={onCloseClick}
className={usesHelpCenter ? "chatContainerStyle" : "oldChatStyle"}
classNameToAdd={"titleStyle"}
headerBackgroundColor={usesHelpCenter ? "#474747" : ""}
></Window>
{this.renderNotificationsList()}
</div>
</Modal>
);
But it is not working, Can anyone help me to see what I am doing wrong? and how should I fix this?
Related
I'm trying to get the Menu (from #szhsin/react-menu module) element buttons to show up to the right of the previous generated item, however I'm a bit lost as to how to get it to do so. Everything results in the element showing below previous.
import React from 'react';
import {
Menu,
MenuItem,
MenuButton,
SubMenu
} from '#szhsin/react-menu';
import '#szhsin/react-menu/dist/index.css'
class TopMenuDropdown extends React.Component {
constructor(props) {
super(props);
}
render () {
return (
<div>
{this.props.TMPMenuTestCategory.map (({name,items},i) =>
{
return <Menu
align={'end'}
key={i}
menuButton={<MenuButton>{name}</MenuButton>}
reposition={'initial'}
>
{items.map((item,j) =>
{
console.log(item,j);
return <MenuItem key={j}>{item}</MenuItem>
}
)}
</Menu>
} )}
</div>
)
}
}
I was looking through the documentation on https://szhsin.github.io/react-menu/docs , however, me trying the following has had no effect:
Assigning the display:'inline' or 'flex' the <Menu> or to a <div><Menu> as I attempted to give each menu it's own div when generated.
Wrapping each generated menu in a <span>
Fiddling with the Menu item's props like 'align' , 'position' , and 'reposition' (though I'm guessing Reposition needs an additional RepositionFlag to work if I understand it correctly)
Here's the snippet of index.JS it is part of
const basicMenuArray = [
{ name: 'ProTIS', items: [ 'Login', 'Exit' ] },
{ name: 'Project', items: [ 'Open', 'Info' ] },
]
class App extends React.Component {
state={
language:'sq'
}
render () {
return (
<div >
<div style={{display:'flex', width:'75%', float:'left' }}>
<span> Temp Text </span>
</div>
<div style={{display:'flex', width:'25%'}}>
<span style={{marginLeft:'auto'}}>
<DataComboBox
dropdownOptions={languages}
value={this.state.language}
valueField='language_code'
textField='language_full_name'
onChange={(value) => alert(JSON.stringify(value))}
/>
</span>
</div>
<div>
<TopMenuDropdown TMPMenuTestCategory={basicMenuArray} />
</div>
</div>
);
}
}
So I ended up realizing something this morning, as I'm learning ReactJS still, and my brain did not process the things properly.
I changed the initial
<div>
to
<div style={{display:'flex'}}>
and added a style={{display:'flex', float:'left'}} to the <Menu> which generates the button.
the final code snippet looks like this for anyone still learning like I am :)
return (
<div style={{display:'flex'}}>
{this.props.TMPMenuTestCategory.map (({name,items},i) =>
{
return <Menu
style={{display:'flex', float:'left'}}
key={i}
menuButton={<MenuButton>{name}</MenuButton>}
>
{items.map((item,j) =>
{
console.log(item,j);
return <MenuItem key={j}>{item}</MenuItem>
}
)}
</Menu>
} )}
</div>
)
Good morning, I am in a React and JS project and I am still learning React and some things are difficult to do and I have a small problem with which I can't make any progress.
I had a modal with one color for all the results, but I have been told that depending on the result it is necessary to show one color or another. I have it defined this way in the Modal component:
const headerModal = {
0: "modal-error", //red
1: "modal-ok", //green
};
And in another component I have what would go inside the kata, everything that has the className "statusKata" should come out with headerModal={1} and the "Not started" with headerModal={0} but I don't know how to implement it, that code is this below:
import React from 'react';
const DetailUserKata = (props) => {
return (
<>
{!props.statusKata ?
<div>Obteniendo datos...</div> :
props.statusKata.length ?
<div>
<div className="statusKata"><label>Autor: </label> {props.statusKata[0].author_login_txt}</div>
<div className="statusKata"><label>Cuenta de GitHub: </label> {props.statusKata[0].autor_github_url}</div>
</div> :
<div>Not started</div>
}
</>
);
}
export default DetailUserKata;
At first, in the page where the modal is shown I had it as below with the header={1} with the green color (modal-ok), but I have to change it:
<Modal show={showKata} handleClose={hideModalKata} header={1} title="Detalles de la kata">
{<DetailUserKata statusKata={detail} />}
</Modal >
Thanks in advance! And any feedback for change or help is always welcome.
Replace green and red with your desired colors
import React from 'react';
const DetailUserKata = (props) => {
return (
<div style={{background-color: props.header === headerModal[1] ? 'green' :
props.header === headerModal[0] ? 'red' :''}
}>
{!props.statusKata ?
<div>Obteniendo datos...</div> :
props.statusKata.length ?
<div>
<div className="statusKata"><label>Autor: </label> {props.statusKata[0].author_login_txt}</div>
<div className="statusKata"><label>Cuenta de GitHub: </label> {props.statusKata[0].autor_github_url}</div>
</div> :
<div>Not started</div>
}
<div/>
);
}
export default DetailUserKata;
and move header prop to DetailUserKata
<Modal show={showKata} handleClose={hideModalKata} title="Detalles de la kata">
{<DetailUserKata statusKata={detail} header={headerModal[1]} />}
</Modal >
I am making a Accordion and when we click each individual item then its opening or closing well.
Now I have implemented expand all or collapse all option to that to make all the accordions expand/collapse.
Accordion.js
const accordionArray = [
{ heading: "Heading 1", text: "Text for Heading 1" },
{ heading: "Heading 2", text: "Text for Heading 2" },
{ heading: "Heading 3", text: "Text for Heading 3" }
];
.
.
.
{accordionArray.map((item, index) => (
<div key={index}>
<Accordion>
<Heading>
<div className="heading-box">
<h1 className="heading">{item.heading}</h1>
</div>
</Heading>
<Text expandAll={expandAll}>
<p className="text">{item.text}</p>
</Text>
</Accordion>
</div>
))}
And text.js is a file where I am making the action to open any particular content of the accordion and the code as follows,
import React from "react";
class Text extends React.Component {
render() {
return (
<div style={{ ...this.props.style }}>
{this.props.expandAll ? (
<div className={`content open`}>
{this.props.render && this.props.render(this.props.text)}
</div>
) : (
<div className={`content ${this.props.text ? "open" : ""}`}>
{this.props.text ? this.props.children : ""}
{this.props.text
? this.props.render && this.props.render(this.props.text)
: ""}
</div>
)}
</div>
);
}
}
export default Text;
Here via this.props.expandAll I am getting the value whether the expandAll is true or false. If it is true then all accordion will get the class className={`content open`} so all will gets opened.
Problem:
The open class is applied but the inside text content is not rendered.
So this line doesn't work,
{this.props.render && this.props.render(this.props.text)}
Requirement:
If expand all/collapse all button is clicked then all the accordions should gets opened/closed respectively.
This should work irrespective of previously opened/closed accordion.. So if Expand all then it should open all the accordion or else needs to close all accordion even though it was opened/closed previously.
Links:
This is the link of the file https://codesandbox.io/s/react-accordion-forked-sm5fw?file=/src/GetAccordion.js where the props are actually gets passed down.
Edit:
If I use {this.props.children} then every accordion gets opened.. No issues.
But if I open any accordion manually on click over particular item then If i click expand all then its expanded(expected) but If I click back Collapse all option then not all the accordions are closed.. The ones which we opened previously are still in open state.. But expected behavior here is that everything should gets closed.
In your file text.js
at line number 9. please replace the previous code by:
{this.props.children}
Tried in the sandbox and worked for me.
///
cant add a comment so editing the answer itself.
Accordian.js contains your hook expandAll and the heading boolean is already happening GetAccordian.js.
I suggest moving the expand all to GetAccordian.js so that you can control both values.
in this case this.props.render is not a function and this.props.text is undefined, try replacing this line
<div className={`content open`}>
{this.props.render && this.props.render(this.props.text)}
</div>
by this:
<div className={`content open`}>
{this.props.children}
</div>
EDIT: //
Other solution is to pass the expandAll property to the Accordion component
<Accordion expandAll={expandAll}>
<Heading>
<div className="heading-box">
<h1 className="heading">{item.heading}</h1>
</div>
</Heading>
<Text>
<p className="text">{item.text}</p>
</Text>
</Accordion>
then in getAccordion.js
onShow = (i) => {
this.setState({
active: this.props.expandAll ? -1: i,
reserve: this.props.expandAll ? -1: i
});
if (this.state.reserve === i) {
this.setState({
active: -1,
reserve: -1
});
}
};
render() {
const children = React.Children.map(this.props.children, (child, i) => {
return React.cloneElement(child, {
heading: this.props.expandAll || this.state.active === i,
text: this.props.expandAll || this.state.active + stage === i,
onShow: () => this.onShow(i)
});
});
return <div className="accordion">{children}</div>;
}
};
Building off of #lissettdm answer, it's not clear to me why getAccordion and accordion are two separate entities. You might have a very valid reason for the separation, but the fact that the two components' states are interdependent hints that they might be better implemented as one component.
Accordion now controls the state of it's children directly, as before, but without using getAccordion. Toggling expandAll now resets the states of the individual items as well.
const NormalAccordion = () => {
const accordionArray = [ //... your data ];
const [state, setState] = useState({
expandAll: false,
...accordionArray.map(item => false),
});
const handleExpandAll = () => {
setState((prevState) => ({
expandAll: !prevState.expandAll,
...accordionArray.map(item => !prevState.expandAll),
}));
};
const handleTextExpand = (id) => {
setState((prevState) => ({
...prevState,
[id]: !prevState[id]
}));
};
return (
<>
<div className="w-full text-right">
<button onClick={handleExpandAll}>
{state.expandAll ? `Collapse All` : `Expand All`}
</button>
</div>
<br />
{accordionArray.map((item, index) => (
<div key={index}>
<div className="accordion">
<Heading handleTextExpand={handleTextExpand} id={index}>
<div className="heading-box">
<h1 className="heading">{item.heading}</h1>
</div>
</Heading>
<Text shouldExpand={state[index]}>
<p className="text">{item.text}</p>
</Text>
</div>
</div>
))}
</>
);
};
Heading passes back the index so the parent component knows which item to turn off.
class Heading extends React.Component {
handleExpand = () => {
this.props.handleTextExpand(this.props.id);
};
render() {
return (
<div
style={ //... your styles}
onClick={this.handleExpand}
>
{this.props.children}
</div>
);
}
}
Text only cares about one prop to determine if it should display the expand content.
class Text extends React.Component {
render() {
return (
<div style={{ ...this.props.style }}>
<div
className={`content ${this.props.shouldExpand ? "open" : ""}`}
>
{this.props.shouldExpand ? this.props.children : ""}
</div>
</div>
);
}
}
I am working on a project and i want to display a hidden <div> below another <div> element using an event handler but when i click the icon that is meant to display the div, the whole page becomes blank
This is image I want:
This is what i get
I have tried to check through the internet for some places where i could get the solution. Well i found something similar to what i had done but the error still happens for me.
class PostItTeaser extends Component {
state = {
postIt: false,
moreIt: false,
}
togglePostIt = e => {
e ? e.preventDefault() : null
this.setState({ postIt: !this.state.postIt })
}
_toggle = e => {
e ? e.preventDefault() : null
this.setState({
moreIt: !this.state.moreIt,
})
}
Child = () => <div className="modal">Hello, World!</div>
render() {
let { postIt } = this.state
let { moreIt } = this.state
let {
type,
group,
disabled,
session: { id, username },
} = this.props
return (
<div>
<div
className="post_it inst"
style={{ marginBottom: type == 'group' && 10 }}
>
<img src={`/users/${id}/avatar.jpg`} alt="Your avatar" />
<div className="post_teaser">
<span
className="p_whats_new"
onClick={disabled ? null : this.togglePostIt}
>
What's new with you, #{username}? #cool
</span>
<span className="m_m_exp" data-tip="More" onClick={this._toggle}>
<MaterialIcon icon="expand_more" />
</span>
</div>
</div>
{moreIt && <Child />}
{postIt && (
<PostIt back={this.togglePostIt} type={type} group={group} />
)}
</div>
)
}
}
From skimming through the code I believe you need to bind the scope, since the function you're calling is using this.setState, it needs this to be the react component, not the event you're listening to:
onClick={this._toggle.bind(this)}
You can also bind the functions scope in the constructor. Or, a less memory performant & ugly way:
onClick={() => { this._toggle(); } }
Is it possible to render and append a new component after click? I have my calendar component
return (
<span
key={date.toString()}
className={"day" + (isToday ? " today" : "") + (isCurrentMonth ? "" : " different-month") + (date.isSame(selected) ? " selected" : "")}
onClick={()=>select(day)}>{number}</span>
);
onClick I want to render my jsWindow Component
render(){
return (
<div className="js-window">
{console.log(this.props)}
<Icon icon={close} className="closeBtn" size={24} onClick={(e)=>e.target.parentNode.parentNode.remove()}/>
{this.props.children}
</div>
)
}
After click close icon I want remove JsWindow.
You can use conditional rendering:
{ condition && <Component /> }
Put the selected day in component state and render your component based on that. On click you set or reset the state, which will trigger a rerender.
Basic example to get you started:
state = {
day: undefined
}
selectDay = day => {
this.setState({day});
};
resetDay = () => {
this.setState({day: undefined});
};
render(){
const day = this.state.day;
return day ? (
<div className="js-window">
<Icon icon={close} className="closeBtn" size={24} onClick={this.resetDay}/>
{this.props.children}
</div>
) : (
<span key={date.toString()} className={} onClick={()=>this.selectDay(day)}>{number}</span>
)
)
}