Different Between DoubleClick and Edit Button When Editing An Event

This is my code, I have a problem which is when I edit a event, if I click on it and choose Edit button and then I click Save it will log the error like picture 1. But when I double Click the event, It can not set the value to the field I want (Picture 2 and 3). But if I click the Edit button it can set the value to the field I want (Picture 4 and 5) and I can't click the save button, it will log the error in Picture 1. Please help me.

Image_7244_1728287703601Image_4092_1728287840444Image_8417_1728287862530Image_2109_1728288056826
Image_6746_1728288081298

11 Replies 1 reply marked as answer

PH Phan Hu?nh Nh?t Hùng October 7, 2024 08:11 AM UTC


consteventSettings= {
    dataSource: [
      {
        Id: 1,
        Subject: 'Họp nhóm dự án',
        StartTime: newDate(2024, 8, 28, 10, 0),
        EndTime: newDate(2024, 8, 28, 12, 30),
        IsAllDay: false,
        Description: 'Thảo luận dự án và đánh giá tiến độ',
        UserName: ['Alice'],
        RecurrenceRule: 'FREQ=DAILY;INTERVAL=3;UNTIL=20241202T095121Z',
        UserType: "Vệ sinh",


      },
      {
        Id: 2,
        Subject: 'Đánh giá tiến độ',
        StartTime: newDate(2024, 8, 29, 9, 0),
        EndTime: newDate(2024, 8, 29, 10, 0),
        IsAllDay: false,
        Description: 'Tiến hành đánh giá tiến độ công việc',
        RecurrenceRule: '',
        UserName: ['Bob', 'Jack', 'Tom', 'Ashley'],
        UserType: "Điện",
        Place: {
          'Tòa nhà': [{ Id: '1', Name: 'Tòa nhà A' }, { Id: '2', Name: 'Tòa nhà B' }],
          'Phòng': [{ Id: '101', Name: 'Phòng 101' }, { Id: '102', Name: 'Phòng 102' }]
        },
      }
    ],
    fields: {
      Id: 'Id',
      Subject: { name: 'Subject' },
      IsAllDay: { name: 'IsAllDay' },
      StartTime: { name: 'StartTime' },
      EndTime: { name: 'EndTime' },
      RecurrenceRule: { name: 'RecurrenceRule' },
      Description: { name: 'Description' },
      UserName: { name: 'UserName' },
      UserType: { name: 'UserType' },
      Place: { name: 'Place' },
      resourceFields: ['UserType'],
    }
  };
