I am currently trying to create a custom form in Magento 2.2.7. The purpose of this contact form is to provide our trade (wholesale) customers with a separate contact form to our retail customers (i.e. it will go to a seperate email to the main contact form).
I am using the method given in question 198838 to create this form. However when I click "Submit" nothing happens and in the Google developer console I get the following error:
My file system for this module is as follows:
My code is as follows:
Controller> Index> Index.php
 <?php
 /**
 *
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
 namespace Trading\Cform\Controller\Index;
 use Magento\Framework\App\Action\Action;
 use Magento\Framework\App\Action\Context;
 use Magento\Framework\App\Filesystem\DirectoryList;
 use Magento\Framework\Filesystem;
 use Magento\Framework\App\Request\DataPersistorInterface;
 class Index extends Action
 {
 private $dataPersistor;
 /**
 * @return 
 \Magento\Framework\Controller\Result\Redirect|\Magento\Framework\View\Result\Page
 */
 protected $context;
 private $fileUploaderFactory;
 private $fileSy
stem;
 /**
 * @var \Magento\Framework\Mail\Template\TransportBuilder
 */
 protected $_transportBuilder;
 /**
 * @var \Magento\Framework\Translate\Inline\StateInterface
 */
 protected $inlineTranslation;
 /**
 * @var \Magento\Framework\App\Config\ScopeConfigInterface
 */
 protected $scopeConfig;
 /**
 * @var \Magento\Store\Model\StoreManagerInterface
 */
 /**
 * @param \Magento\Framework\App\Action\Context $context
 * @param \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder
 * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation
 * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
 */
 public function __construct(
 \Magento\Framework\App\Action\Context $context,
 Filesystem $fileSystem,
 \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory,
 \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder,
 \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation,
 \Modia\Cform\Helper\Data $helper,
 \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
 ) {
 parent::__construct($context,$transportBuilder,$inlineTranslation, $scopeConfig );
 $this->fileUploaderFactory = $fileUploaderFactory;
 $this->fileSystem = $fileSystem;
 $this->_transportBuilder = $transportBuilder;
 $this->inlineTranslation = $inlineTranslation;
 $this->helper = $helper;
 $this->scopeConfig = $scopeConfig;
 }
 public function execute()
 {
 $post = $this->getRequest()->getPostValue();
 $filesData = $this->getRequest()->getFiles('upload_document');
 if ($filesData['name']) {
 $uploader = $this->fileUploaderFactory->create(['fileId' => 'upload_document']);
 $uploader->setAllowRenameFiles(true);
 $uploader->setFilesDispersion(true);
 $uploader->setAllowCreateFolders(true);
 $path = $this->fileSystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath('test-doc');
 $result = $uploader->save($path);
 $upload_document = 'test-doc'.$uploader->getUploadedFilename();
 $filePath = $result['path'].$result['file'];
 $fileName = $result['name'];
 } else {
 $upload_document = '';
 $filePath = '';
 $fileName = '';
 }
 $txt='<table>';
 if($post['fname']){ 
 $txt.='<tr><td><strong>Client Name</strong>:'.$post['fname'].'</td></tr>'; 
 }
 if($post['address']){ 
 $txt.='<tr><td><strong>Address</strong>:'.$post['address'].'</td></tr>'; 
 }
 if($post['city']){
 $txt.='<tr><td><strong>City</strong>:'.$post['city'].'</td></tr>';
 }
 if($post['state']){
 $txt.='<tr><td><strong>State/Province</strong>:'.$post['state'].'</td></tr>';
 }
 if($post['zipcode']){
 $txt.='<tr><td><strong>Zip Code</strong>:'.$post['zipcode'].'</td></tr>';
 }
 if($post['phone']){
 $txt.='<tr><td><strong>Phone</strong>:'.$post['phone'].'</td></tr>';
 }
 if($post['email']){
 $txt.='<tr><td><strong>Email</strong>:'.$post['email'].'</td></tr>';
 }
 if(!empty($post['project_type'])){ 
 $projecttypearray = implode(",",$post['project_type']); 
 $txt.='<tr><td><strong>Project Type</strong>:'.$projecttypearray.'</td></tr>'; 
 }
 if($post['comment']){
 $txt.='<tr><td><strong>Comment</strong>:'.$post['comment'].'</td></tr>';
 }
 $txt.='</table>';
 //echo $txt;
 $customerName='Demo Form';
 $message=$txt;
 $userSubject= 'Demo From '; 
 $fromEmail= '[email protected]';
 $fromName = 'Test Demo Form';
 $templateVars = [
 'store' => 1,
 'customer_name' => $customerName,
 'subject' => $userSubject,
 'message' => $message
 ];
 $from = ['email' => $fromEmail, 'name' => $fromName];
 $this->inlineTranslation->suspend();
 $to = '[email protected]'; 
 $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE;
 $templateOptions = [
 'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
 'store' => 1
 ];
 $transport = $this->_transportBuilder->setTemplateIdentifier(5, $storeScope)
 ->setTemplateOptions($templateOptions)
 ->setTemplateVars($templateVars)
 ->setFrom($from)
 ->addTo($to)
 ->addAttachment($filePath, $fileName) 
 ->getTransport();
 $transport->sendMessage();
 $this->inlineTranslation->resume();
 $this->messageManager->addSuccess(__('Form successfully submitted'));
 $this->_redirect('form');
 }
}
Magento> Mail> Template> TransportBuilder.php
<?php
namespace Trading\Cform\Magento\Mail\Template;
class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder
{
 public function addAttachment($file, $name)
 {
 if (!empty($file) && file_exists($file)) {
 $this->message
 ->createAttachment(
 file_get_contents($file),
 \Zend_Mime::TYPE_OCTETSTREAM,
 \Zend_Mime::DISPOSITION_ATTACHMENT,
 \Zend_Mime::ENCODING_BASE64,
 basename($name)
 );
 }
 return $this;
 }
}
Model> ResourceModel> Cform> Collection.php
<?php
namespace Trading\Cform\Model\ResourceModel\Cform;
use \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
class Collection extends AbstractCollection
{
 protected $_idFieldName = \Trading\Cform\Model\Cform::CONTECT_ID;
 /**
 * Define resource model
 *
 * @return void
 */
 protected function _construct()
 {
 $this->_init('Trading\Cform\Model\Cform', 'Trading\Cform\Model\ResourceModel\Cform');
 }
}
Model> ResourceModel> Cform.php
<?php
namespace Trading\Cform\Model\ResourceModel;
class Cform extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
 protected $storeManager;
 public function __construct(
 \Magento\Framework\Model\ResourceModel\Db\Context $context,
 \Magento\Store\Model\StoreManagerInterface $storeManager,
 $connectionName = null
 ) {
 parent::__construct($context, $connectionName);
 $this->storeManager = $storeManager;
 }
 protected function _construct()
 {
 $this->_init('trading_contect', 'contect_id');
 }
}
Model> Cform.php
<?php
namespace Trading\Cform\Model;
class Cform extends \Magento\Framework\Model\AbstractModel
{
 /**
 * Initialize resource model
 *
 * @return void
 */
 protected function _construct()
 {
 $this->_init('Trading\Cform\Model\ResourceModel\Cform');
 }
}
Setup> InstallSchema.php
<?php
namespace Trading\Cform\Setup;
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
/**
 * @codeCoverageIgnore
 */
class InstallSchema implements InstallSchemaInterface
{
 public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
 {
 $installer = $setup;
 $installer->startSetup();
 /**
 * Create table 'vendor_contect'
 */
 $table = $installer->getConnection()->newTable(
 $installer->getTable('trading_contect')
 )->addColumn(
 'contect_id',
 \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
 null,
 ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true],
 'Contect Id'
 )->addColumn(
 'name',
 \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
 255,
 ['nullable' => false],
 'Name'
 )->addColumn(
 'email',
 \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
 255,
 ['nullable' => false],
 'Email Id'
 )->addColumn(
 'telephone',
 \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
 null,
 ['nullable'=> false],
 'Phone Number'
 )->addColumn(
 'comment',
 \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
 255,
 ['nullable' => false],
 'What's on your mind?'
 );
 $installer->getConnection()->createTable($table);
 }
}
etc> frontend> routes.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
 <router id="standard">
 <route id="cform" frontName="cform">
 <module name="Trading_Cform" />
 </route>
 </router>
</config>
etc> di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
 <preference for="\Magento\Framework\Mail\Template\TransportBuilder" type="\Trading\Cform\Magento\Mail\Template\TransportBuilder" />
</config>
etc> module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
 <module name="Trading_Cform" setup_version="1.0.0">
 </module>
