Передайте некоторые инструкции функции - PullRequest
0 голосов
/ 20 февраля 2020

Я пытаюсь дедуплицировать код js основной формы, который выполняет запрос ajax. Сначала я выполняю функцию php, которая генерирует любую функцию при отправке формы, передавая другой код в качестве параметров, но не выглядит неплохо. После того, как я попытался вместо этого использовать функцию javascript, для простых переменных я сделал это работающим, например:

// <script> inside of the page generate by php (and in some cases in html received by other ajax request)
$('#f_man-marker_edit-marker').on('submit', function(e){
    TM.editMarker(e, $(this), 'man-marker_edit-marker');
});

...
// in other js file
TM.editMarker = function (e, form, ajax_request) {
    // stop browser from submitting form!
    e.preventDefault();

    // Abort any pending request
    if (request) request.abort();

    // Let's select and cache all the fields
    let inputs = form.find("input, select, button, textarea");

    // Serialize the data in the form
    let serializedData = form.serialize();

    // Let's disable the inputs for the duration of the Ajax request.
    // Note: we disable elements AFTER the form data has been serialized.
    // Disabled form elements will not be serialized.
    inputs.prop("disabled", true);

    request = $.ajax({
        url: "ajax.php?req=" + ajax_request,
        type: "post",
        data: serializedData,
        dataType: "html"
    });

    request.done(function (response) {
        $("#ajaxoutput2").empty().append(response);
        $("#ResultModal2").modal("show");
    });

    request.fail(function (jqXHR, textStatus, errorThrown) {
        console.error(
            "Ajax " + ajax_request + " request failed. The following error occurred: " +
            textStatus, errorThrown
        );
    });

    request.always(function () {
        inputs.prop("disabled", false);
    });

};

Теперь пропущены инструкции request.done в качестве параметра, но я не нашел хороший и работающий способ сделать это. Поместив их в функцию, я получил неопределенный ответ переменной, а также добавил его в качестве параметра. Точнее я попробовал:

$('#f_man-marker_edit-marker').on('submit', function(e){
                    let req_done = function (response) {
                        $("#ajaxoutput2").empty().append(response);
                        $("#ResultModal2").modal("show");
                    };
                    TM.editMarker(e, $(this), 'man-marker_edit-marker', req_done());
                });

...
// in other js file
TM.editMarker = function (e, form, ajax_request, req_done()) {
...
    request.done(function (response) {
        req_done(response);
    });
...
};

Это не работает. Можно ли передать инструкции такими, какие они есть, и заставить их работать или они должны быть в работе? Если должен быть в функции, как правильно это сделать? Вероятно, это возможно с eval (), но кажется очень обескураженным, и я не пробовал это сейчас.

РЕДАКТИРОВАТЬ: Я пытаюсь объяснить лучше: я пытаюсь сделать, это иметь функцию php или js для вызывайте и передавайте в качестве параметров единственные вещи, которые меняются, например, на сотнях подобных форм, которые я буду делать в проекте, все будет хорошо, если будут избегаться тысячи или десятки тысяч строк дублирующегося кода и возможный рефакторинг или будущее улучшения намного проще и быстрее. Я начал с генерации с php, например:

...
// "f_man-marker_add-marker" is the id of the form, "man-marker_add-marker" is the id of the ajax request, $man_marker_jap1 contain that instructions printed inside of request.done function (they can be different on any form)

TM\UI\JSHelper::jqueryAjaxPost(
            "f_man-marker_add-marker", "man-marker_add-marker", $man_marker_jap1);

.....
// in the file of TM\UI\JSHelper:

...
/**
     * Generate a jquery ajax of type post and datatype html
     * will call the url ajax.php?req=$request_name
     * and request.done will do what define in $done_content
     *
     * @param string $form_id Id of the form
     * @param string $request_name Name of the ajax request parameter
     * @param string $done_content Content of request.done
     */
    public static function jqueryAjaxPost(string $form_id, string $request_name, string $done_content){
        echo <<<HTML

$("#$form_id").submit(function(event){

    // Prevent default posting of form - put here to work in case of errors
    event.preventDefault();

    // Abort any pending request
    if (request) { request.abort(); }

    let form = $(this);

    // Let's select and cache all the fields
    let inputs = form.find("input, select, button, textarea");

    // Serialize the data in the form
    let serializedData = form.serialize();

    // Let's disable the inputs for the duration of the Ajax request.
    // Note: we disable elements AFTER the form data has been serialized.
    // Disabled form elements will not be serialized.
    inputs.prop("disabled", true);

    request = $.ajax({
        url: "ajax.php?req=$request_name",
        type: "post",
        data: serializedData,
        dataType: "html"
    });

    request.done(function (response){
        $done_content
    });

    request.fail(function (jqXHR, textStatus, errorThrown){
        console.error(
            "Ajax $request_name request failed. The following error occurred: "+
            textStatus, errorThrown
        );
    });

    request.always(function () {
        inputs.prop("disabled", false);
    });

});

HTML;
    }

, но не имел js «проблемы» (если все сделано правильно), потому что сгенерированный код указывает c для каждой формы и «полный» js "без вызова других внешних функций. Затем я подумал сделать это в основном только в js файле (который для логики c будет казаться более правильным, а не генерировать все js из php) и был в порядке, за исключением содержимого request.done, которое должно измениться. , поэтому я открываю этот пост, чтобы выяснить, каков наилучший и правильный способ сделать это. Если вместо этого нет лучшего способа сделать то, что мне нужно, в основном в js, а менее худшее, похоже, останется в поколении php, скажите мне.