const editorWindowTemplate = (props: any) => {
   
    const [locations, setLocations] = useState(() => {
      if (props.Place && typeof props.Place === 'object') {
        return Object.entries(props.Place).map(([level, rooms]) => ({
          level,
          room: Array.isArray(rooms) ? rooms.map((room: { Id: string, Name: string }) =>
({ Id: room.Id, Name: room.Name })) : []
        }));
      }
      if (props.Place && typeof props.Place === 'string') {
        return Object.entries(JSON.parse(props.Place)).map(([level, rooms]) => ({
          level,
          room: Array.isArray(rooms) ? rooms.map((room: { Id: string, Name: string }) =>
({ Id: room.Id, Name: room.Name })) : []
        }));
      }
      return [{ level: '', room: [] }];
    });
    const [placeObject, setPlaceObject] = useState<Record<string, { Id: string, Name: string }[]>>({});
    const [recurrenceRule, setRecurrenceRule] = useState(props.RecurrenceRule || '');
    const [isAllDay, setIsAllDay] = useState(props.IsAllDay || false);

    const handleIsAllDayChange = (args: any) => {
      setIsAllDay(args.checked);
    };

    const handleRecurrenceChange = (args: any) => {
        const newRecurrenceRule = args.value;
        setRecurrenceRule(newRecurrenceRule);
    };

   
    const handleLocationChange = useCallback((index: number, level: string, rooms: { Id: string; Name: string }[]) => {
      setLocations(prevLocations => {
        const newLocations = prevLocations.map((loc, i) =>
          i === index ? { level, room: rooms } : loc
        );
        return newLocations;
      });
   
      setPlaceObject(prevPlaceObject => {
        const newPlaceObject = { ...prevPlaceObject };
        if (rooms.length > 0) {
          newPlaceObject[level] = rooms;
        } else {
          delete newPlaceObject[level];
        }
     
        return newPlaceObject;
      });
    }, []);
   

    const addLocation = useCallback(() => {
      setLocations(prev => {
        const newLocations = [...prev, { level: '', room: [] }];
       
        return newLocations;
      });
    }, []);

    const removeLocation = useCallback((index: number) => {
      setLocations(prev => {
        const newLocations = prev.filter((_, i) => i !== index);
       
        return newLocations;
      });
    }, []);

    return (
      <Table>
        <TableBody>
          <TableRow>
            <TableCell colSpan={2}>
              <TextBoxComponent
              id="Summary"
              data-name="Subject"
              className="e-field"
              floatLabelType="Always"
              placeholder='Tiêu đề'
              value={props.Subject|| ''} />
            </TableCell>

          </TableRow>
          <TableRow>
            <TableCell colSpan={2}>
              <MultiSelectComponent
                id="EventType"
                dataSource={['Nguyễn Vũ Hoàng', 'Phạm Văn Hiếu', 'Phan Huỳnh Nhật Hùng']}
                fields={{ text: 'UserName', value: 'UserName' }}
                placeholder="Chọn người dùng"
                floatLabelType="Always"
                mode="Box"
                style={{ color: "#000" }}
                showClearButton={true}
                showDropDownIcon={true}
                filterBarPlaceholder="Tìm kiếm người dùng"
                popupHeight="200px"
                value={props.UserName || []}
                className='e-field'
                allowFiltering={true}
                filterType="Contains"
                data-name="UserName"
              />
            </TableCell>
          </TableRow>
          <TableRow>
            <TableCell colSpan={2}>
              <DropDownListComponent
                id="EventType"
                dataSource={['Vệ sinh', 'Điện', 'Âm nhạc']}
                placeholder="Chọn nhóm người"
                floatLabelType="Always"
                popupHeight="200px"
                style={{ color: "#000" }}
                showClearButton={true}
                value={props.UserType || ''}
                className='e-field'
                data-name="UserType"
              />
            </TableCell>
          </TableRow>
          <TableRow>
            <TableCell>
              <DateTimePickerComponent
id="StartTime"
data-name="StartTime"
value={new Date(props.StartTime || props.StartTime)}
format={isAllDay ? 'dd/MM/yy' : 'dd/MM/yy hh:mm a'}
className='e-field' floatLabelType="Always"
placeholder='Ngày bắt đầu'></DateTimePickerComponent >
            </TableCell>
            <TableCell>
              <DateTimePickerComponent
id="EndTime"
data-name="EndTime"
value={new Date(props.EndTime || props.EndTime)}
format={isAllDay ? 'dd/MM/yy' : 'dd/MM/yy hh:mm a'}
className='e-field' floatLabelType="Always"
placeholder='Ngày kết thúc'></DateTimePickerComponent>
            </TableCell>
          </TableRow>
          <TableRow>
            <TableCell colSpan={2}>
              <CheckBoxComponent
                id="IsAllDay"
                checked={isAllDay}
                label="Cả ngày"
                change={handleIsAllDayChange}
                className="e-field"
                data-name="IsAllDay"
              />
            </TableCell>
          </TableRow>
          <TableRow>
            <TableCell colSpan={2}>
              {locations.map((location: any, index: any) => (
                <Box key={index} sx={{ mt: 2 }}>
                  <LocationSelector
                    key={index}
                    index={index}
                    data={location}
                    onChange={handleLocationChange}
                    onRemove={removeLocation} />
                </Box>
              ))}
              <Box
sx={{ mt: 2, display: 'flex', justifyContent: 'center', border: '1px dashed', borderRadius: '5px', cursor: 'pointer' }}
onClick={addLocation}>
                <IconButton color="primary">
                  <AddIcon />
                </IconButton>
              </Box>
              <ButtonComponent onClick={() => console.log(JSON.stringify(placeObject))}>Log Place</ButtonComponent>
              <input type="hidden" className="e-field" data-name="Place" value={JSON.stringify(placeObject)} />
            </TableCell>
          </TableRow>
          <TableRow>
            <TableCell colSpan={2}>
              <RecurrenceEditorComponent
                id='RecurrenceRule'
                value={recurrenceRule}
                change={handleRecurrenceChange}
                locale='vi'
              />
              <ButtonComponent onClick={() => console.log(recurrenceRule)}>Log Recurrence Rule</ButtonComponent>
              <input
                type="hidden"
                data-name="RecurrenceRule"
                name="RecurrenceRule"
                value={recurrenceRule}
                className="e-field"
              />
            </TableCell>
          </TableRow>
          <TableRow>
            <TableCell colSpan={2}>
              <TextAreaComponent
                id="Description"
                name="Description"
                data-name='Description'
                placeholder="Nhập mô tả"
                resizeMode='None'
                floatLabelType="Always"
                className="e-field"
                style={{ width: '100%' }}
                value={props.Description || ''}
              />
            </TableCell>
          </TableRow>
        </TableBody>
      </Table>
    )
  }