</config>
view> frontend> templates> form.phtml
<form id="contact-form" class="form-horizontal" method="post" enctype="multipart/form-data" action="<?php echo $this->getUrl("cform/index/index")?>">
 <h1><?= $block->escapeHtml(__('Contact Form')) ?></h1>
 <fieldset class="fieldset">
 <div class="field name">
 <label class="label" for="name"><span><?= $block->escapeHtml(__('Name')) ?></span></label>
 <div class="control">
 <input name="name" id="name" class="input-text" type="text" />
 </div>
 </div>
 <div class="field email">
 <label class="label" for="email"><span><?= $block->escapeHtml(__('Email')) ?></span></label>
 <div class="control">
 <input name="email" id="email" class="input-text" type="email" />
 </div>
 </div>
 <div class="field telephone">
 <label class="label" for="telephone"><span><?= $block->escapeHtml(__('Phone Number')) ?></span></label>
 <div class="control">
 <input name="telephone" id="telephone" class="input-text" type="text" />
 </div>
 </div>
 <div class="field comment">
 <label class="label" for="comment"><span><?= $block->escapeHtml(__('What�s on your mind?')) ?></span></label>
 <div class="control">
 <textarea name="comment" id="comment" class="input-text" cols="5" rows="3" ></textarea>
 </div>
 </div>
 <?= $block->getChildHtml('form.additional.info') ?>
 </fieldset>
 <div class="actions-toolbar">
 <div class="primary">
 <input type="hidden" name="hideit" id="hideit" value="" />
 <button type="submit" id="add" title="" class="action submit primary">
 <span><?= $block->escapeHtml(__('Submit')) ?></span>
 </button>
 </div>
 </div>
</form>
<script>
require(['jquery'],function($){
 $(document).ready(function(){
 $("#add").click(function(){
 var customurl = "<?php echo $this->getUrl("cform/index/index") ?>";
 $.ajax({
 url: customurl,
 type: "POST",
 data: $(this).closest('form').serialize(),
 dataType: "json",
 success: function(result){
 console.log(result);
 }
 });
 $('#contact-form')[0].reset(); 
 return false;
 });
 });
}); 
</script>
registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
 \Magento\Framework\Component\ComponentRegistrar::MODULE,
 'Trading_Cform',
 __DIR__
);
If someone could advise me on what I am doing wrong here I would greatly appreciate it.
- 
 Did you want to create new form page or additional fields in contact us page?Arunprabakaran M– Arunprabakaran M2019年06月28日 11:23:17 +00:00Commented Jun 28, 2019 at 11:23
- 
 A new form pageCJNotts– CJNotts2019年06月28日 11:24:33 +00:00Commented Jun 28, 2019 at 11:24
- 
 Try this link magento.stackexchange.com/a/278541/60921Arunprabakaran M– Arunprabakaran M2019年06月28日 11:28:38 +00:00Commented Jun 28, 2019 at 11:28
- 
 Did you get solution?Arunprabakaran M– Arunprabakaran M2019年06月28日 12:08:54 +00:00Commented Jun 28, 2019 at 12:08
- 
 I've implemented the solution and I'm not getting the error anymore but it's not displaying the 'Booking done' Message or sending any emails.CJNotts– CJNotts2019年06月28日 12:41:41 +00:00Commented Jun 28, 2019 at 12:41
2 Answers 2
create layout file
view/frontend/layout/cform_index_index.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
 <referenceContainer name="content">
 <block class="Trading\Cform\Block\Custom" name="customer_index_gallery" template="Trading_Cform::form.phtml" cacheable="false"/>
 </referenceContainer>
</page>
Controller file
Controller\Index\Index.php
<?php
namespace Trading\Cform\Controller\Index;
class Index extends \Magento\Framework\App\Action\Action
{
 protected $_pageFactory;
 public function __construct(
 \Magento\Framework\App\Action\Context $context,
 \Magento\Framework\View\Result\PageFactory $pageFactory)
 {
 $this->_pageFactory = $pageFactory;
 return parent::__construct($context);
 }
 public function execute()
 {
 return $this->_pageFactory->create();
 }
}
view/frontend/templates/form.phtml
<form action="<?php echo $block->getFormAction() ?>" method="post">
 <input name="firstname" type="text">
 <input name="lastname" type="text">
 <input name="email" type="text">
 <input type="submit" value="informations">
</form>
/app/codeTrading/Cform/Block
<?php
namespace Trading\Cform\Block;
class Custom extends \Magento\Framework\View\Element\Template
{
 /**
 * Construct
 *
 * @param \Magento\Framework\View\Element\Template\Context $context
 * @param array $data
 */
 public function __construct(
 \Magento\Backend\Block\Template\Context $context,
 array $data = []
 )
 {
 parent::__construct($context, $data);
 }
 /**
 * Get form action URL for POST booking request
 *
 * @return string
 */
 public function getFormAction()
 {
 return '/cform/index/index';
 // here controller_name is index, action is booking
 }
}
- 
 Try this @CJNottsArunprabakaran M– Arunprabakaran M2019年06月28日 14:36:23 +00:00Commented Jun 28, 2019 at 14:36
- 
 Thanks. Could you let me know the file paths that I need to create those files in please?CJNotts– CJNotts2019年06月28日 14:43:06 +00:00Commented Jun 28, 2019 at 14:43
- 
 1I updated file pathArunprabakaran M– Arunprabakaran M2019年06月28日 14:46:50 +00:00Commented Jun 28, 2019 at 14:46
