Skip to content

Padrão de Formulário com Envio de API

Este padrão define como implementar formulários que interagem com APIs, estabelecendo convenções claras para labels de botões baseadas no comportamento de envio dos dados. O objetivo é criar consistência na interface e comunicar claramente ao usuário o que acontecerá quando ele submeter o formulário.

Em interfaces que interagem com APIs, diferentes tipos de operações podem confundir o usuário sobre o que realmente acontece quando um formulário é submetido. A falta de padronização nas labels dos botões pode gerar incertezas sobre se os dados serão salvos imediatamente ou processados posteriormente.

  • Para formulários que fazem chamadas diretas para API
  • Quando há necessidade de distinguir entre salvamento imediato e processamento posterior
  • Em interfaces que precisam de feedback claro sobre o tipo de operação sendo realizada
  • Button (Console Kit Blocks)
  • Form (Console Kit Blocks)
  • Loading States (Console Kit Blocks)

Exemplo de formulário com botão Save

Formulário com botão “Save” para operações imediatas

Exemplo de formulário com botão Apply

Formulário com botão “Apply” para operações em fila

  1. “Save”: Usar quando o formulário envia dados diretamente para a API e os dados são processados/salvos imediatamente
  2. “Apply”: Usar quando o formulário registra dados para processamento posterior ou em fila
  3. Consistência: Manter a mesma label para operações similares em toda a aplicação
formSubmissionPattern.js
const FormSubmissionHandler = {
// Determina a label baseada no tipo de operação
getButtonLabel: (operationType) => {
switch (operationType) {
case 'immediate':
return 'Save';
case 'queued':
case 'deferred':
return 'Apply';
default:
return 'Submit';
}
},
// Gerencia o estado do botão durante o envio
handleSubmission: async (formData, operationType) => {
const button = document.querySelector('[data-submit-button]');
const originalLabel = button.textContent;
try {
// Estado de loading
button.disabled = true;
button.innerHTML = '<span class="loading-spinner"></span> Processing...';
// Envio para API
const response = await fetch('/api/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ...formData, operationType })
});
if (response.ok) {
// Feedback de sucesso
button.textContent = operationType === 'immediate' ? 'Saved!' : 'Applied!';
setTimeout(() => {
button.textContent = originalLabel;
button.disabled = false;
}, 2000);
}
} catch (error) {
// Estado de erro
button.textContent = 'Error - Try Again';
button.disabled = false;
}
}
};
// Exemplo de uso
const form = document.querySelector('#custom-page-form');
form.addEventListener('submit', (e) => {
e.preventDefault();
const formData = new FormData(form);
const operationType = form.dataset.operationType || 'immediate';
FormSubmissionHandler.handleSubmission(
Object.fromEntries(formData),
operationType
);
});
  • Utilize aria-label para descrever a ação específica do botão
  • Implemente aria-live regions para anunciar mudanças de estado
  • Garanta que estados de loading sejam anunciados por leitores de tela
  • Mantenha contraste adequado em todos os estados do botão