EDIT2: я провел другие тесты и нашел рабочее решение без использования eval (я не знаю, хорошо ли):

// inside a <script> of part of page generated by php or html code received from ajax request
$('#f_man-marker_edit-marker').on('submit', function(e){
    let req_done = function (response) {
        $("#ajaxoutput2").empty().append(response);
        $("#ResultModal2").modal("show");
    };
    TM.jqueryAjaxPost(e, $(this), 'man-marker_edit-marker', req_done);
});

...
// in other js-only file
/**
 * Basic jquery ajax request of type post from form
 * where changes only request.done content
 * @param e Event received from onsubmit of the form
 * @param form Receive the element with $(this)
 * @param ajax_request Name of the ajax request send to php
 * @param req_done Instruction to do on request.done
 */
TM.jqueryAjaxPost = function (e, form, ajax_request, req_done) {

    // stop browser from submitting form!
    e.preventDefault();

    // Abort any pending request
    if (request) request.abort();

    // Let's select and cache all the fields
    let inputs = form.find("input, select, button, textarea");

    // Serialize the data in the form
    let serializedData = form.serialize();

    // Let's disable the inputs for the duration of the Ajax request.
    // Note: we disable elements AFTER the form data has been serialized.
    // Disabled form elements will not be serialized.
    inputs.prop("disabled", true);

    request = $.ajax({
        url: "ajax.php?req=" + ajax_request,
        type: "post",
        data: serializedData,
        dataType: "html"
    });

    request.done(function (response) {
        req_done(response);
    });

    request.fail(function (jqXHR, textStatus, errorThrown) {
        console.error(
            "Ajax " + ajax_request + " request failed. The following error occurred: " +
            textStatus, errorThrown
        );
    });

    request.always(function () {
        inputs.prop("disabled", false);
    });

};

Это хорошо или есть лучший способ сделать это и / или возможное улучшение?

РЕДАКТИРОВАТЬ3: я пытался также сделать что-то, работающее с дополнительными параметрами:

TM.deleteMarker = function (id) {
    let req_done = function (response, parArray) {
        $("#ajaxoutput").empty().append(response);
        $('#link_open-marker' + parArray[id]).remove();
    };
    TM.jqueryAjaxGet('man-marker_delete-marker&id=' + id, req_done, {id: id});
};

/**
 * Basic jquery ajax request of method get and datatype html
 * @param ajax_request Name of the ajax request send to php and get parameters, it will be
 * will be added to the end of the url
 * @param req_done Instruction to do on request.done
 * @param parArray Additional parameters used in req_done
 */
TM.jqueryAjaxGet = function (ajax_request, req_done, parArray = {}) {
    // Abort any pending request
    if (request) {
        request.abort();
    }

    request = $.ajax({
        url: "ajax.php?req=" + ajax_request,
        method: "get",
        dataType: "html"
    });

    request.done(function (response) {
        req_done(response, parArray);
    });

    request.fail(function (jqXHR, textStatus, errorThrown) {
        console.error(
            "Ajax " + ajax_request + " request failed. The following error occurred: " +
            textStatus, errorThrown
        );
    });
};

не дает ошибок или предупреждений и работает все, кроме

$('#link_open-marker' + parArray[id]).remove();

, поэтому я полагаю, что я сделал что-то не так с parArray, но я не Понимаете, что, Может кто-нибудь помочь мне решить (или сделать по-другому, если это нехорошо), пожалуйста?

Спасибо за любой ответ и извините за мой плохой английский sh.

1 Ответ

0 голосов
/ 20 февраля 2020

Я не совсем уверен, правильно ли я понял ваш вопрос, но если речь идет о получении обратного вызова done вне вашего метода, у вас есть два возможных способа сделать это.

Используйте замыкания:

TM.editMarker = function (e, form, ajax_request, doneHandler) {
   ...

   request.done(function (response) {
        $("#ajaxoutput2").empty().append(response);
        $("#ResultModal2").modal("show");

        if(doneHandler !== undefined)
             doneHandler();
    });
}

TM.editMarker(e, $(this), 'man-marker_edit-marker', function() {
   console.log("done");
});

Используйте обещания:

TM.editMarker = function (e, form, ajax_request) {
   ...

   var prom= jQuery.Deferred();
   request.done(function (response) {
        $("#ajaxoutput2").empty().append(response);
        $("#ResultModal2").modal("show");

        prom.resolve();
    });

    return prom.promise();
}

TM.editMarker(e, $(this), 'man-marker_edit-marker').then(function() {
   console.log("done");
});

Ответ на редактирование:

Хорошо, так что вы пытаемся выполнить javascript функцию через ответ ajax. Вы можете достичь этого, выполнив что-то вроде этого:

$.ajax({
    url: "somejs.js",
    context: document.body,
    success: function(responseText) {
        eval(responseText);
    }
});

Однако это действительно грязно и не очень хорошая практика, потому что javascript - это, как правило, манипулирование командами в пользовательском интерфейсе. Храните пользовательский интерфейс во внешнем интерфейсе и возвращайте только необработанные данные / json из своего внутреннего интерфейса. Можете ли вы дать мне пример того, как выглядит ответ, тогда я могу дать вам пример того, как я бы его решил.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...