1

I've made a question on the forum about a issue I was facing in my application. Although the question was marked as duplicate, I tried to use the good practices to solve the problem. After very tries my code finnaly works, but not in the way I expected. I'm making an application using the Fullcalendar plugin. In the "eventRender" callback, which is executed to each event on the calendar, the callback I've made is making hundreds of ajax calls :@ I think I don't understand very well all that callback thing. Here's my code:

    $().ready(function() {
        var obterDadosCategorias = (function() {
            var dadosCategorias;

            var efetuarPost = function(callback){
                $.post(
                    "{{ baseRoute }}/cadastro/categoria/listar"
                    , {
                        "ajax": "true"
                    }
                ).done(function(data) {
                    var obj = $.parseJSON(data);
                    if (obj.result) {
                        callback(obj.data);
                    } else {
                        alert('Erro interno: não foi possível obter os dados das categorias');
                    }
                }).fail(function(){
                    alert('Erro interno: não foi possível obter os dados das categorias');
                });
            };

            return function(callback) {
                if (dadosCategorias) {
                    callback(dadosCategorias);
                    return;
                }

                efetuarPost(function(dados) {
                    dadosCategorias = dados;
                    callback(dados);
                });
            };
        })();

        $("#fullcalendar").fullCalendar({
            "eventRender": function(event, element, view) {
                if (view.name === "month") {
                    var beforeMonth = parseInt(event.end.format("YYYYMMDD")) < parseInt(view.intervalStart.format("YYYYMMDD"));
                    var afterMonth = parseInt(event.start.format("YYYYMMDD")) > parseInt(view.intervalEnd.clone().subtract(1, 'days').format("YYYYMMDD"));

                    if (beforeMonth || afterMonth) {
                        return false;
                    }
                }

                obterDadosCategorias(function(dadosCategorias) {
                    $(element).css("background-color", dadosCategorias["id_" + event.categoria].cor).css("color", textoBrancoOuPreto(dadosCategorias["id_" + event.categoria].cor));
                });

                return $(element);
            }
        });
    });

Hope you guys can help me. :D Thanks in advance.

Community
  • 1
  • 1

1 Answers1

1

Using asynchronous code requires you to think differently about how your functions should be structured. Instead of thinking: "I need to write a function that returns a value," you should be thinking "I need to write a function that performs an action once I have a value."

It appears your only need for an AJAX call is to get your list of categories. You are currently making that AJAX request every time an event is rendered on your calendar. Instead you should get the categories once, then initialize your calendar after retrieving them.

The other key is storing the categories where they can be accessed in your renderEvent handler. I solved this below by using JavaScript Closures, but you could also use a global variable (preferably namespaced).

I believe this code accomplishes all you are looking for:

$(document).ready(function() {  

    $.post(
        "{{ baseRoute }}/cadastro/categoria/listar"
        , {
            "ajax": "true"
        }
    ).done(function(data) {
        $("#fullcalendar").fullCalendar({
            "eventRender": createRenderEvent($.parseJSON(data))
        });

    }).fail(function(){
        alert('Erro interno: não foi possível obter os dados das categorias');
    });

    function createRenderEvent(dadosCategorias) {
        return function(event, element, view) {
            if (view.name === "month") {
                var beforeMonth = parseInt(event.end.format("YYYYMMDD")) < parseInt(view.intervalStart.format("YYYYMMDD"));
                var afterMonth = parseInt(event.start.format("YYYYMMDD")) > parseInt(view.intervalEnd.clone().subtract(1, 'days').format("YYYYMMDD"));

                if (beforeMonth || afterMonth) {
                    return false;
                }
            }

            $(element).css("background-color", dadosCategorias["id_" + event.categoria].cor).css("color", textoBrancoOuPreto(dadosCategorias["id_" + event.categoria].cor));
            return $(element);
        }
    }

});
Dave
  • 10,748
  • 3
  • 43
  • 54