<ScheduleComponent
key={calendars.map(cal => cal.id).join(',')}
width='100%'
height='550px'
dateFormat='dd-MM-yyyy'
selectedDate={new Date(2024, 8, 26)}
eventSettings={{ ...currentEventSettings, template: eventTemplate, enableTooltip: true, tooltipTemplate: toolTipTemplate}}
ref={scheduleObj}
rowAutoHeight={true}  
enableAdaptiveUI={true}
locale='vi'
cssClass="schedule-customization"
quickInfoTemplates={quickInfoTemplates}
actionComplete={onActionComplete}
editorTemplate={editorWindowTemplate}
popupOpen={onPopupOpen}>
              <ViewsDirective>
                <ViewDirective option="Day" interval={5}></ViewDirective>
                <ViewDirective option="Month" ></ViewDirective>
                <ViewDirective option="Week" isSelected={true}></ViewDirective>
                <ViewDirective option="TimelineDay" ></ViewDirective>
                <ViewDirective option="TimelineMonth"></ViewDirective>
                <ViewDirective option="Agenda"></ViewDirective>
              </ViewsDirective>
              <ResourcesDirective>
                <ResourceDirective
                  field='UserType'
                  title='Nhóm người dùng'
                  name='UserTypes'
                  allowMultiple={true}
                  dataSource={calendars}
                  textField='text'
                  idField='text'
                  colorField='color'
                />
              </ResourcesDirective>
              <Inject services={[Week, Day, Month, Agenda, Resize, DragAndDrop, RecurrenceEditor]} />
            </ScheduleComponent>




VR Vijay Ravi Syncfusion Team October 8, 2024 03:48 PM UTC

Hi Phan,
 

we have prepared Schedule sample using the shared details. In our testing We were unable to replicate your mentioned issue. So, we kindly request that you provide the following details. This information will help us better understand the problem and assist you more effectively in resolving it.

 

  • Could you share the sample replicating the issue?
  • Replicate the issue in our below shared sample.
  • Could you share the entire schedule related code snippets,
  • Could you share the issue video demo

 

Sample link: https://stackblitz.com/edit/react-mqqa7p-52f72s?file=index.js

please get back with requested details to us if you need any further assistance


Regards,

Vijay



PH Phan Hu?nh Nh?t Hùng replied to Vijay Ravi October 9, 2024 04:54 AM UTC

Hi Vijay, thank you for your reply, the problem in the video I post is when I double click to edit an appointment. The EditorWindowTemplate cannot get the value of the Subject field and the Place Field and it can save. But when I click on edit button, It can get all the value and set for my field and I can't save, it returns an error.

