Followup on #2894052: Hide add to cart form in disabled product variants: This module no longer displays a form if the product variation is disabled, consistent with standard Commerce behaviour. That is not a problem for the standard Commerce add-to-cart form because only the relevant attributes for the product variation are removed, not the entire form.

But in our case, if it is desirable to show a "product unavailable" message or something like that, there is no straightforward way to do so. It should be possible to use hook_entity_view_alter() or hook_preprocess_commerce_product_variation() to test the variation state and alter the render array to output a message, but I have not tested this.

@wassper proposed providing a form wrapper template, with appropriate twig variables to determine the state of the form.

Comments

John Pitcairn created an issue. See original summary.

zenimagine’s picture

When I disable the variations of a product and I am on the product page, the following error is displayed :

The website encountered an unexpected error. Please try again later.

TypeError: Argument 2 passed to Drupal\commerce_product\ProductVariationFieldRenderer::renderField() must implement interface Drupal\commerce_product\Entity\ProductVariationInterface, null given, called in /home/www.s1biose.com/public_html/web/modules/contrib/commerce/modules/product/src/Plugin/DsField/ProductVariationField.php on line 33 in Drupal\commerce_product\ProductVariationFieldRenderer->renderField() (line 79 of /home/www.s1biose.com/public_html/web/modules/contrib/commerce/modules/product/src/ProductVariationFieldRenderer.php) #0 /home/www.s1biose.com/public_html/web/modules/contrib/commerce/modules/product/src/Plugin/DsField/ProductVariationField.php(33): Drupal\commerce_product\ProductVariationFieldRenderer->renderField('sku', NULL, Array) #1 /home/www.s1biose.com/public_html/web/modules/contrib/ds/ds.module(365): Drupal\commerce_product\Plugin\DsField\ProductVariationField->build() #2 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/Extension/ModuleHandler.php(501): ds_entity_view_alter(Array, Object(Drupal\commerce_product\Entity\Product), Object(Drupal\Core\Entity\Entity\EntityViewDisplay)) #3 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/Entity/EntityViewBuilder.php(285): Drupal\Core\Extension\ModuleHandler->alter('commerce_produc...', Array, Object(Drupal\commerce_product\Entity\Product), Object(Drupal\Core\Entity\Entity\EntityViewDisplay)) #4 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/Entity/EntityViewBuilder.php(220): Drupal\Core\Entity\EntityViewBuilder->buildMultiple(Array) #5 [internal function]: Drupal\Core\Entity\EntityViewBuilder->build(Array) #6 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/Render/Renderer.php(376): call_user_func(Array, Array) #7 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/Render/Renderer.php(195): Drupal\Core\Render\Renderer->doRender(Array, false) #8 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(226): Drupal\Core\Render\Renderer->render(Array, false) #9 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/Render/Renderer.php(574): Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() #10 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(227): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure)) #11 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(117): Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch)) #12 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php(90): Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch)) #13 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(111): Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object(Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent), 'kernel.view', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher)) #14 /home/www.s1biose.com/public_html/vendor/symfony/http-kernel/HttpKernel.php(149): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.view', Object(Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent)) #15 /home/www.s1biose.com/public_html/vendor/symfony/http-kernel/HttpKernel.php(64): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) #16 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #17 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #18 /home/www.s1biose.com/public_html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(99): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #19 /home/www.s1biose.com/public_html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(78): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true) #20 /home/www.s1biose.com/public_html/web/core/modules/ban/src/BanMiddleware.php(50): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #21 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\ban\BanMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #22 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(50): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #23 /home/www.s1biose.com/public_html/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #24 /home/www.s1biose.com/public_html/web/core/lib/Drupal/Core/DrupalKernel.php(656): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #25 /home/www.s1biose.com/public_html/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request)) #26 {main}.

johnpitcairn’s picture

Looks like a Display Suite issue?

zenimagine’s picture

