Skip to content

UR-4862: Fix multi-step form rendering step 1 fields inside step 2 - #1404

Open
saurab018 wants to merge 1 commit into
developfrom
UR-4862-multipart-registration-form-not-working-correctly
Open

UR-4862: Fix multi-step form rendering step 1 fields inside step 2#1404
saurab018 wants to merge 1 commit into
developfrom
UR-4862-multipart-registration-form-not-working-correctly

Conversation

@saurab018

Copy link
Copy Markdown
Contributor

Multi-step registration forms rendered step 1's fields inside step 2. On a reported form the first step showed only its section heading while every personal field (First Name → Mobile Phone) appeared on step 2 above the employment fields, even though the step configuration in the builder was correct.

Row ids are creation-order identifiers that never renumber, while user_registration_form_row_ids stores rows in visual order. The builder hardcodes the first row of every form to data-row-id="0", so dragging any later-created row above it (adding a Section Title header, for example) moves row 0 off index 0. At that point ! empty( $row_ids[ $index ] ) is false for row 0 — the meta stores ids as strings, and "0" is falsy too — and the row silently falls back to $index, stamping it with a different row's id. The multi-step addon then wraps it in whichever part owns that id. Rows now keep their real id regardless of position, so each one lands in its configured step.

Changes proposed in this Pull Request:

  • templates/form-registration.php — the row id guard changes from ! empty( $row_ids[ $index ] ) to ! empty( $row_ids ) && isset( $row_ids[ $index ] ). The $index fallback is preserved for legacy forms that have no user_registration_form_row_ids meta at all, which was the fallback's actual purpose; it just no longer swallows a legitimate id of 0.

  • Multi-step addon unchangeddisplay_before_row() already resolves parts correctly via in_array( $row_id, $rows, true ). It was acting on a corrupted $row_id, not choosing the wrong part.

  • Stored form data unchanged — no migration. The multi-step configuration was already correct on affected forms; only the rendered data-row-id was wrong.

Note

This is the only place the bug can occur. The three other consumers of $row_idsclass-ur-users-menu.php:892, class-ur-members-menu.php:1631 and templates/myaccount/form-edit-profile.php:364 — already guard with ! empty( $row_ids ) && isset( $row_ids[ $index ] ); this template was the lone straggler, and the fix adopts their existing pattern rather than inventing one. Row-level conditional logic a few lines below compares $row_id == $individual_row_data->row_id and was misfiring on the same corrupted value, so it is fixed by the same line.

Row id resolution

flowchart LR
    A["Render row<br/>at visual index N"] --> B{"row_ids meta<br/>present?"}
    B -- no --> C["Fall back to<br/>$index"]
    B -- yes --> D{"Changed:<br/>isset row_ids[N]?"}
    D -- no --> C
    D -- yes --> E["Changed:<br/>use real row id<br/>including 0"]
    E --> F["data-row-id correct,<br/>row lands in its<br/>configured step"]
    C --> F
    D:::changed
    E:::changed
    classDef changed fill:#9a6700,color:#fff,stroke:#5c3d00,stroke-width:3px,stroke-dasharray:6 3
Loading

How to test the changes in this Pull Request:

  1. Create a registration form with two rows. Put username/name fields in the first row, password fields in the second. Save.

  2. Add a new row, drag it above the existing first row, and drop a Section Title field into it. Save. This is what makes row 0 stop being the first row — confirm it with:

    wp post meta get FORM_ID user_registration_form_row_ids
    

    Expect: the array does not start with "0" — e.g. ["2","0","1"].

  3. Enable Page Options (multi-step), create two steps, and assign the rows so that row 0's fields belong to step 1.

  4. View the form (/?ur_preview=true&form_id=FORM_ID) and inspect the rendered rows:

    [...document.querySelectorAll('.ur-form-row')].map(r => r.getAttribute('data-row-id'))

    Expect: every id is distinct and "0" is present. Before the fix this printed a duplicate id and no "0" — the row whose real id was 0 was stamped with the id of the row sitting at its index.

  5. Check which step each row landed in:

    [...document.querySelectorAll('.user-registration-part')].map(p => p.className + ' -> ' + [...p.querySelectorAll('input')].map(i => i.name).join());

    Expect: row 0's fields sit in user-registration-part-1. Before the fix they sat in part 2, and step 2 could render with no fields of its own at all.

  6. Fill step 1 and click Next.

    Expect: step 1 hides, step 2 shows, and step 2 contains only its configured fields.

  7. Negative case — open a form that has never had its rows reordered (row_ids starts at "0", or the meta is absent entirely).

    Expect: unchanged rendering; ids still ascend from 0 and every step holds the same fields as before this patch.

  8. Regression check on row conditional logic — on the reordered form from step 2, set a conditional rule on a row and trigger it.

    Expect: the intended row shows/hides. Before the fix the rule applied to whichever row shared the corrupted id.

Types of changes:

  • Bug fix (non-breaking change which fixes an issue)

Other information:

Verified with a controlled A/B on a local WordPress install (UR Pro 6.2.7, Multi-Step 1.3.2) against a form with row id 1 at visual index 0 and row id 0 at index 1, parts configured as part1=[1], part2=[0]. The template line was the only variable changed between runs:

before: idx0 data-row-id="1" -> part-1 | idx1 data-row-id="1" -> part-1  (step 2 empty)
after : idx0 data-row-id="1" -> part-1 | idx1 data-row-id="0" -> part-2  (Next advances correctly)

No automated test was added — the affected code is inline markup in a template with no existing test harness covering it.

Changelog entry

Fix - Multi-step registration form rendering the first step's fields inside the second step when form rows had been reordered.

Ref: UR-4862

Rows are identified by a creation-order id that never renumbers, while
user_registration_form_row_ids stores them in visual order. The first row
of every form is hardcoded to id 0, so as soon as any later-created row is
dragged above it, row 0 leaves index 0.

At that point `! empty( $row_ids[ $index ] )` evaluates false for row 0
(both int 0 and the string "0" that the meta actually stores) and the row
silently falls back to `$index`, stamping it with another row's id. The
multi-step addon then wraps it in whichever part owns that id, and row
level conditional logic matches the wrong row for the same reason.

Guard on the array instead of the element so a legitimate row id of 0 is
kept, matching the pattern already used in class-ur-users-menu.php.
@saurab018 saurab018 self-assigned this Aug 26, 2026
@tg-autopilot

Copy link
Copy Markdown
Contributor

Build for 61ca6adf is ready 🛎️

⬇️ Download user-registration-5.2.7.zip (8.1M)

Installs directly via Plugins → Add New → Upload Plugin.
Link expires in 30 days · updated Aug 26, 2026 9:16 AM +0545

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants