Course progress0%
Course content
35 min

A Click Is an Intention, Not a Business Rule

Translate a user action into one explicit operation

By the end of this lesson

  • Translate a user action into one explicit operation
  • Explain submit events, default behavior and listener lifetime

The request

"Let me calculate again after changing the order." A button is a way to express that intention. It should not become a new home for the pricing formula.

Pause: Should clicking calculate save the order, change inventory or take payment? Under our current contract, none of those actions is authorized. It only requests a new quote.

Start with a native action

In your page, create a form with id quote-form, a submit button and a paragraph with id action-status. This isolated experiment explains event flow before we connect real input.

const form = document.querySelector('#quote-form');
const status = document.querySelector('#action-status');
let requests = 0;
form.addEventListener('submit', (event) => {
  event.preventDefault();
  requests += 1;
  status.textContent = `Calculation requested ${requests} times`;
});

The handler is registered now and called later. PreventDefault stops the form's normal navigation, not other event listeners. Submitting the form rather than handling only a button click also covers keyboard submission. A button that must not submit should have type button.

The event's target is where the event originated; currentTarget is where the current listener is attached. Bubbling lets events reach ancestors. Do not stop propagation reflexively: it can break deliberate coordination elsewhere.

Challenge the first implementation

If initialization runs twice, two listeners can respond to one submit. Put listener registration in one startup path. Rendering should update content, not register another copy of the same handler on every calculation.

For a reusable view with a lifecycle, keep a named callback and remove it when that view is destroyed. Anonymous callbacks are fine when registered once for the lifetime of this simple page.

Build it yourself

Replace the counter body with a call to your existing calculation-and-render coordinator. Keep your domain function unchanged. Add a separate Restore example button with type button. Make restoring load the baseline input and explicitly request a render.

Expected evidence

One submit causes one calculation. Pressing Enter behaves like activating Calculate. Restore does not accidentally submit twice. Changing a button label does not change the computed amount.

Change request

The user wants calculation on every keystroke. Identify the consequences before switching to an input event: incomplete intermediate values, repeated announcements and potentially expensive requests. Local arithmetic is cheap; network-backed actions need a different policy. Keep submit-based calculation until the interaction is confirmed.

Check your reasoning

What belongs in the handler? Reading the intention and coordinating established operations. Eligibility, tax and rounding still belong in the tested domain module. A click handler that duplicates those decisions has introduced a second source of truth.

Lesson complete?

Your progress is saved on this device.