How to display modal popup with a form inside a Lightning component

  • I need to display a modal popup when i click on event in my calendar with editing details of that event, Please any one suggest me the right way to display popup, i would like to call a "Event Click" function of full calendar to display popup.

    Component

    <aura:component controller="CalendarCtrl" implements="force:appHostable">
        <ltng:require scripts="/resource/Bootstrap_ltng/js/jquery-2.1.4.min.js,/resource/FullCalendar/fullcalendar.min.js,/resource/FullCalendar/fullcalendar.js, /resource/FullCalendar/lib/js/moment.min.js, /resource/FullCalendar/lib/js/jquery-ui.min.js,/resource/FullCalendar/lib/js/multiSelect/jquery.multiselect.js,/resource/FullCalendar/lib/js/multiSelect/jquery.multiselect.filter.js" styles="/resource/BootStrap1/css/bootstrap.min.css,/resource/FullCalendar/fullcalendar.min.css,/resource/FullCalendar/lib/css/multiselect/jquery.multiselect.css,/resource/FullCalendar/lib/css/multiselect/jquery.multiselect.filter.css,/resource/FullCalendar/lib/themes/smoothness/jquery-ui.css" afterScriptsLoaded="{!c.init}" />
        <ltng:require styles="/resource/slds090/assets/styles/salesforce-lightning-design-system.min.css"/>
        <aura:registerEvent name="btnClick" type="c:ButtonClicked" />
        <aura:handler name="btnClick" event="c:ButtonClicked" action="{!c.openNewEventDialog}" />
        <aura:attribute name="startDateTime" type="DateTime" />
        <aura:attribute name="endDateTime" type="DateTime" />
        <aura:attribute name="dueDateTime" type="DateTime" />
        <aura:attribute name="subject" type="String" />
        <aura:attribute name="view" type="String" description="Use this variable to fetch my records or team records " default="My View" />
        <aura:attribute name="EventTypes" type="Calendar_Settings__c[]" description="Event types" default="" />
        <aura:attribute name="settings" type="Calendar_Settings__c[]" description="calendar settings" />
        <div class="container-fluid">
            <div class="row">
                <div aura:id="calendar-filter" class="filters col-xs-12 col-sm-12 col-md-12 col-lg-12" style="padding:0px;">
                <div class="row">
                    <div class="col-md-4 col-sm-4 colxs-12">
                    <div id="viewAs" class="left-radio-filter panel panel-primary">
                        <div class="filter-view-header panel-heading"><span id="view-header">View As</span></div>
                        <div id="My_view" class="viewAs">
                            <ui:inputRadio aura:id="myview" value="" label="My View" name="view" click="{!c.setViewType}" labelClass="left-filter-label" />
                        </div>
                        <div id="Team_view" class="viewAs">
                            <ui:inputRadio aura:id="teamview" value="" label="Team View" name="view" click="{!c.setViewType}" labelClass="left-filter-label" />
                        </div>
                    </div>
                        </div>
    
                 <div class="col-md-8 col-sm-8 col-xs-12" style="padding-left:0px;">   
                    <div id="filter-multiselect" class="left-multi-filter panel panel-primary">
                        <div class="panel-heading">
                            <span>Filters</span>
                        </div>
                        <aura:iteration items="{!v.EventTypes}" var="filter">
                            <div aura:id="inputcheckbox" class="inputcheckbox">
                                <ui:inputCheckbox click="{!c.filterEvents}" label="{!filter.Name}" text="{!filter.RecordTypeName__c}" aura:id="filteroption" labelClass="left-filter-label"> </ui:inputCheckbox>
                            </div>
                        </aura:iteration>
                    </div>
                     </div>
                </div>
                </div>    
                <div class="calendar col-md-12 " style="padding:0px">
                    <div id="calendar" style="margin:0px;">
                    </div>
                </div>
                <div aura:id="newEvent-dialog-form" title="New Event header" class="dialogform">
                    <form class="container">
                        <div class="row">
                            <fieldSet class="form-group col-md-4">
                                <label for="eSubject">Subject</label>
                                <ui:inputText aura:id="eSubject" value="{!v.subject}" class="form-control" />
                            </fieldSet>
                            <fieldSet class="form-group col-md-4">
                                <!-- <label for="eSubject">Event Type</label> -->
                                <ui:inputSelect label="Event Type" class="form-control" aura:id="eventType">
                                    <aura:iteration items="{!v.EventTypes}" var="filter">
                                        <ui:inputSelectOption text="{!filter.Id}" label="{!filter.RecordTypeName__c}" />
                                    </aura:iteration>
                                </ui:inputSelect>
                            </fieldSet>
                        </div>
                        <div class="row">
                            <fieldSet class="form-group col-md-4">
                                <label for="eDuteDate">Due Date</label>
                                <ui:inputDateTime aura:id="eDueDate" value="{!v.dueDateTime}" class="form-control" />
                            </fieldSet>
                            <fieldSet class="form-group col-md-4">
                                <ui:inputDateTime label="Start Date" aura:id="eStart" value="{!v.startDateTime}" class="form-control" />
                            </fieldSet>
                        </div>
                        <div class="row">
                            <fieldSet class="form-group col-md-4">
                                <ui:inputDateTime label="End Date" aura:id="eEndDate" value="{!v.endDateTime}" class="form-control" />
                            </fieldSet>
                        </div>
                        <ui:button label="Save" press="{!c.newEvent}" class="btn btn-primary" />
                    </form>
                </div>
            </div>
             </div>
    </aura:component>
    

    Client side Controller

     ({
        init : function(cmp, event, helper) {
    
             console.log('init');
            var eventSelect ="<div></div>"
                //cmp.find("multiselect").getElement();
    
           //$("select").multiselect();
            console.log(eventSelect);
    
        helper.setEventTypes(cmp,event);
    
        $('#calendar').fullCalendar({
            // put your options and callbacks here
            customButtons: {
            /*     newEventButton: {
                    text: 'New Event',
                    click: function(){
    
                    var btnClick = cmp.getEvent("btnClick");
    
                        btnClick.setParams({
    
                            "type":"newEvent"
    
                        });
                        btnClick.fire();
    
                    }  
                 } */
    
             },
            aspectRatio: 2,
            height: 600,
            header: {
                  left: 'prev,next today,newEventButton',
                  center: 'title',
                  right: 'month,agendaWeek,agendaDay'
           },
            editable: true,
            events: $A.getCallback(function(start, end, timezone, callback){
    
                var cSettings = cmp.get("v.settings");     
                var action = cmp.get("c.getEvents");
                var viewType = cmp.get("v.view");
                var cEvents = {};
                var Events = [];
    
                console.log('####settings: '+  cSettings);
                console.log('####timeZone: '+ timezone);
               // console.log('end: '+  end);
                action.setParams({
    
                    "StartDate": start,
                    "EndDate" : end,
                    "settings": cSettings,
                    "viewType": viewType
                });
                 action.setCallback(this,function(r){  
    
                   var state = r.getState();
    
                  // console.log('State: '+ state);
    
                   if(state =='SUCCESS'){    
    
                    cEvents = JSON.parse(r.getReturnValue());
    
                  /*  console.log('jSon String is : ')
                    console.log(r.getReturnValue());
                    console.log('cEventsources are: ')
                    console.log(cEvents); */
    
                       callback(cEvents);
    
                   }
    
                 })
    
               $A.enqueueAction(action);
    
            }  //events function 
            ),
    
            eventClick: function(calEvent, jsEvent, view) {
    
              // window.open(calEvent.url, '_blank');
               //$.popupWindow(calEvent.url, { height: 500, width: 1000 });
                //console.log('----Hi-- '+calEvent.url);
                //alert(calEvent.url);
                //return false;
                $("#account-dialog").show('fade');
                return false;
    
            },
    
    
    
        });
    
    
        },
    
        newEvent : function(cmp,event,helper){
    
            var v_event = {};
            v_event.StartDateTime= cmp.get("v.startDateTime");
            v_event.EndDateTime= cmp.get("v.endDateTime");
             v_event.ActivityDate= cmp.get("v.dueDateTime");
            v_event.Subject= cmp.get("v.subject");
            var setting_mdt={};
    
            var eventType = cmp.get("v.EventTypes");
    
            var settingId =  cmp.find("eventType").get("v.value");
    
            for(i in eventType){
    
    
                if(eventType[i].Id==settingId){
    
                    setting_mdt = eventType[i]; 
    
                    console.log('EventType is');
                    console.log(setting_mdt);
                    console.log(setting_mdt.Subject__c);
    
                    console.log(setting_mdt.Id);
    
                }
            }
    
    
    
            helper.createEvent(cmp,v_event,setting_mdt,function(r){
    
                var state = r.getState(); 
    
                var toastEvent = $A.get("e.force:showToast");
    
                if(toastEvent){
    
                  toastEvent.setParams({
    
                        "title": "Success !",
                        "message": "Event has been successfully created."
                    });
    
                }
                else{
    
                    console.log('Event creation Status is: '+state);
    
                    if(state=="SUCCESS"){
    
                        dialog.dialog("close");
                    }
    
                    $('#calendar').fullCalendar('refetchEvents');
                }
    
    
            });
    
           // console.log('closing the dialog');
    
        },
        updateEvent : function(cEvent,helper){
    
            console.log('Event in update method');
            console.log(cEvent);
    
        }, 
    
        openNewEventDialog : function(cmp,event,helper){
    
            console.log('New Event dialog');
    
            var eventDialog = cmp.find('newEvent-dialog-form'); 
    
    
    
            dialog = $( "[data-aura-rendered-by=\'"+eventDialog.getGlobalId()+"\']" ).dialog({
    
                autoOpen: false,
                modal: true,
                draggable: true,
                height: 600,
                width: 900,
                resizable: true,
                position: { my:'center', at:'center'},
    
    
                 buttons: {
    
                Cancel: function () {
                   $(this).dialog('close');
                  }
                },
                close: function() {
    
                    dialog.dialog("close");
                }
        });
    
    
              dialog.dialog( "open" );
    
        },
    
    
    
    })
    

    This is my VF page using lightning component

    enter image description here

    And I would like to display popup like this,

    enter image description here

    Please any one suggest me the better idea,

  • Bagpiper001

    Bagpiper001 Correct answer

    5 years ago

    I had a similar challenge to build, but with a button. I managed to succesfully build a popup like you want, but I'm not 100% sure if it works in your code, but it's definitely worth a try.

    Component

    In your component you need two extra div's:

    <div class="slds">
        <div aria-hidden="true" role="dialog" class="slds-modal slds-modal--prompt slds-fade-in-hide" aura:id="modaldialog">
            <div class="slds-modal__container">
                <div class="slds-modal__header slds-theme--info">
                    <button class="slds-button slds-button--icon-inverse slds-notify__close" onclick="{!c.hidePopup}">
                        <c:svg aria-hidden="false" class="slds-button__icon slds-button__icon--large" xlinkHref="/resource/SLDS105/assets/icons/action-sprite/svg/symbols.svg#close">
                        </c:svg>
                        <span class="slds-assistive-text">Close</span>
                    </button>
                    <h2 class="slds-text-heading--medium">Your Title</h2>
                </div>
                <div class="slds-modal__content slds-p-around--medium">
                    <div>
                        <p>{!v.body}</p>
                    </div>
                </div>
            </div>
        </div>
    </div>
    

    This div is a hidden div (slds-fade-in-hide does that for you) which will display your form. The second div will display a dark background:

    <div class="slds-backdrop slds-backdrop--hide" aura:id="backdrop">
    </div>
    

    Controller

    I assume that you have a controller to render your form, and that this form is a different component. If not, you should consider building it, as it's really easy.

    Your helper class should look like this:

    function_name :  function(component, event, helper){
    //called on clicking your button
    //run your form render code after that, run the following lines
    helper.showPopupHelper(component, 'modaldialog', 'slds-fade-in-');
    helper.showPopupHelper(component,'backdrop','slds-backdrop--');
    }
    

    You'll also need a function to drop the screen (on cancel for example) as you can see in my component example, I called it hidePopup, this is what's in it:

    helper.hidePopupHelper(component, 'modaldialog', 'slds-fade-in-');
    helper.hidePopupHelper(component, 'backdrop', 'slds-backdrop--');
    

    Helper

    You'll need a couple of methods here:

    1. The method to call the form component, I assume you know how to do this. The only thing you have to do here is put that component in v.body like this component.set("{!v.body}", component);
    2. the showPopupHelper shows the correct popup

          showPopupHelper: function(component, componentId, className){
              var modal = component.find(componentId);
              $A.util.removeClass(modal, className + 'hide');
              $A.util.addClass(modal, className + 'open');
          },
      
    3. the hidePopupHelper hides it when done and, because I use this popup for multiple components, it empties the body, so that next time you'll click it, you don't get the old body first.

          hidePopupHelper: function(component, componentId, className){
              var modal = component.find(componentId);
              $A.util.addClass(modal, className+'hide');
              $A.util.removeClass(modal, className+'open');
              component.set("v.body", "");
          },
      

    I hope it's a bit clear for you, good luck!

    Thanks for the solution.. Exactly what i am looking for. And i have changed my existing component into your aproach and worked like a charm. thank you so much!

    Nice! I'm glad it worked :)

    What's the key to show that modal. I am open document page https://www.lightningdesignsystem.com/components/modals/#overview, copy code to my file, and don't know how to make it work. I just want to see a working example.

    Hey @Stiger, you can do that via a button which calls some javascript in your helper class, which assigns your component to v.body, and then call the helper.showPopupHelper, which I showed in my answer. Good luck!

    Thanks @Bagpiper001, I found it, it have to put inside `.slds` class. I miss that piece. Thanks

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM