2

I am using magento 2.1.5, and i am trying to make ajax newslatter.

di.xml

<type name="Magento\Newsletter\Controller\Subscriber\NewAction">
    <plugin name="Newsletter_Subscriber_NewAction"
            type="Namespace\Module\Controller\Plugin\Subscriber\NewAction" sortOrder="10" disabled="false" />
</type>

created new file inside controller as route:

app/code/Namespace/Module/Controller/Plugin/Subscriber/NewAction.php

<?php
/**
 *
 */
  namespace Namespace\Module\Controller\Plugin\Subscriber;

 use Magento\Customer\Api\AccountManagementInterface as      CustomerAccountManagement;
 use Magento\Customer\Model\Session;
use Magento\Customer\Model\Url as CustomerUrl;
use Magento\Framework\App\Action\Context;
use Magento\Store\Model\StoreManagerInterface;
 use Magento\Newsletter\Model\SubscriberFactory;

 /**
* Class NewAction
  */
 class NewAction extends \Magento\Newsletter\Controller\Subscriber\NewAction
{
/**
 * @var CustomerAccountManagement
 */
protected $customerAccountManagement;

protected $resultJsonFactory;

/**
 * Initialize dependencies.
 *
 * @param Context $context
 * @param SubscriberFactory $subscriberFactory
 * @param Session $customerSession
 * @param StoreManagerInterface $storeManager
 * @param CustomerUrl $customerUrl
 * @param CustomerAccountManagement $customerAccountManagement
 */
public function __construct(
    Context $context,
    SubscriberFactory $subscriberFactory,
    Session $customerSession,
    StoreManagerInterface $storeManager,
    CustomerUrl $customerUrl,
    CustomerAccountManagement $customerAccountManagement,
    \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
) {
    $this->customerAccountManagement = $customerAccountManagement;
    $this->resultJsonFactory = $resultJsonFactory;
    parent::__construct(
        $context,
        $subscriberFactory,
        $customerSession,
        $storeManager,
        $customerUrl,
        $customerAccountManagement
    );
}

/**
 * Retrieve available Order fields list
 *
 * @return array
 */
public function aroundExecute($subject, $procede)
{
    $response = [];
    if ($this->getRequest()->isPost() && $this->getRequest()->getPost('email')) {
        $email = (string)$this->getRequest()->getPost('email');

        try {
            $this->validateEmailFormat($email);
            $this->validateGuestSubscription();
            $this->validateEmailAvailable($email);

            $status = $this->_subscriberFactory->create()->subscribe($email);
            if ($status == \Magento\Newsletter\Model\Subscriber::STATUS_NOT_ACTIVE) {
                $response = [
                    'status' => 'OK',
                    'msg' => 'The confirmation request has been sent.',
                ];
            } else {
                $response = [
                    'status' => 'OK',
                    'msg' => 'Thank you for your subscription.',
                ];
            }
        } catch (\Magento\Framework\Exception\LocalizedException $e) {
            $response = [
                'status' => 'ERROR',
                'msg' => __('There was a problem with the subscription: %1', $e->getMessage()),
            ];
        } catch (\Exception $e) {
            $response = [
                'status' => 'ERROR',
                'msg' => __('Something went wrong with the subscription.'),
            ];
        }
    }

    return $this->resultJsonFactory->create()->setData($response);
}

}

over write the subscribe.phtml file in my theme file

<div class="block-subscribe">

<form novalidate
        action="<?php /* @escapeNotVerified */ echo $block->getFormActionUrl() ?>"
        method="post"
        data-mage-init='{"validation": {"errorClass": "mage-error"}}'
        id="newsletter-validate-detail">

        <div class="input-box">
            <div class="input-left">
                <i class="fa fa-envelope"></i>                    
                <input class="input-text" name="email" type="email" id="newsletter"
                            placeholder="<?php /* @escapeNotVerified */ echo __('Enter your email address') ?>"
                            data-validate="{required:true, 'validate-email':true}"/>
            </div>

            <button class="button action subscribe primary" title="<?php /* @escapeNotVerified */ echo __('Subscribe') ?>" type="submit">
                <span><span><?php /* @escapeNotVerified */ echo __('Subscribe') ?></span></span>
            </button>
        </div>
</form>

  <script>

  {
    "*": {
        "js/newsletter_subscriber_ajax": { }
    }
}
 </script>

and then create js/newsletter_subscriber_ajax at

app/design/frontend/NAMESPACE/MY_CUSTOM_THEME/web/js/newsletter_subscriber_ajax.js

require.config({
deps: [
    'jquery'
],
callback: function ($) {
    var form = $('form.subscribe');

    form.submit(function(e) {
        if(form.validation('isValid')){
            var email = $("#newsletter").val();
            var url = form.attr('action');
            var loadingMessage = $('#loading-message');

            if(loadingMessage.length == 0) {
                form.find('.control').append('<div id="loading-message" style="display:none;padding-top:10px;">&nbsp;</div>');
                var loadingMessage = $('#loading-message');
            }

            e.preventDefault();
            try{
                loadingMessage.html('Submitting...').show();
                $.ajax({
                    url: url,
                    dataType: 'json',
                    type: 'POST',
                    data: {email: email},
                    success: function (data){
                        if(data.status != "ERROR"){
                            $('#newsletter').val('');
                        }
                        loadingMessage.html(data.msg);
                    },
                    complete: function(){
                        setTimeout(function(){
                            loadingMessage.hide();
                        },5000);
                    }
                });
            } catch (e){
                loadingMessage.html(e.message);
            }
        }
        return false;
    });
}
 })

its return the result fine in json formate. but js is not working. is there any error with js???

4 Answers 4

2

add jquery code in your subscribe.phtml file like this:

<script>
  require(['jquery'],function($){
  var form = $('#newsletter-validate-detail');
  form.submit(function(e) {
    if(form.validation('isValid')){
            var email = $("#newsletter").val();
            var url = form.attr('action');
            var loadingMessage = $('#loading-message');

            if(loadingMessage.length == 0) {
                form.find('.input-group').append('<div id="loading-message" style="display:none;padding-top:10px;color: red;font-size: 13px;">&nbsp;</div>');
                var loadingMessage = $('#loading-message');
            }

            e.preventDefault();
            try{
                loadingMessage.html('Submitting...').show();
                $.ajax({
                    url: url,
                    dataType: 'json',
                    type: 'POST',
                    data: {email: email},
                    success: function (data){
                        if(data.status != "ERROR"){
                            $('#newsletter').val('');
                        }
                        loadingMessage.html(data.msg);
                    },
                });
            } catch (e){
                loadingMessage.html(e.message);
            }
        }
    });
  })
</script>
1
  • I am always getting error Something went wrong with the subscription. But subscriptions are adding in database. Please give me some solution.
    – Magecode
    Oct 26, 2017 at 11:24
0

Another easy way to do it without creating a custom module, just overriding the Magento newsletter into your theme

app/design/frontend/[Vendor]/[theme]/Magento_Newsletter/Controller/Subscriber/NewAction.php

namespace Magento\Newsletter\Controller\Plugin\Subscriber;

use Magento\Customer\Api\AccountManagementInterface as 
CustomerAccountManagement;
use Magento\Customer\Model\Session;
use Magento\Customer\Model\Url as CustomerUrl;
use Magento\Framework\App\Action\Context;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Newsletter\Model\SubscriberFactory;

