Recipe
- Web
- Android
- iOS
checkout.addEventListener('primer:ready', (event) => {
const primer = event.detail;
const user = getAuthenticatedUser();
if (user?.fullName) {
primer.setCardholderName(user.fullName);
}
});
val checkout = rememberPrimerCheckoutController(clientToken)
val cardFormController = rememberCardFormController(checkout)
LaunchedEffect(cardFormController) {
cardFormController.updateCardholderName(userProfile.fullName)
}
@StateObject private var session = PrimerCheckoutSession(clientToken: clientToken)
var body: some View {
ScrollView {
PrimerCardForm()
}
.primerCheckoutSession(session) { state in
// Handle the terminal PrimerCheckoutState
}
.onChange(of: session.phase) { phase in
if phase == .ready {
session.cardForm?.updateCardholderName(userProfile.fullName)
}
}
}
How it works
- Web
- Android
- iOS
- Listen for the
primer:readyevent to access the Primer SDK instance - Retrieve the user’s name from your authentication system or profile data
- Call
primer.setCardholderName()with the name value
When using
setCardholderName(), you don’t need to include the <primer-input-card-holder-name> component in your form if you don’t want users to edit the name.- Create a
PrimerCardFormControllerusingrememberCardFormController() - Call
updateCardholderName()with the user’s name inside aLaunchedEffect - The field will display the prefilled name and the user can edit it if needed
updateCardholderName() sets the field value programmatically. The customer can still edit the prefilled name. The same approach works for other fields — use updateCardNumber(), updateExpiryDate(), or updateCvv() as needed.- Hold a
PrimerCheckoutSessionas a@StateObjectand apply the.primerCheckoutSession(_:onCompletion:)modifier - Once the session reaches
.ready, itscardFormsub-session (aPrimerCardFormSession) becomes available — callupdateCardholderName()on it with the user’s name - The field displays the prefilled name and the user can still edit it
The same approach works for other fields — use
updateCardNumber(), updateExpiryDate(), or updateCvv() on the cardForm session as needed.Variations
Pre-fill from shipping address
- Web
- Android
- iOS
checkout.addEventListener('primer:ready', (event) => {
const primer = event.detail;
// Get name from shipping form
const shippingName = document.getElementById('shipping-name').value;
if (shippingName) {
primer.setCardholderName(shippingName);
}
});
LaunchedEffect(cardFormController) {
cardFormController.updateCardholderName(shippingAddress.fullName)
}
.onChange(of: session.phase) { phase in
if phase == .ready {
let fullName = "\(shippingAddress.firstName) \(shippingAddress.lastName)"
session.cardForm?.updateCardholderName(fullName)
}
}
Pre-fill with editable field
If you want to pre-fill but still allow editing, include the cardholder name input and set an initial value:- Web
- Android
- iOS
checkout.addEventListener('primer:ready', (event) => {
const primer = event.detail;
const user = getAuthenticatedUser();
if (user?.fullName) {
// Pre-fill the value
primer.setCardholderName(user.fullName);
// The <primer-input-card-holder-name> component will show this value
// and users can still edit it
}
});
val state by checkout.state.collectAsStateWithLifecycle()
LaunchedEffect(state) {
when (state) {
is PrimerCheckoutState.Success -> { }
is PrimerCheckoutState.Failure -> { }
else -> Unit
}
}
PrimerCheckoutHost(
checkout = checkout,
) {
val cardFormController = rememberCardFormController(checkout)
LaunchedEffect(cardFormController) {
cardFormController.updateCardholderName(userProfile.fullName)
}
PrimerCardForm(
controller = cardFormController,
cardDetails = {
Column {
CardFormDefaults.CardholderField(cardFormController)
Spacer(Modifier.height(8.dp))
CardFormDefaults.CardNumberField(cardFormController)
Spacer(Modifier.height(8.dp))
Row(Modifier.fillMaxWidth()) {
CardFormDefaults.ExpiryField(
cardFormController,
Modifier.weight(1f),
)
Spacer(Modifier.width(8.dp))
CardFormDefaults.CvvField(
cardFormController,
Modifier.weight(1f),
)
}
}
},
)
}
Pre-fill the name and recompose the
cardDetails slot with CardFormDefaults.cardholderName so users can edit it:struct PrefilledCardFormScreen: View {
@StateObject private var session: PrimerCheckoutSession
let userProfile: UserProfile
init(clientToken: String, userProfile: UserProfile) {
_session = StateObject(wrappedValue: PrimerCheckoutSession(clientToken: clientToken))
self.userProfile = userProfile
}
var body: some View {
ScrollView {
PrimerCardForm(cardDetails: { formSession in
VStack(spacing: 16) {
CardFormDefaults.cardholderName(formSession)
CardFormDefaults.cardNumber(formSession)
HStack(spacing: 12) {
CardFormDefaults.expiryDate(formSession)
CardFormDefaults.cvv(formSession)
}
CardFormDefaults.cardNetwork(formSession)
}
.padding()
})
}
.primerCheckoutSession(session) { state in
// Handle the terminal PrimerCheckoutState
}
.onChange(of: session.phase) { phase in
if phase == .ready {
session.cardForm?.updateCardholderName(userProfile.fullName)
}
}
}
}
When you recompose the individual card fields, add
CardFormDefaults.cardNetwork(formSession) so co-badged cards still get a network selector — the built-in one is suppressed once you replace the default cardDetails section.See also
Build a custom card form
Step-by-step guide to building a fully custom card form
SDK options
All available SDK configuration options