ChangeCredential
ChangeCredential renders a row that opens a full-screen form on tap, letting a signed-in user set a new value for one of their own credentials. The form collects only a new value and its confirmation, checks it against the applicable rules, and posts the change via ThunderIDClient.updateUserCredentials.
It reads the rules it needs from the user type schema (GET /users/me/meta), fetched when the widget mounts. The default label comes from the credential attribute's own displayName in that schema, so it always matches whatever an admin named it there.
By default it manages the password credential. To manage a different one, for example a PIN declared on the user type schema, set attribute; render one instance per credential to let a user manage more than one.
ChangeCredential requires a ThunderIDProvider ancestor.
ChangeCredential collects only a new value and its confirmation, not the account's existing value. The self-service credential write path does not verify the current value today, so asking for one would only teach the user a false sense of security.
Usage
import 'package:thunderid_flutter/thunderid_flutter.dart';
class SecuritySection extends StatelessWidget {
const SecuritySection({super.key});
@override
Widget build(BuildContext context) {
return const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Security'),
ChangeCredential(),
],
);
}
}
Managing a Different Credential
Render one instance per credential the user type schema declares, keyed by its attribute name:
Column(
children: const [
ChangeCredential(),
ChangeCredential(attribute: 'pin'),
],
)
ChangeCredential Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
attribute | String | The credential attribute this instance manages, any attribute the user type schema declares credential: true for. Defaults to 'password'. | |
onSuccess | VoidCallback? | Called after the credential has been changed successfully. | |
showDivider | bool | Whether to draw the row's bottom divider, matching UserProfile's field rows. Set to false on the last credential row in a list to avoid a trailing divider. Defaults to true. |
Behavior
- Renders as a row that opens a full-screen form on tap, and closes again on a successful change.
- If the schema does not declare
attributeas a credential, the row's Update link is hidden and its value text shows an unavailable message instead. - If the schema declares a
regexfor the attribute, the form enforces it and shows a requirement hint on the new-value field when the value does not match. - The new-value and confirmation fields are obscured, with a trailing toggle to reveal the typed value.
- Closing the form without saving clears the entered values.
BaseChangeCredential
BaseChangeCredential is the unstyled builder variant. It manages the schema lookup, validation, and the network call, and passes the current ChangeCredentialState to a builder function, giving full control over the form layout.
BaseChangeCredential(
attribute: 'pin',
onSuccess: () => print('PIN updated'),
builder: (context, state) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (state.error != null) Text(state.error!),
TextField(
obscureText: true,
onChanged: state.onNewValueChanged,
decoration: InputDecoration(labelText: 'New ${state.credentialDisplayName}'),
),
TextField(
obscureText: true,
onChanged: state.onConfirmValueChanged,
decoration: InputDecoration(labelText: 'Confirm New ${state.credentialDisplayName}'),
),
ElevatedButton(
onPressed: state.evaluation.isValid && !state.loading ? state.submit : null,
child: Text(state.loading ? 'Saving…' : 'Save'),
),
],
);
},
)
BaseChangeCredential Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
attribute | String | The credential attribute to manage. Defaults to 'password'. | |
credentialDisplayName | String? | Overrides the display name resolved from the schema. ChangeCredential does not expose this; it is an escape hatch for callers building their own UI without schema context. | |
policyRegex | String? | Overrides the schema-derived validation regex. | |
onSuccess | VoidCallback? | Called after a successful credential change. | |
onError | VoidCallback? | Called when a change fails. | |
builder | Widget Function(BuildContext, ChangeCredentialState) | ✅ | Renders the form from the current state. |
ChangeCredentialState
| Property/Method | Type | Description |
|---|---|---|
credentialDisplayName | String | The resolved display name for the credential. |
newValue | String | The new value entered so far. |
confirmValue | String | The re-entered confirmation value. |
onNewValueChanged | ValueChanged<String> | Updates newValue and re-evaluates the form. |
onConfirmValueChanged | ValueChanged<String> | Updates confirmValue and re-evaluates the form. |
error | String? | Form-level error from the last failed submission. |
loading | bool | true while a submission is in flight. |
success | bool | true after the last submission succeeded. |
unavailable | bool | true when the schema does not declare attribute as a credential. |
evaluation | CredentialFormEvaluation | Derived validation state: isValid, confirmMatches, meetsPolicy, patternChecked, patternPassed. |
fieldError(field) | String? Function(CredentialField) | The error for CredentialField.newValue or CredentialField.form, if any. |
submit() | Future<void> Function() | Submits the current values. No-ops while invalid, loading, or unavailable. Resolves once the submission settles; read success/error/fieldError afterward for the outcome. |
resetValues() | void Function() | Clears newValue and confirmValue. Field/form errors are left as-is; they only clear at the start of the next submit(). |