> ## Documentation Index
> Fetch the complete documentation index at: https://primer.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Pre-fill cardholder name

> Automatically fill in the cardholder name from user profile data.

Pre-populate the cardholder name field with data from your user's profile to reduce friction at checkout.

## Recipe

<Tabs>
  <Tab title="Web">
    ```javascript theme={"dark"}
    checkout.addEventListener('primer:ready', (event) => {
      const primer = event.detail;

      const user = getAuthenticatedUser();
      if (user?.fullName) {
        primer.setCardholderName(user.fullName);
      }
    });
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={"dark"}
    val checkout = rememberPrimerCheckoutController(clientToken)
    val cardFormController = rememberCardFormController(checkout)

    LaunchedEffect(cardFormController) {
        cardFormController.updateCardholderName(userProfile.fullName)
    }
    ```
  </Tab>

  <Tab title="iOS">
    ```swift theme={"dark"}
    @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)
        }
      }
    }
    ```
  </Tab>
</Tabs>

## How it works

<Tabs>
  <Tab title="Web">
    1. Listen for the `primer:ready` event to access the Primer SDK instance
    2. Retrieve the user's name from your authentication system or profile data
    3. Call `primer.setCardholderName()` with the name value

    <Info>
      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.
    </Info>
  </Tab>

  <Tab title="Android">
    1. Create a `PrimerCardFormController` using `rememberCardFormController()`
    2. Call `updateCardholderName()` with the user's name inside a `LaunchedEffect`
    3. The field will display the prefilled name and the user can edit it if needed

    <Note>
      `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.
    </Note>
  </Tab>

  <Tab title="iOS">
    1. Hold a `PrimerCheckoutSession` as a `@StateObject` and apply the `.primerCheckoutSession(_:onCompletion:)` modifier
    2. Once the session reaches `.ready`, its `cardForm` sub-session (a `PrimerCardFormSession`) becomes available -- call `updateCardholderName()` on it with the user's name
    3. The field displays the prefilled name and the user can still edit it

    <Note>
      The same approach works for other fields -- use `updateCardNumber()`, `updateExpiryDate()`, or `updateCvv()` on the `cardForm` session as needed.
    </Note>
  </Tab>
</Tabs>

## Variations

### Pre-fill from shipping address

<Tabs>
  <Tab title="Web">
    ```javascript theme={"dark"}
    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);
      }
    });
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={"dark"}
    LaunchedEffect(cardFormController) {
        cardFormController.updateCardholderName(shippingAddress.fullName)
    }
    ```
  </Tab>

  <Tab title="iOS">
    ```swift theme={"dark"}
    .onChange(of: session.phase) { phase in
      if phase == .ready {
        let fullName = "\(shippingAddress.firstName) \(shippingAddress.lastName)"
        session.cardForm?.updateCardholderName(fullName)
      }
    }
    ```
  </Tab>
</Tabs>

### 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:

<Tabs>
  <Tab title="Web">
    ```javascript theme={"dark"}
    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
      }
    });
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={"dark"}
    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),
                        )
                    }
                }
            },
        )
    }
    ```
  </Tab>

  <Tab title="iOS">
    Pre-fill the name and recompose the `cardDetails` slot with `CardFormDefaults.cardholderName` so users can edit it:

    ```swift theme={"dark"}
    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)
          }
        }
      }
    }
    ```

    <Note>
      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.
    </Note>
  </Tab>
</Tabs>

## See also

<CardGroup cols={2}>
  <Card title="Build a custom card form" icon="credit-card" href="/docs/checkout/primer-checkout/guides-and-recipes/build-custom-card-form">
    Step-by-step guide to building a fully custom card form
  </Card>

  <Card title="SDK options" icon="gear" href="/docs/checkout/primer-checkout/configuration/sdk-options">
    All available SDK configuration options
  </Card>
</CardGroup>