/**
 * Class NewAction
*/
class NewAction extends \Magento\Newsletter\Controller\Subscriber\NewAction
{
/**
 * @var CustomerAccountManagement
 */
protected $customerAccountManagement;

protected $resultJsonFactory;

/**
 * Initialize dependencies.
 *
 * @param Context $context
 * @param SubscriberFactory $subscriberFactory
 * @param Session $customerSession
 * @param StoreManagerInterface $storeManager
 * @param CustomerUrl $customerUrl
 * @param CustomerAccountManagement $customerAccountManagement
 */
public function __construct(
    Context $context,
    SubscriberFactory $subscriberFactory,
    Session $customerSession,
    StoreManagerInterface $storeManager,
    CustomerUrl $customerUrl,
    CustomerAccountManagement $customerAccountManagement,
    \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
) {
    $this->customerAccountManagement = $customerAccountManagement;
    $this->resultJsonFactory = $resultJsonFactory;
    parent::__construct(
        $context,
        $subscriberFactory,
        $customerSession,
        $storeManager,
        $customerUrl,
        $customerAccountManagement
    );
}

/**
 * Retrieve available Order fields list
 *
 * @return array
 */
public function aroundExecute($subject, $procede)
{
    $response = [];
    if ($this->getRequest()->isPost() && $this->getRequest()->getPost('email')) {
        $email = (string)$this->getRequest()->getPost('email');

        try {
            $this->validateEmailFormat($email);
            $this->validateGuestSubscription();
            $this->validateEmailAvailable($email);

            $status = $this->_subscriberFactory->create()->subscribe($email);
            if ($status == \Magento\Newsletter\Model\Subscriber::STATUS_NOT_ACTIVE) {
                $response = [
                    'status' => 'OK',
                    'msg' => 'The confirmation request has been sent.',
                ];
            } else {
                $response = [
                    'status' => 'OK',
                    'msg' => 'Thank you for your subscription.',
                ];
            }
        } catch (\Magento\Framework\Exception\LocalizedException $e) {
            $response = [
                'status' => 'ERROR',
                'msg' => __('There was a problem with the subscription: %1', $e->getMessage()),
            ];
        } catch (\Exception $e) {
            $response = [
                'status' => 'ERROR',
                'msg' => __('Something went wrong with the subscription.'),
            ];
        }
    }

    return $this->resultJsonFactory->create()->setData($response);
  }
}

the JS file

<script>
 require(['jquery'],function($){
 var form = $('#newsletter-validate-detail');
 form.submit(function(e) {
   if(form.validation('isValid')){
        var email = $("#newsletter").val();
        var url = form.attr('action');
        var loadingMessage = $('#loading-message');

        if(loadingMessage.length == 0) {
            form.find('.input-group').append('<div id="loading-message" style="display:none;padding-top:10px;color: red;font-size: 13px;">&nbsp;</div>');
            var loadingMessage = $('#loading-message');
        }

        e.preventDefault();
        try{
            loadingMessage.html('Submitting...').show();
            debugger;
            $.ajax({
                url: url,
                dataType: 'json',
                type: 'POST',
                data: {email: email},
                success: function (data){
                    if(data.status != "ERROR"){
                        $('#newsletter').val('');
                    }
                    loadingMessage.html(data.msg);
                },
            });
        } catch (e){
            loadingMessage.html(e.message);
        }
    }
});
})
 </script>
0

Need to modify the following files:

  1. app/code/Namespace/Module/Controller/Plugin/Subscriber/NewAction.php

namespace Namespace\Module\Controller\Plugin\Subscriber;

use Magento\Customer\Api\AccountManagementInterface as 
CustomerAccountManagement;
use Magento\Customer\Model\Session;
use Magento\Customer\Model\Url as CustomerUrl;
use Magento\Framework\App\Action\Context;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Newsletter\Model\SubscriberFactory;

class NewAction extends \Magento\Newsletter\Controller\Subscriber\NewAction
{

protected $customerAccountManagement;

protected $resultJsonFactory;

public function __construct(
    Context $context,
    SubscriberFactory $subscriberFactory,
    Session $customerSession,
    StoreManagerInterface $storeManager,
    CustomerUrl $customerUrl,
    CustomerAccountManagement $customerAccountManagement,
    \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
) {
    $this->customerAccountManagement = $customerAccountManagement;
    $this->resultJsonFactory = $resultJsonFactory;
    $this->subscriberFactory = $subscriberFactory;
    parent::__construct(
        $context,
        $subscriberFactory,
        $customerSession,
        $storeManager,
        $customerUrl,
        $customerAccountManagement
    );
}

public function aroundExecute($subject, $procede)
{
    $response = [];
    if ($this->getRequest()->isPost() && $this->getRequest()->getPost('email')) {
        $email = (string)$this->getRequest()->getPost('email');

        try {
            $this->validateEmailFormat($email);
            $this->validateGuestSubscription();
            $this->validateEmailAvailable($email);            

            $subscriber = $this->subscriberFactory->create()->loadByEmail($email);            
            if ($subscriber->getId()
                && $subscriber->getSubscriberStatus() == \Magento\Newsletter\Model\Subscriber::STATUS_SUBSCRIBED
            ) {
                $response = [
                    'status' => 'ERROR',
                    'msg' => __('This email address is already subscribed.'),
                ];
                return $this->resultJsonFactory->create()->setData($response);
            }

            $status = $this->subscriberFactory->create()->subscribe($email);
            if ($status == \Magento\Newsletter\Model\Subscriber::STATUS_NOT_ACTIVE) {                
                $response = [
                    'status' => 'OK',
                    'msg' => __('The confirmation request has been sent.'),
                ];
            } else {
                $response = [
                    'status' => 'OK',
                    'msg' => __('Thank you for your subscription.'),
                ];
            }

        } catch (\Magento\Framework\Exception\LocalizedException $e) {
            $response = [
                'status' => 'ERROR',
                'msg' => __('There was a problem with the subscription: %1', $e->getMessage()),
            ];
        } catch (\Exception $e) {
            $response = [
                'status' => 'ERROR',
                'msg' => __('Something went wrong with the subscription. %1',$e->getMessage()),
            ];
        }
    }

    return $this->resultJsonFactory->create()->setData($response);
  }
}
  1. JS Code and HTML Changes
    <script type="text/javascript">
        require(['jquery'],function($){
            var form = $('#newsletter-validate-detail');
            form.submit(function(e) {
                if(form.validation('isValid')){
                    var email = $("#footer_newsletter").val();
                    var url = form.attr('action');
                    var loadingMessage = $('#loading-message');

                    if(loadingMessage.length == 0) {            
                        var loadingMessage = $('#loading-message');
                    }

                    e.preventDefault();
                    try{
                        loadingMessage.html('Submitting...').show();            
                        $.ajax({
                            url: url,
                            dataType: 'json',
                            type: 'POST',
                            data: {email: email},
                            success: function (data){
                                if(data.status != "ERROR"){
                                    $('#footer_newsletter').val('');
                                }
                                loadingMessage.html(data.msg);
                            },
                        });
                    } catch (e){
                        loadingMessage.html(e.message);
                    }
                }
            });
        })        
    </script>

add following code after form :

    <div class="message">
       <span id="loading-message"></span>
    </div>
0

By default, Magento 2 provides us with a module called Magento_Newsletter, which allows the customer to subscribe to the newsletter by submitting the form shown on the footer. However, when the customer submits the form, the current page must be reloaded, this is not good.

To improve the experience of the customer avoiding reloading the current page, we use Ajax for submitting the form.

  1. We will create a new module named Magento_Newsletter
  2. We will use the preference to override the action named NewAction of the controller named Subscriber in the module Magento_Newsletter
  3. We will create a new Jquery Widget called magento.Newsletter for submitting the newsletter form by Ajax.

Step 1: I have completed the codes to create the new module called Magento_Newsletter.

Step 2: Override the action named NewAction of the controller named Subscriber in the module Magento_Newsletter

You can see this action here

  • Create the new file named di.xml in the path app\code\Magento\Newsletter\etc\frontend
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Newsletter\Controller\Subscriber\NewAction" type="Magento\Newsletter\Override\Newsletter\Controller\Subscriber\NewAction" />
</config>

This is the action used in the newsletter subscription form, we need to override it to use with the Ajax.

  • Create the new file named NewAction.php in the path app\code\Magento\Newsletter\Override\Newsletter\Controller\Subscriber
<?php

namespace Magento\Newsletter\Override\Newsletter\Controller\Subscriber;

use Magento\Framework\App\ObjectManager;

class NewAction extends \Magento\Newsletter\Controller\Subscriber\NewAction
{
    /**
     * @var \Magento\Framework\Controller\Result\Json
     */
    protected $_resultJson;