- 
 Hi. That seems to be doing something now at least. I'm getting the message "Navigated to mysite.magedemo.co.uk/test-page jquery-migrate.js:21 JQMIGRATE: Logging is active" I'm guessing now that I just have to specify that I want it to send the form details to an email address?CJNotts– CJNotts2019年06月28日 14:53:42 +00:00Commented Jun 28, 2019 at 14:53
- 
 mysite.magedemo.co.uk/cform/index/indexArunprabakaran M– Arunprabakaran M2019年06月28日 14:55:53 +00:00Commented Jun 28, 2019 at 14:55
With much thanks to MSA for pointing me in the right direction. I've now created a working form based on a few previously asked questions but in particular 125478:
The file system now looks as follows:
All of these files are placed in the following location:
App> Code> Trade> Tform
First the registration file:
registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
 \Magento\Framework\Component\ComponentRegistrar::MODULE,
 'Trade_Tform',
 __DIR__
);
Block> Tcontact.php
 <?php
namespace Trade\Tform\Block;
class Tcontact extends \Magento\Framework\View\Element\Template
{
 /**
 * Construct
 *
 * @param \Magento\Framework\View\Element\Template\Context $context
 * @param array $data
 */
 public function __construct(
 \Magento\Backend\Block\Template\Context $context,
 array $data = []
 )
 {
 parent::__construct($context, $data);
 }
 /**
 * Get form action URL for POST booking request
 *
 * @return string
 */
 public function getFormAction()
 {
 // tradetform is given in routes.xml
 // controller_name is folder name inside controller folder
 // action is php file name inside above controller_name folder
 return '/tradetform/index/tcontact';
 // here controller_name is index, action is tcontact
 }
}
Controller> Index> Tcontact.php
<?php
namespace Trade\Tform\Controller\Index;
use Magento\Framework\Controller\ResultFactory;
class Tcontact extends \Magento\Framework\App\Action\Action
{
 /**
 * Booking action
 *
 * @return void
 */
 public function execute()
 {
 // 1. POST request : Get booking data
 $post = (array) $this->getRequest()->getPost();
 if (!empty($post)) {
 // Retrieve your form data
 $name = $post['name'];
 $email = $post['email'];
 $phone = $post['phone'];
 $comment = $post['comment'];
 $messagetitle = "Enquiry From Custom Contact Form";
 $messagecontent = 
 $messagetitle."\n"."\n".
 "name: ".$name."\n"."\n".
 "email: ".$email."\n"."\n".
 "phone: ".$phone."\n"."\n".
 "comment: ".$comment."\n";
 // Send email to the following specified address
 mail("[email protected]","Trade Enquiry",$messagecontent);
 // Display the succes form validation message
 $this->messageManager->addSuccessMessage('Message Sent!');
 // Redirect to your form page (or anywhere you want...)
 $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
 $resultRedirect->setUrl('/page-that-form-is-on');
 return $resultRedirect;
 }
 // 2. GET request : Render the booking page 
 $this->_view->loadLayout();
 $this->_view->renderLayout();
 }
}
etc> frontend> routes.xml
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
 <router id="standard">
 <route id="tradetform" frontName="tradetform">
 <module name="Trade_Tform"/>
 </route>
 </router>
</config>
etc> module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
 <module name="Trade_Tform" setup_version="1.0.0" />
</config>
view> frontend> layout> tradetform_index_tcontact.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
 <head>
 <title>Trade Form</title>
 </head>
 <body>
 <referenceBlock name="navigation.sections" remove="true" />
 <referenceContainer name="content">
 <block class="Trade\Tform\Block\Tcontact" name="tradetform.tcontact" template="Trade_Tform::tcontact.phtml"/>
 </referenceContainer>
 </body>
</page>
view> frontend> templates> tcontact.phtml
<form action="<?php echo $block->getFormAction() ?>" data-mage-init='{"validation":{}}' method="post">
 <p>Contact Name <span style=" color: #e02b27; font-size: 1.2rem;">*</span>
 <input name="name" type="text" data-validate='{"required":true}'></p>
 <p>Contact Email <span style=" color: #e02b27; font-size: 1.2rem;">*</span>
 <input name="email" type="text" data-validate='{"required":true}'></p>
 <p>Contact Phone
 <input name="phone" type="text"></p>
 <p>Message
 <textarea name="comment" cols="40" rows="5"></textarea></p>
 <input type="submit" value="Submit">
</form>
After this it was a case of running the upgrade command in CLI.
php bin/magento setup:upgrade
- 
 congrats @CJNOttsArunprabakaran M– Arunprabakaran M2019年07月11日 11:41:25 +00:00Commented Jul 11, 2019 at 11:41
- 
 Thanks, much appreciatedCJNotts– CJNotts2019年07月11日 14:31:14 +00:00Commented Jul 11, 2019 at 14:31