2

Goal

With Drupal Commerce, my goal is to have a customizable product with persistent user entered text.

I have added a text field to the order item type and I can see the custom field in the "add to cart" form. When customer enters a value in that field and adds the product to the cart, I can see the value of that field in the cart form view.

I want to have a link to the purchased entity in the cart form view so I checked "Link label to the referenced entity" in the view field configuration.

When I hit that link, I get back to my product page, with the correct variation selected, but the custom text field will be empty.

Question

How can I make this custom text field persistent, that is, "save" its value so that when I click the item link in the cart view, I get back to the product variation with the custom text field already filled in?

Note: I could have multiple products/variations in the cart, each with a different custom text so I need to keep the value on the order item level.

What I have tried

I thought about having that custom text field value as a parameter in the cart form view purchased entity link URL so I tried to rewrite the output of that field/link, but I don't have access to the product entity from that view and I'd need it to compute the new URL... so that won't work.

Any idea?

1 Answer 1

1

I couldn't find a more elegant way but this works for me.

First I rebuild the purchased entity link in the commerce cart form view to include the custom text field value as a parameter in the link URL for when I navigate back from the cart to the product variation:

/**
 * Implements hook_preprocess_views_view_field().
 */
function MYMODULE_preprocess_views_view_field(&$variables) {

  $view = $variables['view'];
  $field = $variables['field'];

  // Commerce cart form
  if (isset($view) && ($view->id() === 'commerce_cart_form')) {

    switch($field->field) {
      case 'purchased_entity':

        // Get purchased entity
        $purchased_entity = $variables['row']->_relationship_entities['order_items']->purchased_entity->getValue();
        $purchased_entity_id = $purchased_entity[0]['target_id'];

        // Load product variation
        $product_variation = $variation = ProductVariation::load($purchased_entity_id);

        // Get product variation URL
        $url = Url::fromUserInput($product_variation->toLink()->getUrl()->toString());

        // Get custom field value
        $custom_field = $variables['row']->_relationship_entities['order_items']->field_custom->getValue();

        // Rebuild url with variation & custom field value
        $url->setOption('query', [
          'v' => $purchased_entity_id,
          'custom' => $custom_field[0]['value'],
        ]);

        // Output
        $variables['output'] = Link::fromTextAndUrl(t($product_variation->label()), $url);

        break;
    }
  }
}

This will output a link like /product/1?v=2&custom=MYVALUE

And then on the product add to cart form, if the param is in the URL, I set the default value of the custom field:

/**
 * Implements hook_form_alter().
 */
function MYMODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {

  if (strpos($form_id, 'commerce_order_item_add_to_cart_form_commerce_product_') !== false) {

    // Set custom text form field value from URL
    $form['field_custom']['widget'][0]['value']['#default_value'] = \Drupal::request()->query->get('custom');
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.