Today's craft
Forms, part 2 — the form learns to offer choices.
Class 6 built a form that asks open questions — name, email, phone. But look at any real order screen: most answers aren't typed, they're picked. One dish out of ten. Any number of add-ons. A hostel block from a list. Today the Poshtik order form gets every choice control HTML owns — plus a real submit button — and walks out complete. And because one of these controls hides the classic exam bug, a past paper's 2-mark question gets solved on the way.
Walk out of this room able to…
Idea one
Radio buttons — exactly one pick, enforced by the browser.
A Poshtik order has one main dish — a student can't eat two lunches at once. HTML's control for "pick exactly one" is <input type="radio">. And here is the single most important sentence of this hour: radios become a group because they share the same name. Not because they sit near each other, not because they're in the same form — the shared name is the group. The browser then guarantees only one member of that name can be selected.
name.- Create the
class-07folder, save asradio-dish.html· title text: Pick a dish - Inside
<form action="/place-order" method="post">: three label-wrapped radios, ALL withname="dish", each with its ownvalue
name said it for you.<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Pick a dish</title> </head> <body> <form action="/place-order" method="post"> <p>Pick your dish:</p> <label><input type="radio" name="dish" value="ragi-sangati"> Ragi Sangati Bowl</label><br> <label><input type="radio" name="dish" value="jonna-wrap"> Jonna Rotte Wrap</label><br> <label><input type="radio" name="dish" value="millet-shake"> Millet Protein Shake</label> </form> </body></html>C:\Users\student\Desktop\fswd-practice\class-07\ — today's first file, so create the class-07 folder inside your sandbox first, right next to class-02 … class-06. Same ritual, seventh time.radio-dish.htmlfswd-practice\ is the sandbox — never a git repo. poshtik-campus\ (the real project, under git since Lab 1) stays untouched until Lab 2.Two things to notice in the code: ① each radio carries a value — that's the word actually sent to the server when the form submits (dish=ragi-sangati), because the visible label text is for humans, not machines. ② the <label> here wraps the input instead of using for/id — both styles are legal; wrapping needs no id and is the common habit for radios and checkboxes.
Old car radios had a row of push-buttons for stations — press one in, and the previously pressed one physically popped out. One station at a time, mechanically enforced. HTML borrowed the name and the behaviour wholesale. Interviews and quizzes love this etymology; more usefully, it's a perfect memory hook for "exactly one".
Idea two
Checkboxes — any number of picks, including zero.
Protein add-ons are the opposite question. A boiled egg and extra sprouts and paneer cubes is a perfectly good order; so is none of them. When every option is independent — each one its own yes/no — the control is <input type="checkbox">. Same tag family as radio, one word different, opposite social behaviour: checkboxes never un-pick each other.
- Save as
add-ons.htmlinsideclass-07· title text: Protein add-ons - Three label-wrapped
<input type="checkbox">, all withname="addon", each with its ownvalue
addon=value pair; the server receives a list.<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Protein add-ons</title> </head> <body> <form action="/place-order" method="post"> <p>Protein add-ons (pick any):</p> <label><input type="checkbox" name="addon" value="boiled-egg"> Boiled egg</label><br> <label><input type="checkbox" name="addon" value="extra-sprouts"> Extra sprouts</label><br> <label><input type="checkbox" name="addon" value="paneer-cubes"> Paneer cubes</label> </form> </body></html>C:\Users\student\Desktop\fswd-practice\class-07\add-ons.htmlThe one-line decision rule (memorise this — it answers exam MCQs and real design questions alike): "pick exactly one" means radio with a shared name · "pick any number" means checkbox · "pick one from a long list" means the dropdown you meet next.
Tick boiled egg + paneer cubes and submit: the request body carries addon=boiled-egg&addon=paneer-cubes — the name repeats, once per tick. Untick everything and the pair vanishes entirely (an unchecked box sends nothing, not "false" — a subtlety that bites people in Unit 4, so file it away now).
Idea three
<select> — one pick from a long list, without eating the page.
Delivery location: hostel blocks A to D, the library lawn, three classroom buildings… Ten radio buttons for that would swallow half the screen. When the list is long and the answer is still "exactly one", HTML folds the whole thing into a dropdown: a <select> wrapping one <option> per choice.
- Save as
deliver-to.htmlinsideclass-07· title text: Deliver to - A
<label for="spot">bonded to<select id="spot" name="delivery-spot"> - Four
<option>s — two hostels, the library lawn, the CSE block — each with its ownvalue
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Deliver to</title> </head> <body> <form action="/place-order" method="post"> <label for="spot">Deliver to:</label> <select id="spot" name="delivery-spot"> <option value="hostel-a">Hostel Block A</option> <option value="hostel-b">Hostel Block B</option> <option value="library-lawn">Library lawn</option> <option value="cse-block">CSE classroom block</option> </select> </form> </body></html>C:\Users\student\Desktop\fswd-practice\class-07\deliver-to.htmlReal products rarely let the first real choice be the silent default — a student could submit "Hostel Block A" without ever thinking. The pattern: <option value="" disabled selected>— choose a spot —</option> as the first option. disabled makes it un-pickable, selected makes it what shows first, and the empty value means "no answer yet". You'll use this in Lab 2.
Idea four
<textarea> — when one line isn't enough.
"Less spicy please, and call when you reach the gate — the bell doesn't work." Order notes don't fit an <input>; they need paragraphs. <textarea> is the multi-line answer box — and unlike <input>, it is not a void tag: it opens and closes, and anything between the tags becomes pre-filled text (usually you want nothing there).
- Save as
order-notes.htmlinsideclass-07· title text: Order notes - A labelled
<textarea id="notes" name="order-notes" rows="4" cols="40"></textarea> - Open AND close the tag with nothing between — textarea is a container, not a void tag
<input>.<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Order notes</title> </head> <body> <form action="/place-order" method="post"> <label for="notes">Order notes:</label><br> <textarea id="notes" name="order-notes" rows="4" cols="40"></textarea> </form> </body></html>C:\Users\student\Desktop\fswd-practice\class-07\order-notes.html<input>.Classic slip, worth 2 marks somewhere: writing <textarea /> or forgetting </textarea>. Because textarea is a container, an unclosed one swallows all the HTML after it as "pre-filled text" — your submit button literally appears inside the box as words. If you ever see your own markup rendered as text inside a giant input, you know exactly which tag to check.
Idea five
The real submit button — and the styled <div> that lies.
Class 6 ended with a form that could refuse to send. Here's the piece that does the sending: <button type="submit">. Press it and the browser runs the whole ritual — check every required field, package every name=value pair, send them to the action address. Now the trap: you can style a <div> to look exactly like that button. It will look identical — and do none of it.
<button type="submit"> and a fake styled-text "button" side by side in one form — and catch the impostor doing none of the work.- Save as
real-button.htmlinsideclass-07· title text: Real vs fake button - A labelled,
requiredname input - Line 11:
<button type="submit">Place order</button>· line 12:<div>Place order</div>— same words, no tag magic
/place-order). The div renders as two bare words — deaf to Enter, invisible to Tab, silent to screen readers.<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Real vs fake button</title> </head> <body> <form action="/place-order" method="post"> <label for="n">Name:</label><br> <input type="text" id="n" name="student-name" required><br> <button type="submit">Place order</button> ← the real thing <div>Place order</div> ← the impostor — renders as plain text </form> </body></html>C:\Users\student\Desktop\fswd-practice\class-07\real-button.html/place-order). Now click the div: nothing, ever.type="submit" sends the form (and is the default if you write no type — a famous source of accidental submits). type="reset" wipes every field back to its initial state — users hate it, real products almost never ship it, but exams still name it. type="button" does nothing at all — it exists for JavaScript to attach behaviour to, which is exactly how Unit 2 will use it.
Two questions. One is quietly breaking the other.
A junior built this for the Poshtik counter: question 1 — which dish? question 2 — small or regular portion? Four radios, two groups, honest-looking code. But type it and try to answer both questions: something impossible happens. Your job: see the bug behave, name its cause in one sentence, and write the fix — in your notebook first.
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Broken radios</title> </head> <body> <form action="/place-order" method="post"> <p>Dish:</p> <label><input type="radio" name="choice" value="pesarattu"> Pesarattu with Sprouts</label><br> <label><input type="radio" name="choice" value="ulava-charu"> Ulava Charu Bowl</label><br> <p>Portion:</p> <label><input type="radio" name="choice" value="small"> Small</label><br> <label><input type="radio" name="choice" value="regular"> Regular</label> </form> </body></html>C:\Users\student\Desktop\fswd-practice\class-07\broken-radios.html — yes, save the broken version. Seeing a bug behave in your own browser is worth ten descriptions of it.One word, four lines, two marks.
Honesty rule: notebook first, reveal second. The exam version of this question is waiting below the fix.
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Fixed radios</title> </head> <body> <form action="/place-order" method="post"> <p>Dish:</p> <label><input type="radio" name="dish" value="pesarattu"> Pesarattu with Sprouts</label><br> <label><input type="radio" name="dish" value="ulava-charu"> Ulava Charu Bowl</label><br> <p>Portion:</p> <label><input type="radio" name="portion" value="small"> Small</label><br> <label><input type="radio" name="portion" value="regular"> Regular</label> </form> </body></html>- Observed: picking any of the four un-picks whichever was picked before — the two questions behave as one four-option question.
- Cause (one sentence): all four radios share name="choice", and the shared name is what defines a radio group — so the browser treats them as one group with a one-pick rule across all four.
- Fix: give each question its own name — name="dish" on lines 10–11, name="portion" on lines 13–14. Four highlighted lines, one attribute value changed per line, nothing else touched.
Q1. The following HTML is intended to let a user pick one size AND one crust, but selecting from one group deselects the other. Identify the error and write the corrected code. [2M]
The model answer, point by point — then deeper than two marks demand ↓
Name the error: both radio groups share the same name attribute. Radio buttons are grouped by their name, so all the buttons act as a single group and only one can be selected across both questions.✓ 1
<input type="radio" name="size" value="small"> Small <input type="radio" name="size" value="large"> Large <input type="radio" name="crust" value="thin"> Thin <input type="radio" name="crust" value="thick"> Thick
Not paper-only: the corrected file built LIVE just above this sheet, one line per press, real output beside it — scroll up and actually order a small pesarattu; both groups now answer independently.
✓ 1Exam craft: four corrected lines suffice if the question printed only the inputs; if it printed a full file, correct it inside the full file — the skeleton costs nothing and shows discipline.
Beyond the marks — where the name goes next. The name attribute is doing two jobs at once: grouping the radios in the browser, and becoming the key in the submitted data — the server receives size=small&crust=thin. That's why the shared-name bug is doubly fatal: even the data arrives as one meaningless choice= key. One attribute, two systems — fix the name and both heal.✚ depth
error named via the grouping rule + corrected names shown = full 2 marks ✓ — diagram + depth past the marks, by course rule
It's a two-line answer that cleanly separates students who memorised "radio = one choice" from students who understand that the name attribute is the grouping mechanism. Any paper can re-skin it — sizes and crusts, dishes and portions, genders and payment modes — but the bug and the fix never change. You've now debugged it with your own hands; no re-skin can surprise you.
Idea five
Fieldset & legend — drawing the boxes around related questions.
Our order form is growing: dish radios here, add-on checkboxes there, a dropdown below. Paper forms solved this problem a century ago — they draw a box around each group of related questions and give the box a title. HTML has the same two tools: <fieldset> draws the box, <legend> writes the title on its edge. And it's not just visual: a screen reader announces the legend before every control inside — grouping you can hear.
<fieldset> and <legend>.- Save as
grouped.htmlinsideclass-07· title text: Grouped form - Fieldset 1 — legend Pick your dish: two radios sharing
name="dish" - Fieldset 2 — legend Protein add-ons: two checkboxes with
name="addon"
name, not by fieldset: the box is for humans and screen readers; the name is for the one-pick rule.<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Grouped form</title> </head> <body> <form action="/place-order" method="post"> <fieldset> <legend>Pick your dish</legend> <label><input type="radio" name="dish" value="ragi-dosa"> Ragi Dosa</label> <label><input type="radio" name="dish" value="jowar-upma"> Jowar Upma</label> </fieldset> <fieldset> <legend>Protein add-ons</legend> <label><input type="checkbox" name="addon" value="boiled-egg"> Boiled egg</label> <label><input type="checkbox" name="addon" value="extra-sprouts"> Extra sprouts</label> </fieldset> </form> </body></html>C:\Users\student\Desktop\fswd-practice\class-07\grouped.html<fieldset> pair, save, watch the box vanish while the controls stay — proof the grouping is a separate layer.Common exam confusion, cleared up now: <fieldset> does not create the radio group. Two radios with different names inside one fieldset are still two separate groups; two radios with the same name in different fieldsets are still one group. Fieldset = visual/accessible grouping · shared name = behavioural grouping. Two different jobs, two different tools.
Put disabled on a <fieldset> and every control inside greys out and stops accepting input at once — the only place in HTML where one attribute switches off a whole region. Restaurants use exactly this to grey out the "delivery address" box when "pickup" is selected. That interactivity needs Unit 2's JavaScript; the HTML hook is already in your hands.
The canteen hands you a spec. Build it.
Real work rarely says "type this code" — it says what the thing must do and leaves the markup to you. Here is exactly such a request from the Poshtik counter, five requirements, no code shown. Write the whole file in your notebook first, then type it and watch it run.
THE SPEC — sprouts-chaat toppings picker:
① a complete HTML file (full skeleton — DOCTYPE to </html>, title "Chaat toppings");
② one <form> posting to /toppings;
③ three toppings the customer may combine freely — crunchy sev, lemon squeeze, chopped onions — so choose the control type yourself (that choice IS the test);
④ the three options sit in one drawn, titled box: "Chaat toppings (pick at least one)";
⑤ a real submit button labelled "Add toppings".
SAMPLE OUTPUT — ONE THING DELIBERATELY HIDDEN
Before you peek: the spec hides one trap and one honest impossibility. The trap: "combine freely" is a control-type decision, not a decoration. The impossibility: one of the five requirements cannot actually be enforced by the HTML you know — or by any HTML at all. Which one? Decide before opening the solution.
Checkboxes, one fieldset, one honest confession.
Compare line by line — especially your control-type choice on the three toppings.
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Chaat toppings</title> </head> <body> <form action="/toppings" method="post"> <fieldset> <legend>Chaat toppings (pick at least one)</legend> <label><input type="checkbox" name="topping" value="sev"> Crunchy sev</label> <label><input type="checkbox" name="topping" value="lemon"> Lemon squeeze</label> <label><input type="checkbox" name="topping" value="onion"> Chopped onions</label> </fieldset> <button type="submit">Add toppings</button> </form> </body></html>C:\Users\student\Desktop\fswd-practice\class-07\toppings.html- ① Full skeleton — all five ritual lines present, title "Chaat toppings". Non-negotiable, in class and in the exam.
- ② Form — action="/toppings" method="post": data leaves in the envelope, not the address bar.
- ③ Control choice — checkboxes, because the toppings are independent. This line of reasoning, written in one sentence, is what a 2-mark "choose and justify the control" question wants.
- ④ Drawn, titled box — <fieldset> + <legend>, this hour's tool, first outing.
- ⑤ Real button — <button type="submit">, not a styled div. Part 6's whole argument in one line.
- The honest impossibility: "pick at least one" is in the legend, but nothing enforces it — required on one checkbox would demand that specific box, not "any one of the three". Plain HTML cannot say "at least one of these". The legend documents the rule for humans; enforcing it is a JavaScript job, and Unit 2 does exactly that. Writing "HTML cannot enforce this; JS will" is a mark-earning sentence, not a cop-out.
Notice what the spec never said: the word "checkbox". Specs describe behaviour ("combine freely") and leave the mechanism to you — the same shape as every lab problem statement and every real ticket you'll ever pick up. Train the translation now: exactly one means radio · any number means checkbox · one of many, compactly means select · free prose means textarea.
The payoff
Every piece from Classes 6–7, welded into one real form.
Class 6 gave you text, email, tel, date and labels; your homework grew order-form-start.html to four fields. Today added radios, checkboxes, select, textarea, fieldset and the real button. Watch the whole Poshtik order form assemble — every single line is something you have already written with your own hand this week. Nothing new. That's the point.
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Poshtik Campus — Order</title> </head> <body> <h1>Order your lunch</h1> <form action="/place-order" method="post"> <fieldset> <legend>Who are you?</legend> <label for="n">Name:</label> <input type="text" id="n" name="student-name" required><br> <label for="p">Phone:</label> <input type="tel" id="p" name="student-phone" required> </fieldset> <fieldset> <legend>Your dish</legend> <label><input type="radio" name="dish" value="ragi-sangati" required> Ragi Sangati Bowl</label><br> <label><input type="radio" name="dish" value="pesarattu"> Pesarattu with Sprouts</label><br> <label><input type="radio" name="dish" value="jonna-wrap"> Jonna Rotte Wrap</label> </fieldset> <fieldset> <legend>Protein add-ons</legend> <label><input type="checkbox" name="addon" value="boiled-egg"> Boiled egg</label><br> <label><input type="checkbox" name="addon" value="extra-sprouts"> Extra sprouts</label><br> </fieldset> <label for="h">Deliver to:</label> <select id="h" name="hostel" required> <option value="" disabled selected>— pick a block —</option> <option value="godavari">Godavari Block</option> <option value="krishna">Krishna Block</option> </select><br> <label for="nt">Notes:</label> <textarea id="nt" name="notes" rows="3"></textarea><br> <button type="submit">Place order</button> </form> </body></html>C:\Users\student\Desktop\fswd-practice\class-07\order-form-complete.html — the capstone file of the week. Type all 37 lines; assembling is a different muscle from reading.poshtik-campus\menu.html.One subtle line worth a second look — line 17: required sits on only the first radio of the dish group, yet the rule it creates is "this group must have a pick". For radios, required is read group-wide (any member can carry it). Compare with the checkbox trap from Part 11: required on a checkbox binds to that one box. Same attribute, two behaviours — a favourite MCQ distinction.
What would this form actually send?
Fair warning, said plainly: this is a Unit 4 preview, not today's taught content — no server exists yet, and none is needed. But you just built a form whose every control has a name and a value, and those two attributes exist for exactly one reason: to become the data a server receives. Reading a form as a data contract is a skill worth planting two units early.
THE EXERCISE — in your notebook, in prose, no code: Suppose a student named Anu fills your order-form-complete.html like this — name Anu, phone 9876543210, dish Pesarattu with Sprouts, add-ons boiled egg + extra sprouts, deliver to Krishna Block, notes "less spicy please" — and presses Place order.
① List every name=value pair that travels to the server, one per line.
② Which control contributes two pairs? Which could contribute zero?
③ For each pair, where does the value side come from — something Anu typed, or something you wrote in the markup?
The answer is seven lines of data and three sentences of reasoning.
student-phone=9876543210
dish=pesarattu
addon=boiled-egg
addon=extra-sprouts
hostel=krishna
notes=less spicy please
- ② Two pairs / zero pairs: the checkbox family contributes two pairs here (addon= repeats, once per tick) — and the same family could contribute zero: untick everything and no addon pair travels at all. The textarea can also send an empty notes= — empty, but present. Absent versus empty is a real distinction servers must handle; you'll meet it again in Unit 4.
- ③ Who wrote each value: Anu, 9876543210 and less spicy please are Anu's typing; pesarattu, boiled-egg, extra-sprouts and krishna are your value attributes. For choice controls, the developer decides the vocabulary the server hears — Anu clicked "Pesarattu with Sprouts" but the server was told pesarattu, because you decided so.
- The contract idea itself: the set of names a form sends is a promise between front-end and back-end — rename name="dish" to name="item" and a server expecting dish silently receives nothing. When Unit 4 builds that server, you'll write both sides of this promise and this page will feel like an old friend.
Now review a form you didn't write.
Professionals never ship code only its author has read — review is how bugs die young. Swap laptops with your neighbour, open their order-form-complete.html, and walk this checklist top to bottom. Copy the six lines into your notebook and tick on paper — the discipline is the point, not the boxes.
Why these six checks, and what each one catches in the wild.
- Labels catch the Class-6 sin: an unbonded label looks identical on screen and fails silently — smaller click target, mute screen reader. Only the click-test exposes it.
- Radio names catch today's drill bug — the name collision that merged dish and portion into one group. It reads correct; only behaviour betrays it. That's why the check says test, not read.
- Values catch the invisible failure: a radio without a value still works on screen, but submits a useless dish=on. Nothing visual warns you — only a review (or an angry server) does.
- Real submit catches the impostor div from Part 6 — pretty, clickable-looking, and deaf to Enter, Tab and screen readers.
- Required catches forms that accept a fully empty order — politeness rails from Class 6, verified by attempting the crime.
- Skeleton is the §5.6 ritual: quirks-mode pages fail in ways no checklist can predict, so the skeleton check guards all the others.
Notice the checklist's grammar: every check is a verifiable action ("click each label"), never a vibe ("labels look fine"). That's what separates a checklist from a hope. In Lab 2 you'll run this same list against your own real form in poshtik-campus\menu.html — before you commit it. Review, then commit: the professional order of operations, practised from week two.
Wrap
What you can do now that you couldn't this morning.
The git ledger for today: zero commits — and that's correct. Every file above lives in fswd-practice\, the sandbox that is deliberately not a repo. poshtik-campus\ hasn't changed since Lab 1, so it has nothing to commit. Lab 2 ends that streak: the order form goes into menu.html, and that day finishes with git add . then git commit -m "Add order form to menu page" — not optional.
Homework — in your sandbox.
- Extend the capstone: in order-form-complete.html, add a third fieldset titled "Portion" with two radios — Small / Regular — in their own group (name="portion"). If the dish radios stop working, you know exactly which bug you just re-created — and exactly how to fix it.
- The select upgrade: add a fourth <option> — Penna Block — to the hostel dropdown, and prove the placeholder trick still holds: reload and check "— pick a block —" cannot be re-selected once you've chosen.
- Exam rep: write the P3·Q1 model answer once from memory on paper — the error sentence plus four corrected lines — timed at three minutes.
Next class — Class 8, HTML5 structural elements: your pages stop being one long stream and gain real anatomy — header, nav, main, footer. And right after it, Lab 2: the form you assembled today gets built into the real poshtik-campus site's menu page, reviewed with today's checklist, and committed to git.