React Big Calendar Outside DnD - reactjs

I am using React Big Calendar
https://github.com/intljusticemission/react-big-calendar .
And it has an Drag n Drop option using react-dnd https://github.com/react-dnd/react-dnd . What I am trying to do is to have draggable elements outside of calendar, which I can drag inside the Calendar. Like this : https://codepen.io/kotazi/pen/KVoXob .
class Application extends React.Component {
render() {
return <div><External />
<Calendar /></div>;
}
}
/*
* A simple React component
*/
class Calendar extends React.Component {
render() {
return <div id="calendar"></div>;
}
componentDidMount() {
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: true,
droppable: true, // this allows things to be dropped onto the calendar
drop: function() {
// is the "remove after drop" checkbox checked?
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the "Draggable Events" list
$(this).remove();
}
}
})
}
}
class External extends React.Component {
render() {
return <div id='external-events'>
<h4>Draggable Events</h4>
<div className='fc-event'>My Event 1</div>
<div className='fc-event'>My Event 2</div>
<div className='fc-event'>My Event 3</div>
<div className='fc-event'>My Event 4</div>
<div className='fc-event'>My Event 5</div>
<p>
<input type='checkbox' id='drop-remove' />
<label for='drop-remove'>remove after drop</label>
</p>
</div>;
}
componentDidMount() {
$('#external-events .fc-event').each(function() {
// store data so the calendar knows to render an event upon drop
$(this).data('event', {
title: $.trim($(this).text()), // use the element's text as the event title
stick: true // maintain when user navigates (see docs on the renderEvent method)
});
// make the event draggable using jQuery UI
$(this).draggable({
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0 // original position after the drag
});
});
}
}
/*
* Render the above component into the div#app
*/
React.render(<Application />, document.getElementById('app'));
Only 'solution' that I have found is this one https://github.com/intljusticemission/react-big-calendar/issues/318 but I have no idea how he did it. I have the same code as drag example http://intljusticemission.github.io/react-big-calendar/examples/index.html#prop-onNavigate . Can someone help me, please?

Related

Why is my SVG not appearing when passed as prop?

I've looked through some of the other, similar questions on here, but none of the solutions seem to work for me.
I have a class component that represents a cell on a grid, and for each cell, I want there to be a specific background image that is revealed with the cell is hovered. The default component looks like this:
const Home = () => {
return (
<div id="main">
<Box title='About' svg={ BG1 } />
<Box title='Work' svg={ BG2 } />
<Box title='Portfolio' svg={ BG3 } />
<Box title='Resume' svg={ BG4 } />
</div>
);
};
I want to pass SVG components as background images, but can't seem to figure it out. I've imported each background image like this:
import { ReactComponent as BG1 } from './bg1.svg';
In the Box component, I've added state to handle some of the child elements, and the title prop seems to work out well, but the svg prop doesn't seem to work for me:
class Box extends React.Component {
constructor(props) {
super(props);
this.state = {
hovered: false,
};
}
hoverOn = e => {
this.setState({ hovered: true });
};
hoverOff = e => {
this.setState({ hovered: false });
};
render() {
const { hovered } = this.state;
const style = hovered ? { transform: 'translateY(-20%)', opacity: '.05' } : {};
return(
<section onMouseEnter={this.hoverOn} onMouseLeave={this.hoverOff}>
<a>
<div className="overlay" style={ style }></div>
<div className="bg" style={{ backgroundImage: `url(${this.props.svg})` }} ></div>
<div className="innerContent">
<h2>
{this.props.title}
</h2>
</div>
</a>
</section>
);
};
};
Whenever I inspect my developmental site, I just see <div class='bg'></div>. Any suggestions?
It's not working because BG1 is being set to the SVG file contents; not a link to the SVG file. I think you can just reference the filename in url("./bg1.svg") and it will expand it at build time. However, that probably won't work when you just pass in the filename as a prop. So - you could put the SVGs into the public folder and do something like this: {process.env.PUBLIC_URL + '/img/logo.png'}. Escape hatch doc.
With Vite you can do this: import modelGLB from './static/model.glb?url' to get the URL, but I forget the create-react-app equivalent.