Here is my source code, it quite big so I upload on my drive and here is the link: https://drive.google.com/file/d/1OITQYENzYAw-RuEuQduSxgF4R6KulU37/view?usp=sharing


P.S: I think it relates to the focus on appointment when we click


Attachment: Video_7d2905f.rar



VR Vijay Ravi Syncfusion Team October 9, 2024 03:24 PM UTC

Hi Phan ,
 

We have thoroughly reviewed and validated your project. To address the issue you've described, please note that while you have customized the function for the "Edit" button click, you need to pass the eventData to the "Save" button and call the Scheduler’s saveEvent method. This will ensure that the changes are properly saved.
 

For your convenience, we have provided a code snippet below that demonstrates this approach. Additionally, please refer to the modified sample for further clarification. We recommend trying this out in your project.

[page.tsx]
 

 

const buttonClickActions = useCallback((action: string) => {

    let eventData: any = {};

    let actionType: CurrentAction = "Add";

    const getSlotData = () => {

      const selectedElements = scheduleObj.current?.getSelectedElements();

      if (!selectedElements) return null;

      const cellDetails = scheduleObj.current?.getCellDetails(selectedElements);

      if (!cellDetails) return null;

      const formData = scheduleObj.current?.eventWindow.getObjectFromFormData("e-quick-popup-wrapper");

      if (!formData) return null;

      const addObj: any = {};

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

      addObj.Subject = formData.Subject && formData.Subject.length > 0 ? formData.Subject : "Add title";

      addObj.StartTime = new Date(cellDetails.startTime);

      addObj.EndTime = new Date(cellDetails.endTime);

      return addObj;

    };

 

    switch (action) {

      case "add":

        eventData = getSlotData();

        if (eventData) scheduleObj.current?.addEvent(eventData);

        break;

      case "edit":

        eventData = scheduleObj.current?.activeEventData?.event;

        scheduleObj.current?.saveEvent(eventData);

}


Don't hesitate to get in touch if you require further help or more information.

Regards,

Vijay


Attachment: modifying_testproject_fda6d042.zip


PH Phan Hu?nh Nh?t Hùng replied to Vijay Ravi October 11, 2024 06:57 AM UTC

Thank you for your support, it works well. But I have some problems, please give me the answer please:


  1. How can I disable the double click action on edit an appointment but still allow double click in a cell to create an appointment.
  2. When edit an appointment which has a series, I want to let the people edit whole series not a single appointment in the series.
  3. When you edit an entire series, it will cause the same error with the above problem and if you put the saveEvent in case "edit" it will call your actionComplete when you click on your edit button (I'm not click on the save button).

Sorry for my bad English. I hope you will give me the answer as soon as possible



VR Vijay Ravi Syncfusion Team October 11, 2024 02:48 PM UTC

Hi Phan,

Query 1: How can I disable the double click action on edit an appointment but still allow double click in a cell to create an appointment.
 

We recommend binding the schedule eventDoubleClick event and setting args.cancel = true to prevent or disable the edit action when double-clicking an appointment. Please refer to the API documentation and sample provided below for further reference.

eventDoubleClick event: https://ej2.syncfusion.com/react/documentation/api/schedule/#eventdoubleclick

[page.tsx]
 

const OnEventDoubleClick = (args: EventClickArgs) => {

   args.cancel = true;

}

<ScheduleComponent  eventDoubleClick={OnEventDoubleClick}>

</ScheduleComponent>


Query 2: When edit an appointment which has a series, I want to let the people edit whole series not a single appointment in the series.

When you click an event, the edit event popup opens to allow editing of the entire series. To programmatically click the "Edit Series" button for a recurring appointment, you can use the querySelector method to locate the button and trigger a click event within the onPopupOpen function. Additionally, setting args.cancel = true will prevent the quick info popup from opening when an appointment is clicked.
 

[page.tsx]
 

const onpopupOpen = (args: PopupOpenEventArgs) => {

    console.log(args.type);

    if (args.type === "QuickInfo" && args.data && args.data.RecurrenceRule) {

      args.cancel = true;

      const editSeriesButton = document.querySelector('.e-quick-popup-wrapper .e-edit-series');

      if (editSeriesButton) {

        // Programmatically click the "Edit Series" button

        (editSeriesButton as HTMLElement).click();

      }

    }

}


<ScheduleComponent  popupopen={onpopupOpen }>

</ScheduleComponent>


Query 3: When you edit an entire series, it will cause the same error with the above problem and if you put the saveEvent in case "edit" it will call your actionComplete when you click on your edit button (I'm not click on the save button).

We have modified the code to use the popupOpen event, which programmatically clicks the "Edit Series" button for recurring appointments and prevents the quick info popup from opening. Now, when you click on an appointment, the event editor will open directly, allowing you to make changes and save them, which will apply to the entire series.

Don't hesitate to get in touch if you require further help or more information.

Regards,

Vijay


Attachment: updated_testproject_32da01aa.zip


PH Phan Hu?nh Nh?t Hùng replied to Vijay Ravi October 16, 2024 04:32 AM UTC

Hello Vijay, I have received your information and tested your code. It had some problems:

  1. If you click on edit an appointment, It will automatically call your onActionComplete function even if you haven't clicked the save button.
  2. If you edit an appointment which doesn't have any RecurrenceRule to have a RecurrenceRule, It is not apply any change to the RecurrenceRule props of that appointment.


VR Vijay Ravi Syncfusion Team October 22, 2024 01:56 PM UTC

Hi Phan,


We consider your reported query with "Script error occur while editing as existing event" as a bug and logged the defect report. The fix for this defect will be included in our upcoming weekly patch release, which is expected to be rolled out by the November 12, 2024. You can track the status of the fix at the following link:


Feedback link: https://www.syncfusion.com/feedback/62440/script-error-occur-while-editing-as-existing-event


Disclaimer: Inclusion of this solution in the weekly release may change due to other factors including but not limited to QA checks and works reprioritization.


Regards,

Vijay


Marked as answer

PH Phan Hu?nh Nh?t Hùng replied to Adrian Scott November 6, 2024 03:24 PM UTC

Thank you for your reply. I have one remaining problem. I want to handle the click action on the add button when it is in the adaptive UI mode. How can I do that



Image_3745_1730906592229



VR Vijay Ravi Syncfusion Team November 8, 2024 09:52 AM UTC

Hi Phan,


We have created a new foum for the last reported issue. Please follow below ticket for further assistance.

Forum link: I want to handle the click action on the add button when it is in the adaptive UI mode - from 194681 | React - EJ 2 Forums | Syncfusion

Regards,

Vijay



VR Vijay Ravi Syncfusion Team November 22, 2024 04:40 AM UTC

Hi Phan,
 

We are glad to announce that our weekly release (V27.2.3) has been rolled out successfully. The fix for the issue has been included in our weekly release(27.2.3). Upgrade to the latest version to resolve the issue.


Release notes: https://ej2.syncfusion.com/react/documentation/release-notes/27.2.3?type=all#schedule

Feedback: Script error occur while editing an existing event in Scheduler component in React | Feedback Portal

Sample link: P3rl5s (forked) - StackBlitz


Root Cause: In this, the issue is that when the editor template is opened, the recurrence editor is re-rendered. The instance of the recurrence editor is stored in a variable, which is used when the save button is clicked. However, when using the tooltip template, the reset template function is called, causing the editor template to be re-rendered. This re-rendering destroys the existing recurrence editor instance and creates a new one, which is not stored in the variable. As a result, when the save button is clicked, the old instance is null, leading to an error.
 

The main cause of this issue is that resetting the tooltip template triggers the re-rendering of the editor template. Especially in React platform


We thank you for your support and appreciate your patience in waiting for this release. Please get in touch with us if you would require any further assistance.


Regards,
Vijay


Loader.
Up arrow icon