We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Create custom quick pop up's for events using functional components

Hi there, 

I am trying to create custom quick pop up's for appointments using functional components in React. It seems all the questions about this were previously answered using class components, so I'm having some trouble. I was able to figure out how to create the quick pop up for an "event" but I cannot figure out how to create a custom quick pop up for a "cell" that includes all the functionality I want it to:

  1. I want two fields: a name field that automatically pulls the correct name from my custom resource header. A text box where I can input information. Additionally, I want two buttons: More Details (which will open my custom editor) and Add Event (which will create the new event)
  2. How do I pull the information from my custom resource header? 
  3. How do I send the information I have input on my pop up to my custom editor? 
  4. How do I create the new event? 

If you can create a template using functional react components, that would be great! 

Thank you!

6 Replies

SK Satheesh Kumar Balasubramanian Syncfusion Team March 3, 2023 11:46 AM UTC

Hi Jessica,

 

Query 1, 3 & 4:

 

We have customized the quick popup for appointments using a functional component as per your requirements. Refer to the below demo and UG links for more details.

 

 

Query 2:

 

Before proceeding further with your query, we need some more details to validate further. Can you please share what information you want to pull from the custom resource header? or the use case scenario of your requirement it will help us to provide the solution for your query earlier.


Regards,

Satheesh Kumar B



JN Jessica Newman replied to Satheesh Kumar Balasubramanian March 3, 2023 07:54 PM UTC

Thank you! This has been tremendously helpful. 

With regards to the Resource Header, see my code below. The data that is passed in is an array of objects, so there is one row in the scheduler per object. When I add a new event within the scheduler, I click on a specific time slot in a specified row (the row contains a specific individuals information, aka the resource header). So, if a row is designated to show appointments for "Jessica Newman", I want that individual's information to automatically fill in to a <span></span> in the quick pop up when I create a new event via a pop up. Does that make sense?

function ResourceHeaderTemplate({data}) {
const resourceData = data.resourceData
return (
<ListItem>
<ListItemAvatar>
<Avatar src={resourceData.photo}>
</Avatar>
</ListItemAvatar>
<ListItemText primary={resourceData.text} secondary={`Room: ${resourceData.roomNumber}`}/>
</ListItem>
);
}


SR Swathi Ravi Syncfusion Team March 6, 2023 02:34 PM UTC

Jessica,


You can add the resource details in the quick popup when the cell clicks by using the Schedule’s cellClick event. you can get the resource details by passing the groupIndex as a parameter to the getResoucesByIndex method, and then use the details in the template, as shown in the below snippet.


Sample: https://stackblitz.com/edit/react-schedule-functional-quick-info-4mie28?file=index.js

Api: https://ej2.syncfusion.com/react/documentation/api/schedule/#getresourcesbyindex

https://ej2.syncfusion.com/react/documentation/api/schedule/#cellclick


[index.js]

function headerTemplate(props) {

        return (<div className="quick-info-header">

            <div className="quick-info-header-content" style={getHeaderStyles(props)}>

                <div className="quick-info-title" >{getHeaderTitle(props)}</div>

                {props.elementType==="cell" && <div className="quick-info-resource" style={background: `${Resource.Color}` }}>{Resource.Name}</div> }

                <div className="duration-text">{getHeaderDetails(props)}</div>

            </div>

        </div>);

    }

 

function cellClick(args) {

        Resource = scheduleObj.getResourcesByIndex(args.groupIndex).resourceData;

    }



JN Jessica Newman March 6, 2023 06:44 PM UTC

Great! One additional question: I separated my header, content and footer functions into their own components for reusability purposes. Just like in your stackblitz example, I declare a titleObj in my schedule component. I pass that variable into my content component and use it in my TextBoxComponent: 

<TextBoxComponent
id="title"
ref={typedTitle => titleObj = typedTitle}
placeholder="Title"
/>


titleObj remains undefined. In my footer component, I also pass in titleObj and when I handle my add event, I get the error: "Uncaught TypeError: Cannot read properties of undefined (reading 'previousValue') at handleAddEvent". How can I pass the titleObj between components? I was trying to use the useRef() hook, but the previousValue remained null upon typing in my textbox and adding my event. Please advise!



JN Jessica Newman replied to Jessica Newman March 9, 2023 01:52 PM UTC

Hi there - Wondering I can get a response by the end of the week? This is impacting a project deadline I have. Thanks!



RV Ravikumar Venkatesan Syncfusion Team March 9, 2023 05:39 PM UTC

Jessica,


Sample: https://stackblitz.com/edit/ej2-react-schedule-quick-info-template-lifting-state-up?file=index.js


Based on your query we suspect that you require the titleObj instance to add an appointment directly from the quick info popup and open the editor based on the value titleObj value. You can achieve this with React lifting state up way as shown in the below code snippets.


[index.js]