Focus on (scroll to) a DIV element in React

I have a toggle DIV element and I want to focus on (scroll to) it when it opens.
I followed the doc together with tabindex="-1" with no effect.
class App extends Component {
constructor(props) {
super(props);
this.state = {
formVisible: false
}
this.formRef = React.createRef();
this.onReply = this.onReply.bind(this);
}
onReply(e) {
this.formRef.current.focus(); // doesn't have any effect
this.setState({formVisible: true});
}
render() {
return (
<div>
<div>
<a onClick={this.onReply} href="#">Reply</a>
</div>
<div>
....
</div>
<div ref={this.formRef} tabindex="-1">
{this.state.formVisible &&
<form>
...
</form>
}
</div>
</div>
);
}
}
So far I'm using an anchor, but I don't find this solution very elegant...
...
<a onClick={this.onReply} href="#form">Reply</a>
...
<a name="form"></a>
{this.state.formVisible &&
...
Another problem of the anchor approach is, when there are more dynamically created elements on the page. Then I have to use some kind of ID for the anchor, which is pretty complex:
const {id} = this.props.data;
...
<a onClick={this.onReply} href={"#form-" + id}>Reply</a>
...
<a name={"form-" + id}></a>
{this.state.formVisible &&
...
Because your form is rendered only when formVisible is true, you need to wait until your component is re-rendered before trying to scroll to it. Use componentDidUpdate combined with scrollIntoView:
componentDidUpdate(prevProps) {
// `formVisible` went from false -> true, scroll the <form> into view
if (!prevProps.formVisible && this.props.formVisible) {
this.formRef.current.scrollIntoView();
}
}

How to add scroll event on a React component instead of adding on window object?

I used ReactJS to create a resume, that resume's body have 100vw and 100vh dimension ie, there is no scroll at window/body level, but inside resume there is one component which contains scroll. At the end I want to create a sticky Header. But before creating sticky header this code should run first. I tried this:
componentDidMount() {
ReactDOM.findDOMNode(this.refs.stickyHeader).addEventListener('scroll', this.isScrollOccured.bind(this));
}
componentWillUnmount() {
ReactDOM.findDOMNode(this.refs.stickyHeader).removeEventListener('scroll', this.isScrollOccured.bind(this));
}
isScrollOccured() {
console.log('Scrolling Occured');
}
render() {
return (
<div className="Container">
<div className="Header" ref="stickyHeader">
[...]
</div>
</div>
)
}
This is not giving any response, but if I change scroll event with wheel event inside addEventListener, it works fine, But I don't want to use wheel. I checked Other's Solution but it didn't work for me. Help me to find out the solution. If necessary I will upload Image.png of my work.
The refs API has changed. Try this instead
stickyHeader = React.createRef()
componentDidMount() {
this.stickyHeader.current.addEventListener(
"scroll",
this.isScrollOccured.bind(this)
);
}
componentWillUnmount() {
this.stickyHeader.current.removeEventListener(
"scroll",
this.isScrollOccured.bind(this)
);
}
isScrollOccured() {
console.log("Scrolling Occured");
}
render() {
return (
<div className="Container">
<div className="Header" ref={this.stickyHeader}>
[...]
</div>
</div>
);
}
You can learn more about refs here.

How to hide / show the content of a component that is reused by different views in ReactJS

I have two views that call a particular component and this makes it difficult for me to hide / show when the component is needed. In this way, I have the following:
I tried to make a display: none to overide the styles but it is a problem. This is because the views when using the same component, the classes of the CSS are called the same and when I make the display: none, I get it not to show in "News" but in "Home" it also affects and it is not shown to me.
I tried it:
Component Section:
<div className="section_news">
{orden.map(this.renderSection)}
<ViewAllNews mostrarCategorias={false} categoriaId={newsId} />
If I remove the title like this, I'll leave the view "Home" and "News", and that's not what I intend to do.
Next, I leave the original piece of code:
View named "Home":
<div className="contentbar">
<Section title="Ult. News" />
<Section
notices_id={19}
orden={[[0, 3], [3, 1], [4, 2]]}
/>
</div>
**View named "News": **
<Section
notices_id={data.post.category.id}
orden={[[0, 2], [2, 3]]}
/>
Component Section:
<div className="section_news">
<Titles title={title || (category && category.title)} />
{orden.map(this.renderSection)}
<ViewAllNews categoriaId={newsId} />
Component ViewAllNews:
return (
<Link to={`/news/c/${categoryId}/`}>
<div className="parentLineViewAll">
<div className="LineViewAll" />
<div className="line" />
<div className="Views">View All</div>
<div className="arrowMore">
<FontAwesomeIcon icon="chevron-circle-right" />
</div>
</div>
</Link>
);
};
As you can see, the view of "Home" and "Views" make use of the same component.
What I really need is to hide the component named for the "News" view and also hide the "ViewAllNews" component only for the "News" view.
Thanks for your help!
The easiest way to hide / show react components is to use conditional rendering
Here is a basic example:
class MyComponent Extends React.Component {
constructor(props){
super(props)
this.state = {
isVisible: false, // <-- add a value to state so we can track the components visibility
}
}
show = () => {
this.setState({ isVisible: false })
}
hide = () => {
this.setState({ isVisible: true })
}
render(){
if(this.state.isVisible){
return (
/* your component code */
)
}
}
}
If you want to toggle the component from inside a parent component then you can control this with a ref:
class Parent Extends React.Component {
constructor(props){
this.myRef = React.createRef()
}
render(){
return <MyComponent ref={this.myRef}>
}
}
Once the component mounts, you can check if the ref has been set and call the method anywhere in your code:
if(this.myRef.current){
this.myRef.current.show() // or .hide()
}
You can also control the components visibility via props:
function MyComponent({ isVisible }){
if(isVisible){
return (
/* your component code */
)
}
}
Hope that helps, let me know if you have any questions!
a way to implement this componentWillUnmount() and componentWillMount() ,
like to this example , hope help you this.

Ability to add div element next to chart using plotly.js

I am trying to add an external div element(Summary Panel) on the right side of the bar chart I have implemented using react-plotly.js.
The div element would pop-up next to the chart when onClick event is fired on the chart. The panel would display the information related to the bar that was clicked. The data object based on which the bar chart is created is:
const barData = [
{ endTime: '', startTime: '', duration: 6, initiatorUsername: 'abc', title: 'abc1', aTitle: 'Manager', outcome: 'Success' },
{ endTime: '1521203405', startTime: '1520389805', duration: 7, initiatorUsername: 'defs', title: 'Senior Analyst', aTitle: 'Manager', outcome: 'Failure' }
];
I haven't seen any such example or any documentation related to add external div element to the chart. Is it possible to link chart to the external div element ?
I did attempt to implement it by doing the following:
<Plot
data={this.prepData(timelineData)}
onClick={(data) => {
this.renderCustomPanel(data);
}
onHover={(hover) => this.getHoverInfo(hover)}
type={'bar'}
layout={layout}
style={{ width: '95%' }}
/>
renderCustomPanel(e) {
const panelInfo = timelineData.map(i => `<span className="panel-info">
<span className="tooltip-value" style='font-size:15px;display:block'>${i.duration} days <br> Start time: ${moment.unix(i.startTime).format('MMM-DD-YYYY h:mm:ss')} <br> End time:${moment.unix(i.endTime).format('MMM-DD-YYYY h:mm:ss')}</span></span>`);
return panelInfo;
}
The onClick function does call the function but doesn't display the div element. I did try applying css styles to the element but nothing works. Firstly, how do I make a panel display onClick?
Alternate solution that comes to my mind is to make panel a separate sibling component. In that case, How do I pass the data to it such that in the description section it displays the information related to the bar that was clicked ?
class SummaryPanel extends Component {
constructor(props) {
super(props);
this.state = {
isActive: true
};
}
render() {
return (
<div className='summaryPanel'>
<Card
label='Summary panel'
heading=''
description=''
/>
<button type="button" className="close" data-dismiss="alert" aria-label="Close" onClick={() => this.hideAlert()}><span aria-hidden="true">×</span></button>
</div>
);
}
}

Resources