0

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:

POST https://mysite.magedemo.co.uk/cform/index/index/ 500

enter image description here

My file system for this module is as follows:

enter image description here

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.

10
  • Did you want to create new form page or additional fields in contact us page? Jun 28, 2019 at 11:23
  • A new form page
    – CJNotts
    Jun 28, 2019 at 11:24
  • Try this link magento.stackexchange.com/a/278541/60921 Jun 28, 2019 at 11:28
  • Did you get solution? 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
    Jun 28, 2019 at 12:41

2 Answers 2

1

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
    }
}
8
  • Try this @CJNotts 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
    Jun 28, 2019 at 14:43
  • 1
    I updated file path 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
    Jun 28, 2019 at 14:53
  • mysite.magedemo.co.uk/cform/index/index Jun 28, 2019 at 14:55
0

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:

enter image description here

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
2
  • congrats @CJNOtts Jul 11, 2019 at 11:41
  • Thanks, much appreciated
    – CJNotts
    Jul 11, 2019 at 14:31

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.