How to add a custom form field on the PrestaShop product page using hook

In this blog, we will learn how to implement a new custom form field on the Product Page using Symfony services and components. So, we will define our own Symfony services in the module and will use existing components.

Here, we are showing the process step by step with an example module ‘wkdemo‘

Step 1: Create the module class

Here, we have created the module class file “wkdemo/wkdemo.php“

In this class, we are initializing the module, product controllers tab, and form fields.

declare(strict_types=1);

use PrestaShopModuleWkDemoFormModifierProductFormModifier;
use PrestaShopPrestaShopCoreDomainProductValueObjectProductId;

class WkDemo extends Module
{
    public function __construct()
    {
        $this->name = 'wkdemo';
        $this->tab = 'front_office_features';
        $this->version = '1.0.0';
        $this->need_instance = 0;
        $this->bootstrap = true;
        parent::__construct();
        $this->displayName = $this->l('Webkul');
        $this->description = $this->l('Form types within PrestaShop');
        $this->ps_versions_compliancy = ['min' => '8.1', 'max' => _PS_VERSION_];
    }

    /**
     * @return bool
     */
    public function install()
    {
        return parent::install() && $this->registerHook(['actionProductFormBuilderModifier']);
    }
    
    /**
     * Modify product form builder
     *
     * @param array $params
     */
    public function hookActionProductFormBuilderModifier(array $params): void
    {
        /** @var ProductFormModifier $productFormModifier */
        $productFormModifier = $this->get(ProductFormModifier::class);
        $productId = isset($params['id']) ? new ProductId((int) $params['id']) : null;
        $productFormModifier->modify($productId, $params['form_builder']);
    }
}

Step 2: Define the service

Create a services.yml file inside the wkdemo/config/services.yml folder

In the given code, we have defined our own services. These will be used for form creation and form handling. Service is created inside the wkdemo/src/Form/Modifier folder

services:
    PrestaShopModuleWkDemoFormModifierProductFormModifier:
        autowire: true
        public: true
        arguments:
            $formBuilderModifier: '@form.form_builder_modifier'

Step 3: Create a service class

Now create a service class in the wkdemo/src/Form/Modifier/ProductFormModifier.php

declare(strict_types=1);

namespace PrestaShopModuleWkDemoFormModifier;

use PrestaShopPrestaShopCoreDomainProductValueObjectProductId;
use PrestaShopBundleFormFormBuilderModifier;
use SymfonyComponentFormExtensionCoreTypeTextType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentTranslationTranslatorInterface;

final class ProductFormModifier
{
    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var FormBuilderModifier
     */
    private $formBuilderModifier;

    /**
     * @param TranslatorInterface $translator
     * @param FormBuilderModifier $formBuilderModifier
     */
    public function __construct(
        TranslatorInterface $translator,
        FormBuilderModifier $formBuilderModifier
    ) {
        $this->translator = $translator;
        $this->formBuilderModifier = $formBuilderModifier;
    }

    /**
     * @param ProductId|null $productId
     * @param FormBuilderInterface $productFormBuilder
     */
    public function modify(
        ?ProductId $productId,
        FormBuilderInterface $productFormBuilder
    ): void {
        $data['seo'] = 'Test data';
        $data['price'] = '0';
        $this->modifyDescriptionTab($data, $productFormBuilder);
    }

    private function modifyDescriptionTab($data, FormBuilderInterface $productFormBuilder): void
    {
        $descriptionTabFormBuilder = $productFormBuilder->get('seo');
        $this->formBuilderModifier->addAfter(
            $descriptionTabFormBuilder,
            'tags',
            'demo_module_custom_field',
            TextType::class,
            [
                // you can remove the label if you dont need it by passing 'label' => false
                'label' => $this->translator->trans('Demo custom field', [], 'Modules.WkDemo.Admin'),
                // customize label by any html attribute
                'label_attr' => [
                    'title' => 'h2',
                    'class' => 'text-info',
                ],
                'attr' => [
                    'placeholder' => $this->translator->trans('Your example text here', [], 'Modules.WkDemo.Admin'),
                ],
                // this is just an example, but in real case scenario you could have some data provider class to wrap more complex cases
                'data' => $data['seo'] ,
                'empty_data' => '',
                'form_theme' => '@PrestaShop/Admin/TwigTemplateForm/prestashop_ui_kit_base.html.twig',
            ]
        );
        
        $pricingTabFormBuilder = $productFormBuilder->get('pricing');
        $this->formBuilderModifier->addAfter(
            $pricingTabFormBuilder,
            'wholesale_price',
            'demo_module_pricing_field',
            TextType::class,
            [
                // you can remove the label if you dont need it by passing 'label' => false
                'label' => $this->translator->trans('Extra price for demo', [], 'Modules.WkDemo.Admin'),
                // customize label by any html attribute
                'label_attr' => [
                    'title' => 'h2',
                    'class' => 'text-info',
                ],
                'attr' => [
                    'placeholder' => $this->translator->trans('0', [], 'Modules.WkDemo.Admin'),
                ],
                // this is just an example, but in real case scenario you could have some data provider class to wrap more complex cases
                'data' => $data['price'],
                'empty_data' => '',
                'form_theme' => '@PrestaShop/Admin/TwigTemplateForm/prestashop_ui_kit_base.html.twig',
            ]
        );
    }
}

The above module uses a Form Builder Modifier (FormBuilderModifier) and adds two text field
1- “Extra price for demo” in the Pricing tab, after the existing Cost price form element
2- “Demo custom field” in the SEO tab, after the existing Tags form element
to the SEO tab form, after the existing tags form element.

The above module gives the result as shown below custom form fields:

SEO Custom form field

NOTE: “actionProductFormBuilderModifier” supports in PrestaShop Version V8.1.0

So, this hook will work in the below PrestaShop Versions.

That’s all.

If you are facing any issues or doubts in the above process, please feel free to contact us in the comment section.

I would be happy to help.

Also, you can explore our PrestaShop Development Services and a large range of quality PrestaShop Modules.


Source link