方案是此模式窗口:
带有.on('change', function () {});
的输入2、3和4对指定的控制器进行AJAX调用,该控制器将更新Recod值并重新加载值1。
因此,正确但不实用的方法是:
问题
如果我这样尝试:
现在,以这种方式出现问题是因为确认方法尚未收到上一次onchange触发器的更新,并且检查不正确。
是否可以通过onchange
和onclick
等不同的触发器来管理多个AJAX?
类似于触发以下onclick之类的东西:
// Trigger for button confirm inside timesheet sheet modal
$(document).on('click', 'button.js_confirm_timesheet_sheet', function (ev) {
var $button = $(this);
var wizard_id = $button.data()['wizardId'];
var sheet_id = $button.data()['sheetId'];
var values = {
'wizard_id': wizard_id,
'sheet_id': sheet_id,
};
confirm_sheet_distribution_hours(values);
});
检查点击是否来自输入焦点,如果是,则首先触发onchange
,然后触发onclick
也许此解决方案可能是这样做的一种不好方法。
很少,触发摘要:
另一种解决方法可能是声明一个对象,该对象跟踪每个更改的输入框,并在每次AJAX成功返回时将其清除。
类似的东西:
var changedData = {};
function update_wizard_data_and_modal(values, $input_elem, event) {
changedData[key] = $input_elem;
ajax.jsonRpc("/my/controller/path", "call", values)
.then(function (new_modal_values) {
$input_elem.removeClass('input-value-error');
if (!jQuery.isEmptyObject(new_modal_values)) {
if (new_modal_values.error_msg) {
var $content = $(new_modal_values.error_msg);
$content.modal({
backdrop: 'static',
keyboard: false
});
$content.appendTo('body').modal();
// Show error class
$input_elem.val('00:00');
$input_elem.addClass('input-value-error');
}
// Update the header values with hours to be distribuited
$('#header-wizard-values').html(new_modal_values.header_values);
// Update the hours to get payed available
$('.js_hours_to_get_payed').html(new_modal_values.hours_get_payed_values);
// Clear the changedData object
for (var member in changedData) delete changedData[member];
}
});
}
function confirm_sheet_distribution_hours(values) {
if jQuery.isEmptyObject(changedData){
ajax.jsonRpc("/confirm/controller/path", "call", values)
.then(function (response) {
if ('error' in response) {
//response in this case is the modal error template
$(response.error).appendTo('body').modal();
} else {
// Close modal and refresh the grid for current period
$('#modal_timesheet_sheet_confirm').modal('hide');
var sheet_item_data = {
'year': response.year,
'month': response.month,
};
update_grid_and_bars_values(sheet_item_data);
}
});
} else {
// TODO: trigger the change for element inside object and confirm
}
}
$(document).on("change", "input.distribution-input", function (ev) {
var $input = $(this);
var sheet_id = $('input[name="sheet_id"]').val();
var wiz_line_id = Number($input.attr('id').match(/\d+/)[0]);
var row_wizard_data = $input.closest('div.row').data();
var leave_type_id = row_wizard_data['leaveTypeId'];
var wizard_id = row_wizard_data['wizardId'];
var values = {
'sheet_id': Number(sheet_id),
'wizard_id': wizard_id,
'wiz_line_id': wiz_line_id,
'leave_type_id': leave_type_id,
'input_value': $input.val(),
};
var is_good_formatted = check_string_time_format($input, {});
if (is_good_formatted) {
update_wizard_data_and_modal(values, $input, ev);
}
});
// Trigger for button confirm inside timesheet sheet modal
$(document).on('click', 'button.js_confirm_timesheet_sheet', function (ev) {
ev.preventDefault();
ev.stopPropagation();
var $button = $(this);
var wizard_id = $button.data()['wizardId'];
var sheet_id = $button.data()['sheetId'];
var values = {
'wizard_id': wizard_id,
'sheet_id': sheet_id,
};
confirm_sheet_distribution_hours(values);
});
答案 0 :(得分:0)
根据塔普拉(Taplar)的建议,我使用了类似的方法。
这是在Odoo前端中管理向导的“ onchange”的javascript。
// Variable used for the last input changed when user click the Confirm button
var canConfirm = true;
/* Variable used for keep trace of the number of retry inside method
* confirm_sheet_distribution_hours
* */
var nr_of_try = 0;
function update_wizard_data_and_modal(values, $input_elem, event) {
if (event.type !== 'input') {
ajax.jsonRpc("/controller/path/...", "call", values)
.then(function (new_modal_values) {
canConfirm = true;
$input_elem.removeClass('input-value-error');
if (!jQuery.isEmptyObject(new_modal_values)) {
if (new_modal_values.error_msg) {
var $content = $(new_modal_values.error_msg);
$content.modal({
backdrop: 'static',
keyboard: false
});
$content.appendTo('body').modal();
// Show error class
$input_elem.val('00:00');
$input_elem.addClass('input-value-error');
}
// Update the header values with hours to be distribuited
$('#header-wizard-values').html(new_modal_values.header_values);
// Update the hours to get payed available
$('.js_hours_to_get_payed').html(new_modal_values.hours_get_payed_values);
}
});
} else {
canConfirm = false;
}
}
function set_the_amount_on_wizard($input, values, event) {
if (event.type !== 'input') {
ajax.jsonRpc("/controller/path/...", "call", values)
.then(function (response) {
canConfirm = true;
if ('error' in response) {
//response in this case is the modal error template
$(response.error).appendTo('body').modal();
// Reset input value (backend reset the TransientModel value)
$input.val('00:00')
}
});
} else {
canConfirm = false;
}
}
function confirm_sheet_distribution_hours(values) {
if (canConfirm) {
ajax.jsonRpc("/controller/patH/...", "call", values)
.then(function (response) {
if ('error' in response) {
//response in this case is the modal error template
$(response.error).appendTo('body').modal();
} else {
// Close modal and refresh the grid for current period
$('#modal_timesheet_sheet_confirm').modal('hide');
var sheet_item_data = {
'year': response.year,
'month': response.month,
};
update_grid_and_bars_values(sheet_item_data);
}
});
} else {
/*Try six times to confirm the sheet (Until the onchange doesn't write
* new values the AJAX call doesn't set canConfirm as True
* */
if (nr_of_try <= 5) {
setTimeout(function () {
nr_of_try++;
confirm_sheet_distribution_hours(values);
}, 500);
}
}
}
//Trigger that monitorate hours distribution change
$(document).on("input change", "input.distribution-input", function (ev) {
var $input = $(this);
var sheet_id = $('input[name="sheet_id"]').val();
var wiz_line_id = Number($input.attr('id').match(/\d+/)[0]);
var row_wizard_data = $input.closest('div.row').data();
var leave_type_id = row_wizard_data['leaveTypeId'];
var wizard_id = row_wizard_data['wizardId'];
var values = {
'sheet_id': Number(sheet_id),
'wizard_id': wizard_id,
'wiz_line_id': wiz_line_id,
'leave_type_id': leave_type_id,
'input_value': $input.val(),
};
var is_good_formatted = check_string_time_format($input);
if (is_good_formatted) {
update_wizard_data_and_modal(values, $input, ev);
}
});
//Trigger that monitorate hours distribution change
$(document).on("input change", "input.payment-hour-input", function (ev) {
var $input = $(this);
var row_wizard_data = $input.closest('div.row').data();
var wizard_id = row_wizard_data['wizardId'];
var values = {
'wizard_id': wizard_id,
'input_value': $input.val(),
};
var is_good_formatted = check_string_time_format($input);
if (is_good_formatted) {
set_the_amount_on_wizard($input, values, ev);
}
});
// Trigger for button confirm inside timesheet sheet modal
$(document).on('click', 'button.js_confirm_timesheet_sheet', function (ev) {
var $button = $(this);
var wizard_id = $button.data()['wizardId'];
var sheet_id = $button.data()['sheetId'];
var values = {
'wizard_id': wizard_id,
'sheet_id': sheet_id,
};
// Variable used for retry sheet confirmation until canConfirm is not True
// Max repeat call is 6 times
nr_of_try = 0;
confirm_sheet_distribution_hours(values);
});
简单来说。
当用户在输入框上键入内容时,input
内的on.()
类型会将变量canConfirm
设置为false
。
这样可以防止用户更改值并在之后立即单击“确认”按钮的情况。
实际上,如果用户更改某些输入框并立即单击“确认”,则仅当标志为true
时AAAX调用才会开始,否则,该方法每500毫秒调用一次其自身。
让我知道是否有更好的方法可以做到这一点。 谢谢
PS:我将使用DTO后端尝试一种更好的方法,该方法可从模型中克隆数据并管理onchange缓存之类的更新。
灵感来自:https://python-3-patterns-idioms-test.readthedocs.io/en/latest/Messenger.html