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
close icon

Add custom button to Event Editor in Scheduler

Hi,

I would like to add custom buttons to the footer of the event editor. How can I do that?

(I found a similar question with a support answer, however I am not able to convert that solution to React TypeScript... I'm referring to https://www.syncfusion.com/forums/160475/add-custom-button.)

Thanks.


12 Replies 1 reply marked as answer

HB Hareesh Balasubramanian Syncfusion Team June 29, 2021 06:53 AM UTC

Hi Laurin, 

Greetings from Syncfusion Support..! 

We have prepared a sample based on your shared query “need to add custom button in the editor window of the scheduler” using the popupOpen event of the scheduler, which can be viewed from the following link. 


  onPopupOpen(args) { 
    if (args.type === 'Editor') { 
      if (this.flag) { 
        let dialogObj = args.element.ej2_instances[0]; 
        let buttons = dialogObj.buttons; 
        buttons.push({ 
          buttonModel: { content: 'Alert', isPrimary: true }, 
          click: this.alert.bind(this) 
        }); 
        dialogObj.setProperties({ buttons: buttons }); 
        this.flag = false; 
      } 
    } 
  } 

Kindly try the above solution and get back to us if you need any further assistance. 

Regards, 
Hareesh 


Marked as answer

LS Laurin S July 8, 2021 03:41 PM UTC

Is there also the possibility to add a DropDownMenu-Button and a Split-Button?



VD Vinitha Devi Murugan Syncfusion Team July 9, 2021 02:29 PM UTC

Hi Laurin, 
  
Thanks for your update. 
  
We have prepared a sample based on your shared query “need to add a DropDownMenu-Button and a Split-Button in the editor window of the scheduler” using the editorTemplate option of the Scheduler with some CSS customization, which can be viewed from the following link.  
  
  
editorTemplate(props) { 
    return props !== undefined ? ( 
      <div> 
        .… 
        <div className="footer-buttons"> 
          <span> 
            <DropDownButtonComponent items={this.items}> 
              Profile 
            </DropDownButtonComponent> 
          </span> 
          <span> 
            <SplitButtonComponent items={this.items} content="Paste" /> 
          </span> 
        </div> 
      ….. 
      <div /> 
    ); 
  } 
 
CSS  
.footer-buttons span { 
  padding5px; 
} 
.footer-buttons { 
  positionfixed; 
  margin20px 0; 
} 
 
 
Kindly try with the above sample and get back to us if you need any further assistance 
  
Regards, 
Vinitha 



LS Laurin S July 20, 2021 08:44 AM UTC

Thanks for the quick reply.

Just another thing:

I wanted to modify/use the footerTemplate of the editor, however, the following piece of code is not working, any idea?


onPopupOpen(args) {
    if (args.type === 'Editor') {
      if (this.flag) {
        let dialogObj = args.element.ej2_instances[0];
        let footerTemplate = () => {
          return (
            <div>
              <ButtonComponent>Save</ButtonComponent>
              <ButtonComponent>Save &amp; Print</ButtonComponent>
              <ButtonComponent>Cancel</ButtonComponent>
            </div>
          );
        };
        dialogObj.footerTemplate = footerTemplate//--> NOT WORKING
        dialogObj.setProperties({ footerTemplate: footerTemplate }); //--> NOT WORKING
        this.flag = false;
      }
    }
  }


VD Vinitha Devi Murugan Syncfusion Team July 21, 2021 09:25 AM UTC

Hi Laurin, 
 
Thanks for your update. 
 
We have validated your reported query and achieved your requirement with the help of below code and same can be available in below link. 
 
 
  onPopupOpen(args) { 
    if (args.type === 'Editor') { 
      if (this.flag) { 
        let dialogObj = args.element.ej2_instances[0]; 
        dialogObj.footerTemplate = 
          '<input id="save" type="button" value="Save" /> <input id="print" type="button" value="Print" /> <input id="cancel" type="button" value="Cancel" />'; 
        dialogObj.dataBind(); 
        let saveButtonObj = new Button(); 
        saveButtonObj.appendTo('#save'); 
        saveButtonObj.element.onclick = () => { 
          this.eventAdd(); 
        }; 
        let printButtonObj = new Button(); 
        printButtonObj.appendTo('#print'); 
        printButtonObj.element.onclick = () => { 
          alert('Print button called'); 
        }; 
        let cancelButtonObj = new Button(); 
        cancelButtonObj.appendTo('#cancel'); 
        cancelButtonObj.element.onclick = () => { 
          this.dialogClose(); 
        }; 
        this.flag = false; 
      } 
    } 
  } 
 
Kindly try with the above sample and get back to us if you need any further assistance 
 
Regards, 
Vinitha 



LS Laurin S July 27, 2021 03:35 PM UTC

Thanks for the quick reply, the provided solution worked.


Another question:

How can I save the modifications of the event, when using custom buttons. Is there a method of the scheduler to save the modified event? In the documentation is written to use the "popupClose" event, however the argument "data" is undefined after closing the editor dialog in the event. 

(Do I really have to read each value from each input-field by using something like document.getElementById("..").value? Is there no solution to get all values from each input field, like the "normal" save button is doing?)

I've attached an example...


Attachment: scheduleeditorwindowwithfootertemplatepmf8rg_a8ee9703.zip


VD Vinitha Devi Murugan Syncfusion Team July 28, 2021 08:37 AM UTC

Hi Laurin, 
 
Greetings from Syncfusion Support. 
 
We have validated your reported query “How can I save the modifications of the event, when using custom buttons. Is there a method of the scheduler to save the modified event” and achieved your requirement by using below code. We have prepared below sample for your reference.  
 
 
 eventAdd(e) { 
    // Method to add new event in Scheduler 
    const data = this.scheduleObj.getCellDetails( 
      this.scheduleObj.getSelectedElements() 
    ); 
    const eventData = this.scheduleObj.eventWindow.getObjectFromFormData( 
      'e-schedule-dialog' 
    ); 
    this.scheduleObj.eventWindow.convertToEventData(dataeventData); 
    eventData.Id = this.scheduleObj.eventBase.getEventMaxID() + 1; 
    this.scheduleObj.addEvent(eventData); 
    this.dialogClose(); 
  } 
  eventDelete(e) { 
    // Method to delete selected event 
    const eventData = this.scheduleObj.activeEventData.event; 
    this.scheduleObj.deleteEvent(eventData); 
    this.dialogClose(); 
  } 
  editEvent(e) { 
    // Method to edit event in Scheduler 
    const eventData = this.scheduleObj.eventWindow.getObjectFromFormData( 
      'e-schedule-dialog' 
    ); 
    eventData.Id = this.currentEvent.Id; 
    this.scheduleObj.saveEvent(eventData); 
    this.dialogClose(); 
  } 
  dialogClose() { 
    // Method to close 
    let dialogObj = document.querySelector('.e-schedule-dialog') 
      .ej2_instances[0]; 
    dialogObj.hide(); 
  } 
  onPopupOpen(args) { 
    if (args.type === 'Editor') { 
      if (this.flag) { 
        let dialogObj = args.element.ej2_instances[0]; 
        dialogObj.footerTemplate = 
          '<input id="add" type="button" value="Add" /><input id="save" type="button" value="Save" /> <input id="print" type="button" value="Print" /> <input id="delete" type="button" value="Delete" /> <input id="cancel" type="button" value="Cancel" />'; 
        dialogObj.dataBind(); 
        let addButtonObj = new Button(); 
        addButtonObj.appendTo('#add'); 
        addButtonObj.element.onclick = () => { 
          this.eventAdd(); 
        }; 
        let saveButtonObj = new Button(); 
        saveButtonObj.appendTo('#save'); 
        saveButtonObj.element.onclick = () => { 
          this.editEvent(); 
        }; 
        let printButtonObj = new Button(); 
        printButtonObj.appendTo('#print'); 
        printButtonObj.element.onclick = () => { 
          alert('Print button called'); 
        }; 
        let deleteButtonObj = new Button(); 
        deleteButtonObj.appendTo('#delete'); 
        deleteButtonObj.element.onclick = () => { 
          this.eventDelete(); 
        }; 
        let cancelButtonObj = new Button(); 
        cancelButtonObj.appendTo('#cancel'); 
        cancelButtonObj.element.onclick = () => { 
          this.dialogClose(); 
        }; 
        this.flag = false; 
      } 
      if (!this.flag) { 
        var isApp = args.target.classList.contains('e-appointment'); 
        if (isApp) { 
          this.currentEvent = this.scheduleObj.getEventDetails(args.target); 
        } 
        args.element.querySelector('#save').style.display = isApp ? '' : 'none'; 
        args.element.querySelector('#delete').style.display = isApp 
          ? '' 
          : 'none'; 
        args.element.querySelector('#add').style.display = isApp ? 'none' : ''; 
      } 
    } 
  } 
 
Kindly try with the above sample and get back to us if you need any further assistance 
 
Regards, 
Vinitha 



LS Laurin S July 28, 2021 03:05 PM UTC

Thanks for the reply, the provided solutions works. However, there is another issue:


When opening the event editor a 2nd time, an error appears:  Cannot read property 'className' of null. 
(Just edit an appointment in the provided example, save it and open another one, then the error appears)


Thanks.



LS Laurin S July 28, 2021 03:47 PM UTC

Just another thing:

Any ideas why a multiline TextBox in combination with the className="e-field" fires the following error: 

Uncaught DOMException: Failed to execute 'closest' on 'Element': '.' is not a valid selector.


I'm using the following piece of code to add the multiline TextBoxComponent to my event editor template:




VD Vinitha Devi Murugan Syncfusion Team July 29, 2021 08:30 AM UTC

Hi Laurin, 
 
Thanks for your update. 
 
Please find the below modified sample for all your queries 
 
 
Q1: We could reproduce the reported issue in our previously shared sample. On validating it, the reported issue is due to you have missed to add cssClass for delete button, which causes the issue on edit click. To overcome this we suggest you to use below code in your sample for the same we have modified your shared code. 
 
 let deleteButtonObj = new Button({ cssClass: 'e-event-delete' }); 
        deleteButtonObj.appendTo('#delete'); 
        deleteButtonObj.element.onclick = () => { 
          this.eventDelete(); 
        }; 
 
Q2:  We have validated your reported query at our end and we could reproduce the reported issue. The reported issue was due to when we click the save button, we internally process some components(Dropdownlist, multiselect, input etc..) and save the field which contains ‘e-field’ class to the scheduler. For TextBoxComponent field we doesn’t handle it in source end. So we need to manually process the field using actionBegin event like below and same can be available in above link. 
 
<tr> 
<td className="e-textlabel">Address</td> 
<td style={colspan: '4' }}> 
  <TextBoxComponent 
    id="default" 
    multiline={true} 
    data-name="Address" 
    floatLabelType="Auto" 
    placeholder="Enter your address" 
    ref={scope => { 
      this.textareaObj = scope; 
    }} 
    value={props.Address} 
  /> 