import HeaderTemplate from './header-template';

import ContentTemplate from './content-template';

import FooterTemplate from './footer-template';

 

function QuickInfoTemplate() {

    let scheduleObj;

    let quickPopupData = {};

 

    function headerTemplate(props) {

        return <HeaderTemplate data={props}></HeaderTemplate>;

    }

 

    function contentTemplate(props) {

        return <ContentTemplate data={props} handleChange={handleTextChange}></ContentTemplate>;

    }

 

    function footerTemplate(props) {

        return <FooterTemplate data={props} getQuickData={getQuickPopupData} scheduleObj={scheduleObj}></FooterTemplate>;

    }

 

    function handleTextChange(quickData) {

        quickPopupData = quickData;

    }

 

    function getQuickPopupData() {

        return quickPopupData;

    }

 

    return (<div className='schedule-control-section'>

        <div className='col-lg-12 control-section'>

            <div className='control-wrapper'>

                <ScheduleComponent ref={(schedule=> scheduleObj = schedule} quickInfoTemplates={{ header: headerTemplate.bind(this), content: contentTemplate.bind(this), footer: footerTemplate.bind(this)}}>

                    <Inject services={[DayWeekWorkWeekMonthAgendaMonthAgenda]} />

                </ScheduleComponent>

            </div>

        </div>

    </div>

    );

}

export default QuickInfoTemplate;


[content-template.js]

function ContentTemplate(props) {

  const [quickDatasetQuickData] = useState({ Subject: ""Description: "" });

 

  return (

    <div className="quick-info-content">

      {props.data.elementType === 'cell' ?

        <div className="e-cell-content">

          <div className="content-area">

            <TextBoxComponent id="title" onChange={(event=> { quickData.Subject = event.valueprops.handleChange(quickData); }} placeholder="Title" />

          </div>

          <div className="content-area">

            <TextBoxComponent id="notes" onChange={(event=> { quickData.Description = event.valueprops.handleChange(quickData); }} placeholder="Notes" />

          </div>

        </div>

        :

        <div className="event-content">

          <div className="meeting-type-wrap">

            <label>Subject</label>:

            <span>{props.data.Subject}</span>

          </div>

          <div className="notes-wrap">

            <label>Notes</label>:

            <span>{props.data.Description}</span>

          </div>

        </div>}

    </div>

  );

};

 

export default ContentTemplate;


[footer-template.js]

function FooterTemplate(props) {

 

  function buttonClickActions(e) {

    var appDetail = props.getQuickData();

    var scheduleObj = props.scheduleObj;

    const getSlotData = () => {

      const addObj = {};

      addObj.Id = scheduleObj.getEventMaxID();

      addObj.Subject = appDetail && appDetail.Subject ? appDetail.Subject : 'Add title';

      addObj.StartTime = new Date(scheduleObj.activeCellsData.startTime);

      addObj.EndTime = new Date(scheduleObj.activeCellsData.endTime);

      addObj.IsAllDay = scheduleObj.activeCellsData.isAllDay;

      addObj.Description = appDetail && appDetail.Description ? appDetail.Description : 'Add notes';

      return addObj;

    };

    if (e.target.id === 'add') {

      const addObj = getSlotData();

      props.scheduleObj.addEvent(addObj);

    }

    else if (e.target.id === 'delete') {

      const eventDetails = scheduleObj.activeEventData.event;

      let currentAction = 'Delete';

      if (eventDetails.RecurrenceRule) {

        currentAction = 'DeleteOccurrence';

      }

      scheduleObj.deleteEvent(eventDetailscurrentAction);

    }

    else {

      const isCellPopup = props.data.elementType === "cell";

      const eventDetails = isCellPopup ? getSlotData() : scheduleObj.activeEventData.event;

      let currentAction = isCellPopup ? 'Add' : 'Save';

      if (eventDetails.RecurrenceRule) {

        currentAction = 'EditOccurrence';

      }

      scheduleObj.openEditor(eventDetailscurrentActiontrue);

    }

    scheduleObj.closeQuickInfoPopup();

  };

 

  return (

    <div className="quick-info-footer">

      {props.data.elementType == "cell" ?

        <div className="cell-footer">

          <ButtonComponent id="more-details" cssClass='e-flat' content="More Details" onClick={buttonClickActions} />

          <ButtonComponent id="add" cssClass='e-flat' content="Add" isPrimary={true} onClick={buttonClickActions} />

        </div>

        :

        <div className="event-footer">

          <ButtonComponent id="delete" cssClass='e-flat' content="Delete" onClick={buttonClickActions} />

          <ButtonComponent id="more-details" cssClass='e-flat' content="More Details" isPrimary={true} onClick={buttonClickActions} />

        </div>}

    </div>

  );

};

export default FooterTemplate;


Loader.
Live Chat Icon For mobile
Up arrow icon