Theory (simple)
In a multi-step OTP registration page, the same form is submitted many times (Send OTP, Verify OTP, Phone OTP, Register).
On some submits, the text field may come as blank (user didn’t retype it, browser didn’t send it, etc.).
So the correct solution is:
Save the field value into AuthenticationSessionModel (auth note) on every submit
While rendering the page, read it back from session
Send it to FTL using setAttribute()
In FTL input, set value="${fieldValue!""}" so it never becomes null/empty on refresh
A) Add one new constant (top of class)
private static final String NOTE_NAME_VALUE = "NOTE_NAME_VALUE";
✅ B) Update render() to set nameValue for the template
Replace your current render() with this corrected version (only added parts are name-related + fixed phone attributes)
String nameValue = safe(s.getAuthNote(NOTE_NAME_VALUE));
.setAttribute("nameValue", nameValue)
private Response render(AuthenticationFlowContext context,
List<Map<String, String>> countries,
String userType,
boolean emailOtpSent,
boolean emailVerified,
String emailValue,
boolean phoneOtpSent,
boolean phoneVerified,
String phoneRaw,
String phoneDialCode,
String phoneChannel,
String errorMsg) {
AuthenticationSessionModel s = context.getAuthenticationSession();
// ✅ NAME: always take from session (persist across refresh))=====LOOK AT PLACE
String nameValue = safe(s.getAuthNote(NOTE_NAME_VALUE));
// ✅ PHONE: always take from session if missing
String sessPhoneRaw = safe(s.getAuthNote(NOTE_PHONE_RAW));
String sessPhoneDial = safe(s.getAuthNote(NOTE_PHONE_DIAL_CODE));
String sessPhoneChan = safe(s.getAuthNote(NOTE_PHONE_CHANNEL));
if (phoneRaw == null || phoneRaw.isBlank()) phoneRaw = sessPhoneRaw;
if (phoneDialCode == null || phoneDialCode.isBlank()) phoneDialCode = sessPhoneDial;
if (phoneChannel == null || phoneChannel.isBlank()) phoneChannel = sessPhoneChan;
String phoneE164 = safe(s.getAuthNote(NOTE_PHONE_VALUE)); // stored e164
var form = context.form()
.setAttribute("userType", userType)
.setAttribute("isPartner", "partner".equalsIgnoreCase(userType))
.setAttribute("countries", countries)
.setAttribute("apiBase", new CountryFetcher().resolveLaravelApiBase(context))
// ✅ NAME (new)=====LOOK AT PLACE
.setAttribute("nameValue", nameValue)
// EMAIL
.setAttribute("emailOtpSent", emailOtpSent)
.setAttribute("emailVerified", emailVerified)
.setAttribute("emailValue", emailValue)
// PHONE
.setAttribute("phoneOtpSent", phoneOtpSent)
.setAttribute("phoneVerified", phoneVerified)
.setAttribute("phoneRaw", phoneRaw)
.setAttribute("phoneDialCode", phoneDialCode)
.setAttribute("phoneE164", phoneE164) // ✅ use stored e164 (don’t rebuild)
.setAttribute("phoneChannel", phoneChannel);
if (errorMsg != null && !errorMsg.isBlank()) {
form.setError(errorMsg);
}
return form.createForm("register-start.ftl");
}
✅ C) In action() store name into session on EVERY submit (top section)
Right after you read:
String name = safe(formData.getFirst("name"));
String username = safe(s.getAuthNote(NOTE_NAME_VALUE));
Add this immediately:
// ✅ persist name when user enters it
if (!name.isBlank()) {
s.setAuthNote(NOTE_NAME_VALUE, name);
} else {
// ✅ fallback to stored name
name = username;
}
System.out.println("[RouteByHint] name(afterPersist)=" + name);
Now name will not become blank unless user never typed it.
✅ D) Update FTL Name field to show saved value
In your register-start.ftl, replace the Name input with:
To show saved value MUST DO in render methods
String nameValue = safe(s.getAuthNote(NOTE_NAME_VALUE));
.setAttribute("nameValue", nameValue)
<label class="ms-rs-label">
<#if isPartnerResolved>Name of Partner<#else>Name</#if>
</label>
<input class="ms-rs-input"
type="text"
name="name"
value="${nameValue!""}"
placeholder="Enter your company or full name"
required />
Top comments (0)