</td> 
</tr> 
 
  onActionBegin(args) { 
      //Here we manually processed Textbox component field 
      if (args.requestType === 'eventCreate') { 
        args.data[0].Address = this.textareaObj.value; 
      } 
      if (args.requestType == 'eventChange') { 
        args.data.Address = this.textareaObj.value; 
    } 
  } 
 
Kindly try with the above sample and get back to us if you need any further assistance 
 
Regards, 
Vinitha 



LS Laurin S July 29, 2021 12:33 PM UTC

Hi Vinitha, thanks for your reply. Please find below my answers:

Q1) What if I don't want to have a delete-button?

Q2) Is there no other "automatic" way to fetch the data from the multiline-textbox, like for all other components? I.e. why can't we use also the "e-field" class data-fetching-method for multine-textboxes?

Thanks.



VD Vinitha Devi Murugan Syncfusion Team July 30, 2021 09:37 AM UTC

Hi Laurin, 
 
Thanks for your update. 
 
Q1: In our Scheduler by default we don’t have a footer template option to customize the editor window footer. To achieve your requirement we manually customized editor footer at sample end. For this customization have this restrictions to need `e-event-delete` button in sample end to avoid script error while editing. If you don’t want to have delete button in footer you can hide it by making use below CSS and maintain delete button as dummy button to avoid script error while editing. 
 
 
  onPopupOpen(args) { 
    if (args.type === 'Editor') { 
…. 
        args.element.querySelector('#delete').style.display = 'none'; 
…. 
      } 
    } 
  } 
 
Q2: With our editorTemplate option you can use customize the editor window with any of third-party components or Syncfusion components. So which is difficult to process all the fields at source end. So as  stated in last update in our source end we internally processed some syncfusion components(Dropdownlist, multiselect, input etc..) and save the field which contains ‘e-field’ class. Other components we need to manually process it at sample end. 
 
Kindly try with the above solution and get back to us if you need any further assistance 
 
Regards, 
Vinitha 


Loader.
Live Chat Icon For mobile
Up arrow icon