Customize the small editor

I wanted to customise the editor not the detailed one which we can using editor template but the small one before popup

i want to add just one more field to it which is a dropdown

and want to display that in the scheduler and not the title

so how to firstly customize the editor and secondly display not the title/subject but that added field dropdown value plus time on the scheduler as event

and lastly i believe it automatically updates the events array after an event is rendered
so i have made a state and use that initial events as my initial value and use that state variable as dataSource

const initialUserEvents = [
  {
    Id: 1,
    Subject: "Hello",
    StartTime: new Date(2023, 6, 1, 15, 0),
    EndTime: new Date(2023, 6, 2, 11, 30),
    ResourceID: 1, // Department ID from the resource array
    Department:'Kitchen'
  },
  {
    Id: 2,
    Subject: "You",
    StartTime: new Date(2023, 6, 9, 13, 0),
    EndTime: new Date(2023, 6, 11, 17, 0),
    ResourceID: 2, // Department ID from the resource array
    Department:'Washroom'
  },
  // Add more events as needed
];
  const [userEvents, setUserEvents] = useState(initialUserEvents);
 const eventSettings: EventSettingsModel = {
    dataSource: contextValue?.userEvents,
  };
//now after consoling logging after adding events i am getting the updated events arr with all default values except my //customize dropdown select value //i want to push that as well while updating my arr //here is how i am configuring edtiortemplate using PopOpen as of now since i want all the default values but just one //more value
  const handlePopupOpen = (args: PopupOpenEventArgs): void => {
    console.log(args);
    if (args.type === "Editor") {
      const allDayTimeZoneRow = args.element.querySelector(
        ".e-all-day-time-zone-row"
      ) as HTMLElement;
      if (allDayTimeZoneRow) {
        // Remove the element
        // allDayTimeZoneRow.remove();

        // Or, make it hidden
        allDayTimeZoneRow.style.display = "none";

        let selectElement = document.getElementById(
          "dept"
        ) as HTMLSelectElement;

        if (!selectElement) {
          const containerDiv = document.createElement("div");
          containerDiv.classList.add("form-group");

          // Create and append the label
          const label = document.createElement("label");
          label.textContent = "Departments";
          label.classList.add("control-label");
          containerDiv.appendChild(label);

          // Create the select element
          selectElement = document.createElement("select");
          selectElement.classList.add("e-field", "form-control", "mt-3");
          selectElement.style.height = "30px"; // Set the height to 200 pixels
          selectElement.style.width = "120px";
          selectElement.style.fontSize = "12px";
          selectElement.setAttribute("id", "dept");
          selectElement.setAttribute("data-name", "Department");
          selectElement.setAttribute("value", "props.Department");

          // Append the select element to a parent element
          // const defaultDepartment = "Kitchen";

          // const optionElements = contextValue?.deptData.map((dept) => {
          //   return `<option value="${dept.DepartmentText}"  style="color: ${dept.DepartmentColor};">
          //   ${dept.DepartmentText}
          //   </option>`;
          // });
          const optionElements = contextValue?.deptData.map((dept, index) => {
            if (index === 0) {
              return `<option value="${dept.DepartmentText}" selected style="color: ${dept.DepartmentColor};">
                    ${dept.DepartmentText}
                    </option>`;
            } else {
              return `<option value="${dept.DepartmentText}" style="color: ${dept.DepartmentColor};">
                    ${dept.DepartmentText}
                    </option>`;
            }
          });

          console.log(selectElement.value);

          // Assuming you have an HTML <select> element with the id "departmentSelect"

          selectElement.innerHTML = optionElements
            ? optionElements.join("")
            : "";

          // Append the select element to the container div
          containerDiv.appendChild(selectElement);

          // Insert the container div after the hidden row
          allDayTimeZoneRow.insertAdjacentElement("afterend", containerDiv);
        } else {
          console.log("H");
        }
        // Or, make it disabled
        // const checkboxInput = allDayTimeZoneRow.querySelector('.e-all-day');
        // if (checkboxInput) {
        //   checkboxInput.disabled = true;
        // }
      } else {
        return;
      }
    }
  };
// now if i console log my newEvent on eventrendered it does show department prop but my userEvents arr doesn't show //it

5 Replies

SK Satheesh Kumar Balasubramanian Syncfusion Team July 12, 2023 12:10 PM UTC



AY Ab Y replied to Satheesh Kumar Balasubramanian July 12, 2023 08:01 PM UTC

Thanks and how do i show my dropdown value in the schedular instead of subject when submitting quickinfo template. By dfault it displays the title value in cell but i want to show my dropdown value in it instead of subject/title




VS Venkateshwaran Saravanakumar Syncfusion Team July 13, 2023 01:06 PM UTC

Hi Aby,

Sample: https://stackblitz.com/edit/react-anw52p-vjy8aa?file=index.js

You can achieve your requirement by setting up the eventTypeObj(dropdown) text value to the Subject value, as shown in the highlighted code snippet below. Try the shared sample and let us know if you need any further assistance.

[index.js]

const buttonClickActions = (e=> {

        const quickPopup = closest(e.target'.e-quick-popup-wrapper');

        const getSlotData = () => {

            const addObj = {};

            addObj.Id = scheduleObj.current.getEventMaxID();

            addObj.Subject = eventTypeObj.current.text;

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

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

            addObj.IsAllDay = scheduleObj.current.activeCellsData.isAllDay;

            addObj.Description = isNullOrUndefined(notesObj.current.value) ? 'Add notes' : notesObj.current.value;

            addObj.RoomId = eventTypeObj.current.value;

            return addObj;

        };


 
const contentTemplate = (props=> {

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

                {props.elementType === 'cell' ?

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

                        <div className="content-area">

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

                        </div>

                        <div className="content-area">

                            <DropDownListComponent id="eventType" ref={eventTypeObj} dataSource={roomData} fields={text: "Name"value: "Id" }} placeholder="Choose Type" index={0} popupHeight="200px"/>

                        </div>

                        <div className="content-area">

                            <TextBoxComponent id="notes" ref={notesObj} placeholder="Notes"/>

                        </div>

                    </div>

                :

                    <div className="event-content">

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

                            <label>Subject</label>:

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

                        </div>

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

                            <label>Type</label>:

                            <span>{getEventType(props)}</span>

                        </div>

                        <div className="notes-wrap">

                            <label>Notes</label>:

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

                        </div>

                    </div>}

            </div>);

    };



 



Regards,
Venkatesh



AY Ab Y replied to Venkateshwaran Saravanakumar July 14, 2023 03:29 AM UTC

Thankyou.Iam doing it but i thought its not proper way to assign the classname of subject to my depatment.
i have one more query. I know what the issue is but i can't seem to get hold of the solution. so basically there are two Scheduler Components. One is user and one is dept. So i am basically sending the user events which contain department dropdown value into dept one and basically informing the dept that this user is assigned for this dept at this slot etc and i am using useContext hook and basically updating the deptEvents through useState after i get userEvent
So the issue is that when i am using setState method for updating my deptEvents since it is synchoronous it is executed at the end after every thing is done and my deptEvent doesn't show the userEvent data.However if i rerender then it does show me the data on second render since uptil now useState has been executed and data has been set. I wanna show data on first render whenever the component is first rendered.
I am using useeffect but to no avail. It is giving me userEvent data but i cannot set it on time
Here is my deptSchedular Component. UserSchedular is similar one and i am not inserting here since it isn't needed. it is just updating its own userEvents and i am getting those events through useContext in Dept Schedular Component

. Also owner data is resourceData of Userevent with name of the user in it
and addnewSchedule is the method which updates the deptEvents after getting UserEvent in useEffect.Also why is previous event data rerendered every single time when any event is rendered.And not for once

import * as React from "react";
import * as ReactDOM from "react-dom";

import * as Func from "./datasourceDept";
import "../../node_modules/@syncfusion/ej2-react-schedule/styles/material.css";

import {
ScheduleComponent,
ViewsDirective,
ViewDirective,
ResourcesDirective,
ResourceDirective,
Inject,
Day,
TimelineViews,
TimelineMonth,
PopupOpenEventArgs,
} from "@syncfusion/ej2-react-schedule";
import { Calendar2 } from "./UserSchedular";
import { useState, useEffect } from "react";
import img from "../assets/image.png";
import { initialOwnerData } from "./datasourceUser";
import { useContext } from "react";
import SchedularContext from "../context/SchedularContext";

interface departmentData {
DepartmentText: string;
Id: number;
DepartmentColor: string;
}

export const SchedulerDept = () => {
const [showModal, setShowModal] = useState(false);
const [showNestedModal, setShowNestedModal] = useState(false);
const [deptName, setdeptName] = useState("");
let contextValue = useContext(SchedularContext);

const openModal = () => {
setShowModal(true);
};

const openModal2 = () => {
setShowNestedModal(true);
};
const closeModal = () => {
setShowModal(false);
setdeptName("");
};

const closeModal2 = () => {
setShowNestedModal(false);
setdeptName("");
};
const handleAddOwner = () => {
console.log("working");
const nextId = contextValue?.deptData
? contextValue?.deptData.length + 1
: 1;
const randomColor = "#" + ((Math.random() * 0xffffff) << 0).toString(16);
const newDept: departmentData = {
DepartmentText: deptName,
Id: nextId,
DepartmentColor: randomColor,
};

contextValue?.setDeptdata([...contextValue.deptData, newDept]);

console.log(contextValue?.deptData);

closeModal2();
};

const handlePopupOpen = (args: PopupOpenEventArgs): void => {
if (args.type === "Editor") {
const allDayTimeZoneRow = args.element.querySelector(
".e-all-day-time-zone-row"
) as HTMLElement;
if (allDayTimeZoneRow) {
// Remove the element
// allDayTimeZoneRow.remove();

// Or, make it hidden
allDayTimeZoneRow.style.display = "none";

let selectElement = document.getElementById(
"user"
) as HTMLSelectElement;

if (!selectElement) {
const containerDiv = document.createElement("div");
containerDiv.classList.add("form-group");

// Create and append the label
const label = document.createElement("label");
label.textContent = "Users";
label.classList.add("control-label");
containerDiv.appendChild(label);

// Create the select element
selectElement = document.createElement("select");
selectElement.classList.add("e-field", "form-control", "mt-3");
selectElement.style.height = "30px"; // Set the height to 200 pixels
selectElement.style.width = "120px";
selectElement.style.fontSize = "12px";
selectElement.setAttribute("id", "user");
selectElement.setAttribute("data-name", "User");
selectElement.setAttribute("value", "props.User");

// Append the select element to a parent element
const defaultDepartment = "Kitchen"; // Set the desired default department here

const optionElements = contextValue?.ownerData.map((owner) => {
// const isSelected = dept.DepartmentText === defaultDepartment ? "selected" : "";
return `owner.OwnerText}" style="color: ${owner.OwnerColor};" >
${owner.OwnerText}
`;
});

selectElement.innerHTML = optionElements
? optionElements.join("")
: "";

// Append the select element to the container div
containerDiv.appendChild(selectElement);

// Insert the container div after the hidden row
allDayTimeZoneRow.insertAdjacentElement("afterend", containerDiv);
} else {
console.log("H");
}
// Or, make it disabled
// const checkboxInput = allDayTimeZoneRow.querySelector('.e-all-day');
// if (checkboxInput) {
// checkboxInput.disabled = true;
// }
} else {
return;
}
}
};
const [id, setId] = useState(0);
const addNewSchedule = (scheduleData: any) => {
const { Id, Subject, StartTime, EndTime, ResourceID, Department } =
scheduleData;

const newSchedule = {
Id: contextValue?.deptEvents ? contextValue.deptEvents.length + 1 : 1,
Subject,
StartTime,
EndTime,
ResourceID,
Department,
};

console.log(newSchedule);
const duplicateObject = contextValue?.deptEvents.find((item) => {
return item.Id === newSchedule.Id;
});

const duplicateTime = contextValue?.deptEvents.find((item) => {
return (
item.Subject === newSchedule.Subject &&
item.StartTime === newSchedule?.StartTime &&
item.EndTime === newSchedule?.EndTime
);
});

console.log(duplicateObject, duplicateTime);

const owner = contextValue?.ownerData.find(
(owner) => owner.Id === newSchedule.ResourceID
);

for (const data of contextValue.deptData) {
if (newSchedule["Department"] === data.DepartmentText && owner) {
const updatedSchedule = {
...newSchedule,

ResourceID: data.Id,
Subject: owner.OwnerText,
};

contextValue?.setDeptEvents((prevDeptEvents) => {
const isDuplicate = prevDeptEvents.find((event) => {
return (
event.Subject === updatedSchedule.Subject &&
event.StartTime === updatedSchedule.StartTime
);
});
if (isDuplicate) {
console.log("Duplicate");
// If the updatedSchedule is already present, return the previous array without adding it again
return prevDeptEvents;
} else {
console.log("Added");
setId((prevId) => prevId + 1);

updatedSchedule.Id = prevDeptEvents.length + 1;
// If it's not a duplicate, add the updatedSchedule to the array
return [...prevDeptEvents, updatedSchedule];
}
});

break; // Exit the loop after finding a match
}
}

// if (newSchedule.Subject) {
// if (newSchedule.Department == undefined) {
// newSchedule.Department = "Nancy";
// const updatedEvents = [...contextValue?.deptEvents, newSchedule];
// contextValue?.setDeptEvents(updatedEvents);
// } else {
// const updatedEvents = [...contextValue?.deptEvents, newSchedule];
// contextValue?.setDeptEvents(updatedEvents);
// }
// }
};

const handleAction = (args: any) => {
if (args.items) {
args.items[5].text = "Day";
args.items[6].text = "Week";
args.items[7].text = "Month";
}
};

const handleEventRendered = (args: any) => {
const scheduleData = args.data;
console.log(args);
console.log(scheduleData);
const duplicateObject = contextValue?.deptEvents.find((item) => {
return (
item.Subject === scheduleData.Subject &&
item.StartTime === scheduleData.StartTime
);
});
if (!duplicateObject) {
scheduleData.Id = contextValue?.deptEvents
? contextValue?.deptEvents.length + 1
: 1;
contextValue?.setDeptEvents([...contextValue.deptEvents, scheduleData]);
} else {
console.log("Value duplicate");
}
const r = scheduleData.ResourceID;

let f = initialOwnerData.find(
(owner: any) => owner.OwnerText == scheduleData.Subject
);

};

const iconsRender = () => {
const elements = document.querySelectorAll(".e-resource-text") as any;
var check = document.getElementsByClassName("img");
console.log(check);

elements.forEach(function (element: any, index: any) {
if (index !== 0) {
// if (!check) {
if (!element.querySelector(".img")) {
var img2 = document.createElement("img");
img2.classList.add("img");
img2.setAttribute("src", img);
img2.style.width = "20px";
img2.style.height = "30px";
element.appendChild(img2);
// console.log(element);
// }
}
}
});
};

useEffect(() => {
let userEvent = contextValue?.userEvents.map((user) => {
if (user) {
console.log(user);
addNewSchedule(user);
}
});

//let user = contextValue?.userEvents[contextValue.userEvents.length - 1];
}, [contextValue?.userEvents]);

useEffect(() => {
console.log(contextValue?.deptEvents);
}, [contextValue?.deptEvents]);

const eventSettings = { dataSource: contextValue?.deptEvents };

const group = { resources: ["Departments"] };

return (
<>
<ScheduleComponent
eventRendered={handleEventRendered}
width="950px"
height="450px"
currentView="TimelineWeek"
selectedDate={new Date(2023, 6, 1)}
eventSettings={eventSettings}
group={group}
dataBound={iconsRender}
popupOpen={handlePopupOpen}
actionBegin={handleAction}
>
<ViewsDirective>
<ViewDirective option="TimelineDay" />
<ViewDirective option="TimelineWeek" />
<ViewDirective option="TimelineMonth" />
ViewsDirective>
<ResourcesDirective>
<ResourceDirective
field="ResourceID"
title="Department Name"
name="Departments"
allowMultiple={true}
dataSource={contextValue?.deptData}
textField="DepartmentText"
idField="Id"
colorField="DepartmentColor"
>ResourceDirective>
ResourcesDirective>
<Inject services={[TimelineViews, TimelineMonth]} />
ScheduleComponent>

<button className="btn btn-primary mb-3 mt-3" onClick={openModal}>
Add Department
button>

{showModal && (
<>
<div
className="modal d-block"
style={{
backgroundColor: "rgba(0,0,0,0.5)",
textAlign: "center",
}}
>
<div style={{ backgroundColor: "white", height: "20%" }}>
{" "}
<button
className="btn btn-primary mb-3"
onClick={openModal2}
style={{ marginTop: "40px" }}
>
Add User
button>
<button
className="btn btn-primary mb-3"
onClick={closeModal}
style={{ marginTop: "40px", marginLeft: "5px" }}
>
Close
button>
div>
<table className="table table-bordered">
<thead className="thead-dark">
<tr>
<th>Idth>
<th>Nameth>
<th>Colorth>
tr>
thead>
<tbody>
{contextValue?.deptData.map((dept) => (
<tr key={dept.Id}>
<td>{dept.Id}td>
<td>{dept.DepartmentText}td>
<td>
<div
className="rounded-circle"
style={{
width: "20px",
height: "20px",
backgroundColor: dept.DepartmentColor,
display: "inline-block",
marginRight: "10px",
}}
>div>
td>
tr>
))}
tbody>
table>
div>

{showNestedModal && (
<div
className="modal d-block"
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
>
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">Add Departmenth5>
<button
type="button"
className="close"
onClick={closeModal2}
>
<span aria-hidden="true">×span>
button>
div>
<div className="modal-body">
<div className="form-group">
<label htmlFor="ownerName">Department Namelabel>
<input
type="text"
className="form-control"
id="ownerName"
value={deptName}
onChange={(e) => setdeptName(e.target.value)}
/>
div>
div>
<div className="modal-footer">
<button
type="button"
className="btn btn-secondary"
onClick={closeModal2}
>
Close
button>
<button
type="button"
className="btn btn-primary"
onClick={handleAddOwner}
>
Add
button>
div>
div>
div>
div>
)}
)}
);
};



VS Venkateshwaran Saravanakumar Syncfusion Team July 15, 2023 04:15 PM UTC

Aby,

Q1. Thankyou.Iam doing it but i thought its not proper way to assign the classname of subject to my department.

Since we are not able to get your point, could you please share more details like video or image about your exact requirement that help us to validate further and provide the solution ASAP?


Q2. i have one more query. I know what the issue is but i can't seem to get hold of the solution. so basically there are two Scheduler Components. One is user and one is dept. So i am basically sending the user events which contain department dropdown value into dept one and basically informing the dept that this user is assigned for this dept at this slot etc and i am using useContext hook and basically updating the deptEvents through useState after i get userEvent. So the issue is that when i am using setState method for updating my deptEvents since it is synchoronous it is executed at the end after every thing is done and my deptEvent doesn't show the userEvent data.However if i rerender then it does show me the data on second render since uptil now useState has been executed and data has been set. I wanna show data on first render whenever the component is first rendered. I am using useeffect but to no avail. It is giving me userEvent data but i cannot set it on time Here is my deptSchedular Component. UserSchedular is similar one and i am not inserting here since it isn't needed. it is just updating its own userEvents and i am getting those events through useContext in Dept Schedular Component.

We are unable to fully comprehend your requirement regarding sending events from one scheduler to another scheduler. To assist you better, could you please share an issue replicating the sample? This will enable us to understand the problem and provide you with an appropriate solution.


Q3. Regarding the issue of previous event data being re-rendered every time an event is rendered

We suspect that it could be related to the customizations you have made in the dataBound and eventRendered events. We would suggest reviewing your code in those event handlers to ensure that the updates are being applied correctly. If the issue persists, please provide a simplified sample or a video demonstration showcasing the problem. This would greatly help us understand and resolve the issue.



Regards,
Venkatesh


Loader.
Up arrow icon