    /**
     * New subscription action
     *
     * @throws \Magento\Framework\Exception\LocalizedException
     * @return void
     */
    public function execute()
    {
        $result = [];
        $result['error'] = true;
        $result['message'] = __('You are the man.');
        if ($this->getRequest()->isPost() && $this->getRequest()->getPost('email')) {
            $email = (string)$this->getRequest()->getPost('email');

            try {
                $this->validateEmailFormat($email);
                $this->validateGuestSubscription();
                $this->validateEmailAvailable($email);

                $subscriber = $this->_subscriberFactory->create()->loadByEmail($email);
                if ($subscriber->getId()
                    && $subscriber->getSubscriberStatus() == \Magento\Newsletter\Model\Subscriber::STATUS_SUBSCRIBED
                ) {
                    $result['message'] = __('This email address is already subscribed.');
                } else {
                    $status = $this->_subscriberFactory->create()->subscribe($email);
                    if ($status == \Magento\Newsletter\Model\Subscriber::STATUS_NOT_ACTIVE) {
                        $result['message'] = __('The confirmation request has been sent.');
                        $result['error'] = false;
                    } else {
                        $result['message'] = __('Thank you for your subscription.');
                        $result['error'] = false;
                    }
                }
            } catch (\Magento\Framework\Exception\LocalizedException $e) {
                $result['message'] = __('There was a problem with the subscription: %1', $e->getMessage());
            } catch (\Exception $e) {
                $result['message'] = $e->getMessage();
            }
        }
        return $this->getResultJson()->setData($result);
    }

    /**
     * @return \Magento\Framework\Controller\Result\Json
     */
    protected function getResultJson()
    {
        if ($this->_resultJson === null) {
            $this->_resultJson = ObjectManager::getInstance()->get(\Magento\Framework\Controller\Result\Json::class);
        }
        return $this->_resultJson;
    }
}

Step 3: Create a new Jquery Widget named magento.Newsletter

  • Create the new file named default.xml in the path app\code\Magento\Newsletter\view\frontend\layout
<?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">
    <body>
        <referenceBlock name="newsletter_head_components">
            <block class="Magento\Framework\View\Element\Js\Components" name="ajax_newsletter_subscription" template="Magento_Newsletter::ajax-newsletter-subscription.phtml"/>
        </referenceBlock>
    </body>
</page>
  • Create the new file named ajax-newsletter-subscription.phtml in the path app\code\Magento\Newsletter\view\frontend\templates
<script type="text/x-magento-init">
    {
        "#newsletter-validate-detail": {
            "Magento_Newsletter/js/newsletter-subscription": {}
        }
    }
</script>

  • Create the new file named newsletter-subscription.js in the path app\code\Magento\Newsletter\view\frontend\web\js
define([
    'jquery',
    'mage/translate',
    'jquery/ui',
    'mage/mage'
], function ($, $t) {
    'use strict';

    $.widget('magento.Newsletter', {

        /** @inheritdoc */
        _create: function () {
            this._bindSubmit();
        },

        /**
         * @private
         */
        _bindSubmit: function () {
            var self = this;

            this.element.on('submit', function (e) {
                e.preventDefault();
                if ($(this).validation('isValid')) {
                    self.submitForm($(this));
                }
            });
        },

        /**
         * Handler for the form 'submit' event
         *
         * @param {Object} form
         */
        submitForm: function (form) {
            var self = this;
            $.ajax({
                url: form.attr('action'),
                data: form.serialize(),
                type: 'post',
                dataType: 'json',
                showLoader: true,
                /** @inheritdoc */
                beforeSend: function () {
                    self.element.parent().find('.messages').remove();
                },
                success: function (response) {
                    if (response.error) {
                        self.element.after('<div class="messages"><div class="message message-error error"><div>'+response.message+'</div></div></div>');
                    } else {
                        self.element.find('input').val('');
                        self.element.after('<div class="messages"><div class="message message-success success"><div>'+response.message+'</div></div></div>');
                    }
                },
                error: function() {
                    self.element.after('<div class="messages"><div class="message message-error error"><div>'+$t('An error occurred, please try again later.')+'</div></div></div>');
                }
            });
        }
    });

    return $.magento.Newsletter;
});

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.