Thank you, indeed I had applied the following patch :
https://www.drupal.org/files/issues/2723689-3-add-ds-integration.patch
When I delete it, it works.

Thank you, indeed I had applied the following patch:
When I delete it, it works.

But I still have the same problem with the price and the reference that does not show up. I never succeeded in resolving this.
Commerce 2 is really very complicated.

I use "Display Suite" for displaying product pages.
I copied the file "bs-2col-stacked--commerce-product.html.twig" into the templates folder of my theme.
Here are contents :

{#
/**
 * @file
 * Bootstrap Layouts: "2 Columns (stacked)" template.
 *
 * Available layout variables:
 * - wrapper: Wrapper element for the layout container.
 * - attributes: Wrapper attributes for the layout container.
 *
 * Available region variables:
 * - top
 * - left
 * - right
 * - bottom
 *
 * Each region variable contains the following properties:
 * - wrapper: The HTML element to use to wrap this region.
 * - attributes: The HTML attributes to use on the wrapper for this region.
 * - content: The content to go inside the wrapper for this region.
 */
#}
<{{ wrapper }}{{ attributes }}>
  {{ title_suffix.contextual_links }}

  {% if top.content %}
  <{{ top.wrapper }}{{ top.attributes }}>
    {{ top.content }}
  </{{ top.wrapper }}>
  {% endif %}

  {% if left.content %}
  <{{ left.wrapper }}{{ left.attributes }}>
    {{ left.content }}
  </{{ left.wrapper }}>
  {% endif %}

  {% if right.content %}
  <{{ right.wrapper }}{{ right.attributes }}>
    {{ right.content }}
  </{{ right.wrapper }}>
  {% endif %}

  {% if bottom.content %}
  <{{ bottom.wrapper }}{{ bottom.attributes }}>
    {{ bottom.content }}
  </{{ bottom.wrapper }}>
  {% endif %}

</{{ wrapper }}>

What should I do ?

I also encounter problems with views and product variations.

It's a nightmare.

Thank you

johnpitcairn’s picture

Sorry, your support request is not relevant to this module.

The problem with the patch should be reported in the issue that provided the patch, and your other support questions should be asked in the forums or in the main commerce issue queue.

Please do not post commerce configuration or support questions in this module's issue queue.

waspper’s picture

I think providing a way to display needed information could be very useful. But first, we could decide how and what to theme. Here, some points/ideas:

1. Using a global wrapper template (this will wrap the form or the "Out of stock" message), with needed variables. This could allow using same template for several view modes, instead theming each view mode to know the status (if needed/possible), and allowing themers to know if form is enabled/disabled at top of the element.
2. Keeping default form as it's being used currently (no changes). but show a themed output only when variation is disabled. Same as previous: Allowing to theme per view_mode (if needed/possible).
3. Using a different theme for each case: if form and if disabled. Both cases they should provide needed variables, and the output must be as simple as possible.
4. More ideas? :)

Cheers.

johnpitcairn’s picture

Assigned: Unassigned » johnpitcairn

@wassper: If/when the field is refactored as a computed field, that will likely be a breaking change anyway, so version 2.0, and we can use a global wrapper then. For now I think option #2 is preferable, to avoid breaking any existing css or javascript that does not expect the form to be wrapped. Working on it.

johnpitcairn’s picture

StatusFileSize
new3 KB

Let's try this.

johnpitcairn’s picture

Oops, mismatch on the theme/template name. I don't think we need to use "field" as a prefix. This one should be good.

johnpitcairn’s picture

Issue summary: View changes
johnpitcairn’s picture

Assigned: johnpitcairn » Unassigned
Status: Active » Needs review
waspper’s picture

Last patch is working fine. I've added some improvements, to allow theming by product bundle, variation bundle and view mode. Added theming description into the README.md.

It should cover at least most of cases related to display "XYZ" message or another, depending context.

Cheers.

johnpitcairn’s picture

Status: Needs review » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.