I would like to add a tab with a contact form with additional fields.
Would you tell me the best way without installing an extension?
I have tried like this:
1. Add contact form to the tab
<block class="Magento\Catalog\Block\Product\View\Description" name="product.info.details" template="Magento_Catalog::product/view/details.phtml" after="product.info.media">... ...
<block class="Magento\Contact\Block\ContactForm" name="contactForm" template="Vendor_Theme::productform.phtml"> <container name="form.additional.info" label="Form Additional Info"/> </block>
</block>...</block>
However doing this it submits an contact form and it redirects to the contact us page. I would like to submit a form with additional fields and after submitting, staying on the same page.
Solved! Go to Solution.
You need to override Contact Post Controller because by default it redirects to contact/index
$this->_redirect('contact/index'); needs to be changed to $this->_redirect->getRefererUrl(); in file vendor/magento/module-contact/Controller/Index/Post.php
Code for controller override is as follows :
app/code/Custom/Contact/registration.php
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Custom_Contact', __DIR__);
app/code/Custom/Contact/etc/module.xml
<?xml version="1.0" encoding="UTF-8"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Custom_Contact" setup_version="1.0.0"> <sequence> <module name="Magento_Contact"/> </sequence> </module> </config>
app/code/Custom/Contact/etc/di.xml
<?xml version="1.0" encoding="UTF-8"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <preference for="Magento\Contact\Controller\Index\Post" type="Custom\Contact\Controller\Index\Post" /> </config>
app/code/Custom/Contact/Controller/Index/Post.php
<?phpnamespace Custom\Contact\Controller\Index; use Magento\Framework\App\Request\DataPersistorInterface; use Magento\Framework\App\ObjectManager; class Post extends \Magento\Contact\Controller\Index\Post{ /** * @var DataPersistorInterface */ private $dataPersistor; /** * Post user question * * @return void * @throws \Exception */ public function execute() { $post = $this->getRequest()->getPostValue(); if (!$post) { $this->_redirect('*/*/'); return; } $this->inlineTranslation->suspend(); try { $postObject = new \Magento\Framework\DataObject(); $postObject->setData($post); $error = false; if (!\Zend_Validate::is(trim($post['name']), 'NotEmpty')) { $error = true; } if (!\Zend_Validate::is(trim($post['comment']), 'NotEmpty')) { $error = true; } if (!\Zend_Validate::is(trim($post['email']), 'EmailAddress')) { $error = true; } if (\Zend_Validate::is(trim($post['hideit']), 'NotEmpty')) { $error = true; } if ($error) { throw new \Exception(); } $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; $transport = $this->_transportBuilder ->setTemplateIdentifier($this->scopeConfig->getValue(self::XML_PATH_EMAIL_TEMPLATE, $storeScope)) ->setTemplateOptions( [ 'area' => \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE, 'store' => \Magento\Store\Model\Store::DEFAULT_STORE_ID, ] ) ->setTemplateVars(['data' => $postObject]) ->setFrom($this->scopeConfig->getValue(self::XML_PATH_EMAIL_SENDER, $storeScope)) ->addTo($this->scopeConfig->getValue(self::XML_PATH_EMAIL_RECIPIENT, $storeScope)) ->setReplyTo($post['email']) ->getTransport(); $transport->sendMessage(); $this->inlineTranslation->resume(); $this->messageManager->addSuccess( __('Thanks for contacting us with your comments and questions. We\'ll respond to you very soon.') ); $this->getDataPersistor()->clear('contact_us'); $this->_redirect->getRefererUrl(); return; } catch (\Exception $e) { $this->inlineTranslation->resume(); $this->messageManager->addError( __('We can\'t process your request right now. Sorry, that\'s all we know.') ); $this->getDataPersistor()->set('contact_us', $post); $this->_redirect->getRefererUrl(); return; } } /** * Get Data Persistor * * @return DataPersistorInterface */ private function getDataPersistor() { if ($this->dataPersistor === null) { $this->dataPersistor = ObjectManager::getInstance() ->get(DataPersistorInterface::class); } return $this->dataPersistor; } }
You need to override Contact Post Controller because by default it redirects to contact/index
$this->_redirect('contact/index'); needs to be changed to $this->_redirect->getRefererUrl(); in file vendor/magento/module-contact/Controller/Index/Post.php
Code for controller override is as follows :
app/code/Custom/Contact/registration.php
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Custom_Contact', __DIR__);
app/code/Custom/Contact/etc/module.xml
<?xml version="1.0" encoding="UTF-8"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Custom_Contact" setup_version="1.0.0"> <sequence> <module name="Magento_Contact"/> </sequence> </module> </config>
app/code/Custom/Contact/etc/di.xml
<?xml version="1.0" encoding="UTF-8"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <preference for="Magento\Contact\Controller\Index\Post" type="Custom\Contact\Controller\Index\Post" /> </config>
app/code/Custom/Contact/Controller/Index/Post.php
<?phpnamespace Custom\Contact\Controller\Index; use Magento\Framework\App\Request\DataPersistorInterface; use Magento\Framework\App\ObjectManager; class Post extends \Magento\Contact\Controller\Index\Post{ /** * @var DataPersistorInterface */ private $dataPersistor; /** * Post user question * * @return void * @throws \Exception */ public function execute() { $post = $this->getRequest()->getPostValue(); if (!$post) { $this->_redirect('*/*/'); return; } $this->inlineTranslation->suspend(); try { $postObject = new \Magento\Framework\DataObject(); $postObject->setData($post); $error = false; if (!\Zend_Validate::is(trim($post['name']), 'NotEmpty')) { $error = true; } if (!\Zend_Validate::is(trim($post['comment']), 'NotEmpty')) { $error = true; } if (!\Zend_Validate::is(trim($post['email']), 'EmailAddress')) { $error = true; } if (\Zend_Validate::is(trim($post['hideit']), 'NotEmpty')) { $error = true; } if ($error) { throw new \Exception(); } $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; $transport = $this->_transportBuilder ->setTemplateIdentifier($this->scopeConfig->getValue(self::XML_PATH_EMAIL_TEMPLATE, $storeScope)) ->setTemplateOptions( [ 'area' => \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE, 'store' => \Magento\Store\Model\Store::DEFAULT_STORE_ID, ] ) ->setTemplateVars(['data' => $postObject]) ->setFrom($this->scopeConfig->getValue(self::XML_PATH_EMAIL_SENDER, $storeScope)) ->addTo($this->scopeConfig->getValue(self::XML_PATH_EMAIL_RECIPIENT, $storeScope)) ->setReplyTo($post['email']) ->getTransport(); $transport->sendMessage(); $this->inlineTranslation->resume(); $this->messageManager->addSuccess( __('Thanks for contacting us with your comments and questions. We\'ll respond to you very soon.') ); $this->getDataPersistor()->clear('contact_us'); $this->_redirect->getRefererUrl(); return; } catch (\Exception $e) { $this->inlineTranslation->resume(); $this->messageManager->addError( __('We can\'t process your request right now. Sorry, that\'s all we know.') ); $this->getDataPersistor()->set('contact_us', $post); $this->_redirect->getRefererUrl(); return; } } /** * Get Data Persistor * * @return DataPersistorInterface */ private function getDataPersistor() { if ($this->dataPersistor === null) { $this->dataPersistor = ObjectManager::getInstance() ->get(DataPersistorInterface::class); } return $this->dataPersistor; } }
Thank you for your reply.
I am not able to test it from my PC as I haven't installed Linux onto my PC.
I will test it tomorrow.
So how can I call this module from xml file?
I have created a module Custom_Module, and in the Theme I changed block class to:
<block class="Custom\Contact\Block\ContactForm" >
So the xml file would be:
<block class="Magento\Catalog\Block\Product\View\Description" name="product.info.details" template="Magento_Catalog::product/view/details.phtml" after="product.info.media">... ... <block class="Custom\Contact\Block\ContactForm" name="contactForm" template="Vendor_Theme::productform.phtml"> <container name="form.additional.info" label="Form Additional Info"/> </block> </block>...</block>
Is this right?
I have shared all the steps to create a custom module and files with code, please follow as it is and change according to your requirements.
Receiving an error:
Notice: Undefined property: Custom\Contact\Controller\Index\Post\Interceptor::$inlineTranslation
Exception #0 (Exception): Notice: Undefined property: Custom\Contact\Controller\Index\Post\Interceptor::$inlineTranslation in /var/www/vhosts/appliancespares-direct.co.uk/htdocs/app/code/Custom/Contact/Controller/Index/Post.php on line 28 #0 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/app/code/Custom/Contact/Controller/Index/Post.php(28): Magento\Framework\App\ErrorHandler->handler(8, 'Undefined prope...', '/var/www/vhosts...', 28, Array) #1 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/generated/code/Custom/Contact/Controller/Index/Post/Interceptor.php(24): CUstom\Contact\Controller\Index\Post->execute() #2 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/framework/App/Action/Action.php(107): CUstom\Contact\Controller\Index\Post\Interceptor->execute() #3 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/module-contact/Controller/Index.php(67): Magento\Framework\App\Action\Action->dispatch(Object(Magento\Framework\App\Request\Http)) #4 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/framework/Interception/Interceptor.php(58): Magento\Contact\Controller\Index->dispatch(Object(Magento\Framework\App\Request\Http)) #5 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/framework/Interception/Interceptor.php(138): Custom\Contact\Controller\Index\Post\Interceptor->___callParent('dispatch', Array) #6 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/framework/Interception/Interceptor.php(153): Custom\Contact\Controller\Index\Post\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http)) #7 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/generated/code/custom/Contact/Controller/Index/Post/Interceptor.php(39): Custom\Contact\Controller\Index\Post\Interceptor->___callPlugins('dispatch', Array, Array) #8 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/framework/App/FrontController.php(55): Custom\Contact\Controller\Index\Post\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http)) #9 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/framework/Interception/Interceptor.php(58): Magento\Framework\App\FrontController->dispatch(Object(Magento\Framework\App\Request\Http)) #10 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\App\FrontController\Interceptor->___callParent('dispatch', Array) #11 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/module-store/App/FrontController/Plugin/RequestPreprocessor.php(94): Magento\Framework\App\FrontController\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http)) #12 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/framework/Interception/Interceptor.php(135): Magento\Store\App\FrontController\Plugin\RequestPreprocessor->aroundDispatch(Object(Magento\Framework\App\FrontController\Interceptor), Object(Closure), Object(Magento\Framework\App\Request\Http)) #13 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/module-page-cache/Model/App/FrontController/BuiltinPlugin.php(73): Magento\Framework\App\FrontController\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http)) #14 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/framework/Interception/Interceptor.php(135): Magento\PageCache\Model\App\FrontController\BuiltinPlugin->aroundDispatch(Object(Magento\Framework\App\FrontController\Interceptor), Object(Closure), Object(Magento\Framework\App\Request\Http)) #15 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/framework/Interception/Interceptor.php(153): Magento\Framework\App\FrontController\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http)) #16 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/generated/code/Magento/Framework/App/FrontController/Interceptor.php(26): Magento\Framework\App\FrontController\Interceptor->___callPlugins('dispatch', Array, NULL) #17 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/framework/App/Http.php(135): Magento\Framework\App\FrontController\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http)) #18 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/generated/code/Magento/Framework/App/Http/Interceptor.php(24): Magento\Framework\App\Http->launch() #19 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/vendor/magento/framework/App/Bootstrap.php(257): Magento\Framework\App\Http\Interceptor->launch() #20 /var/www/vhosts/appliancespares-direct.co.uk/htdocs/pub/index.php(37): Magento\Framework\App\Bootstrap->run(Object(Magento\Framework\App\Http\Interceptor)) #21 {main}
Please follow below link for your reference:
Thank you very much for your reply.
The solution works!
I am sorry for the delay.
There is only one problem.
After submitting the form, it directs to contact/index rather than the product page,
The code is obviously directing to the referer.
$this->_redirect->getRefererUrl();
I would like to make it go back to the product page to display the message.
I've just worked out by replacing the code on the bottom of execute() function:
from:
return $this->resultRedirectFactory->create()->setPath('contact/index');
to:
return $this->resultRedirectFactory->create()->setPath($this->_redirect->getRefererUrl());
public function execute() { if (!$this->getRequest()->isPost()) { return $this->resultRedirectFactory->create()->setPath('*/*/'); } try { $this->sendEmail($this->validatedParams()); $this->messageManager->addSuccessMessage( __('Thanks for contacting us with your comments and questions. We\'ll respond to you very soon.') ); $this->dataPersistor->clear('contact_us'); } catch (LocalizedException $e) { $this->messageManager->addErrorMessage($e->getMessage()); $this->dataPersistor->set('contact_us', $this->getRequest()->getParams()); } catch (\Exception $e) { $this->logger->critical($e); $this->messageManager->addErrorMessage( __('An error occurred while processing your form. Please try again later.') ); $this->dataPersistor->set('contact_us', $this->getRequest()->getParams()); } return $this->resultRedirectFactory->create()->setPath($this->_redirect->getRefererUrl()); }
So now it's redirecting to the product page after sending an email.