Search code examples
javascriptajaxcallbackfullcalendartapestry

Tapestry javascript deferredZoneUpdate method of zoneManager callback function


I make a fullcalendar in my tapestry 5.4 web page.

When I make a new Event or I click an existing event, the fullcalendar's method is called (select or eventClick). In these methods tapestry js method is called (zoneManager.deferredZoneUpdate("formZone", listenerURIWithValue);), because I want to refresh my jQuery dialog div (#formZone) what is a tapestry zone. And it works well functionally, the data appears.

However, I always see the refreshing "procedure" because after the zone-update part, the jQuery dialog is opened, but the refresh is not ending (I know because ajax call is asynchronous) and it causes an "ugly" refresh after the jQuery dialog is opened.

My goal is to define a callback function for deferredZoneUpdate or make this code sequence:

...
zoneManager.deferredZoneUpdate("formZone", listenerURIWithValue);
$('#wsDialog').dialog('open');
...

Thanks for the answers in advance!

Update:

calendar-init.js:

    define(["jquery" , "t5/core/zone"], function($, zoneManager) {
        return function(modifyEventLink, newEventLink, pageTurnLink, allDayText) {
            $(document).ready(function() {
                var calendarDiv = $('#calendar');
                calendarDiv.fullCalendar({
                 //....init
                eventClick: function(calEvent, jsEvent, view) {


                // create modifyeventlink with id param
                var listenerURIWithValue = appendQueryStringParameter(modifyEventLink, 'eventID', calEvent.id);
                // ajax zone update
                zoneManager.deferredZoneUpdate("formZone", listenerURIWithValue);
                // open the worksheet dialog
                $('#wsDialog').dialog('option', 'title', calEvent.title);
            },
            //...init
   });});}}) // the code syntacs is good dont bother these :D

backend:

void onModifyEventLink() {
    if(request.isXHR()) {
        logger.debug("ModifyEventLink on.");
        String eventID = (String) request.getParameter("eventID");
        if(eventID == null) {
            logger.error("wsDialog was not able to load because eventID is NULL!");
        } else {                
            try{
                wSheet = sheetService.find(Integer.valueOf(eventID));
                if(wSheet != null) {    
                    ajaxResponseRenderer
                        .addCallback(new JavaScriptCallback() {
                            @Override
                            public void run(JavaScriptSupport javascriptSupport) {
                            javascriptSupport.require("wsdialogs");
                            }};)
                        .addRender(formZone);
                } else {
                    logger.warn("Worksheet with " + eventID + " not found.");                   
                }
            } catch (NumberFormatException e) {
                logger.error("wsDialog was not able to load beacause eventID was not a number.");
                logger.error("Exception: ", e.getLocalizedMessage());
            }
        }
    } else {
        logger.debug("ModifyEventLink on, request is not XHR (ajax)");
    }
}

(module) wsdialogs.js:

define(["jquery" , "t5/core/zone"], function($, zoneManager) {
        console.log("wsdialog-js run"); 
        $("#wsDialog").dialog('open');
});

tml:

<t:container
   xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd"
   xmlns:p="tapestry:parameter">

   <t:jquery.dialog t:clientId="wsDialog" t:id="wsDialog" title="${message:wsheet-new}" style="display: none;">
      <t:zone t:id="formZone" id="formZone">
        <t:form t:id="worksheetForm" t:type="form" t:zone="^">
            ....
        </t:form>   
       </t:zone> 
    </t:jquery.dialog>
</t:container>

Solution

  • public class ComponentWithZone {
        @Inject
        private AjaxResponseRenderer ajaxResponseRenderer;        
        ...
        public void onSomeEventFromClient() {
            ajaxResponseRenderer.addRender("zone-id-to-update", zone.getBody()).addCallback(new JavaScriptCallback() {
                @Override
                public void run(JavaScriptSupport javascriptSupport) {
                    javascriptSupport.require("modal").invoke("showModal").with("#dialog-id");
                }
            });
        }
    }
    

    This example is with bootstrap modal included as tapestry module.

    When tapestry refresh zone div with content it will trigger showModal function.

    UPD: Forgot to mention that this example assumes that you have modal module. Here is example of mine:

    (function(){
        define(["jquery", "bootstrap/modal"], function($, modal) {
            return {
                showModal: function(id) {
                    $('#'+id).modal('show');
                },
                hideModal: function(id) {
                    $('#'+id).modal('hide');
                }
            };
        });
    }).call(this);
    

    Instead of bootstrap/modal you can use any module, but don't forget to include it in META-INF/modules.