0

I want to add the toolbar from the product list to my wishlist to have the pagination and the sorter element.

So in my wishlist_index_index.xml I added the block Magento\Catalog\Block\Product\ProductList\Toolbar to the customer.wishlist.

<?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>
        <referenceContainer name="content">
            <referenceBlock name="customer.wishlist">
                <block class="Magento\Catalog\Block\Product\ProductList\Toolbar" name="product_list_toolbar" template="Magento_Catalog::product/list/toolbar.phtml">
                    <block class="Magento\Theme\Block\Html\Pager" name="product_list_toolbar_pager"/>
                </block>
                <action method="setToolbarBlockName">
                    <argument name="name" xsi:type="string">product_list_toolbar</argument>
                </action>
            </referenceBlock>
        </referenceContainer>
    </body>
</page>

Also I copied some methods that are required for the toolbar from Magento\Catalog\Block\Product\ListProduct to my wishlist Block which extends the default one. As you can see I changed the use statement Magento\Catalog\Model\ResourceModel\Product\Collection to Magento\Wishlist\Model\ResourceModel\Item\Collection to match my needs.

<?php

namespace CustomVendor\Wishlist\Block\Customer;

use Magento\Catalog\Block\Product\ProductList\Toolbar;
use Magento\Wishlist\Model\ResourceModel\Item\Collection;

class Wishlist extends \Magento\Wishlist\Block\Customer\Wishlist
{
    /**
     * Default toolbar block name
     *
     * @var string
     */
    protected $_defaultToolbarBlock = Toolbar::class;

    /**
     * Wishlist constructor.
     *
     * @param \Magento\Catalog\Block\Product\Context $context
     * @param \Magento\Framework\App\Http\Context $httpContext
     * @param \Magento\Catalog\Helper\Product\ConfigurationPool $helperPool
     * @param \Magento\Customer\Helper\Session\CurrentCustomer $currentCustomer
     * @param \Magento\Framework\Data\Helper\PostHelper $postDataHelper
     * @param \Magento\Theme\Block\Html\Pager $pager
     * @param array $data
     */
    public function __construct(
        \Magento\Catalog\Block\Product\Context $context,
        \Magento\Framework\App\Http\Context $httpContext,
        \Magento\Catalog\Helper\Product\ConfigurationPool $helperPool,
        \Magento\Customer\Helper\Session\CurrentCustomer $currentCustomer,
        \Magento\Framework\Data\Helper\PostHelper $postDataHelper,
        array $data = []
    ) {
        parent::__construct(
            $context,
            $httpContext,
            $helperPool,
            $currentCustomer,
            $postDataHelper,
            $data
        );
    }

    /**
     * Add wishlist conditions to collection
     *
     * @param  \Magento\Wishlist\Model\ResourceModel\Item\Collection $collection
     * @return $this
     */
    protected function _prepareCollection($collection)
    {
        $collection
            ->setInStockFilter(true)
            ->setOrderByProductName('asc');
        return $this;
    }

    /**
     * Preparing global layout
     *
     * @return void
     */
    protected function _prepareLayout()
    {
        parent::_prepareLayout();
        $this->pageConfig->getTitle()->set(__('My Wish List'));
    }

    /**
     * Before rendering html, but after trying to load cache
     *
     * @return $this
     */
    protected function _beforeToHtml()
    {
        $collection = $this->getWishlistItems();

        $this->addToolbarBlock($collection);

        $collection->load();

        return $this;
    }

    /**
     * Add toolbar block from product listing layout
     *
     * @param Collection $collection
     */
    private function addToolbarBlock(Collection $collection)
    {
        $toolbarLayout = $this->getToolbarFromLayout();

        if ($toolbarLayout) {
            $this->configureToolbar($toolbarLayout, $collection);
        }
    }

    /**
     * Retrieve Toolbar block from layout or a default Toolbar
     *
     * @return Toolbar
     */
    public function getToolbarBlock()
    {
        $block = $this->getToolbarFromLayout();

        if (!$block) {
            $block = $this->getLayout()->createBlock($this->_defaultToolbarBlock, uniqid(microtime()));
        }

        return $block;
    }

    /**
     * Get toolbar block from layout
     *
     * @return bool|Toolbar
     */
    private function getToolbarFromLayout()
    {
        $blockName = $this->getToolbarBlockName();

        $toolbarLayout = false;

        if ($blockName) {
            $toolbarLayout = $this->getLayout()->getBlock($blockName);
        }

        return $toolbarLayout;
    }

    /**
     * Retrieve list toolbar HTML
     *
     * @return string
     */
    public function getToolbarHtml()
    {
        return $this->getChildHtml('toolbar');
    }

    /**
     * Configures the Toolbar block with options from this block and configured product collection.
     *
     * The purpose of this method is the one-way sharing of different sorting related data
     * between this block, which is responsible for product list rendering,
     * and the Toolbar block, whose responsibility is a rendering of these options.
     *
     * @param \Magento\Catalog\Model\Product\ProductList\Toolbar $toolbar
     * @param Collection $collection
     * @return void
     */
    private function configureToolbar(Toolbar $toolbar, Collection $collection)
    {
        // use sortable parameters
        $orders = $this->getAvailableOrders();
        if ($orders) {
            $toolbar->setAvailableOrders($orders);
        }
        $sort = $this->getSortBy();
        if ($sort) {
            $toolbar->setDefaultOrder($sort);
        }
        $dir = $this->getDefaultDirection();
        if ($dir) {
            $toolbar->setDefaultDirection($dir);
        }
        $modes = $this->getModes();
        if ($modes) {
            $toolbar->setModes($modes);
        }
        // set collection to toolbar and apply sort
        $toolbar->setCollection($collection);
        $this->setChild('toolbar', $toolbar);
    }
}

When I load the site I get the following error:

[08-May-2018 15:52:25 UTC] PHP Fatal error:  Uncaught Error: Call to undefined method Magento\Wishlist\Model\ResourceModel\Item\Collection::addAttributeToSort() in /Applications/MAMP/htdocs/mag2/vendor/magento/module-catalog/Block/Product/ProductList/Toolbar.php:196
Stack trace:
#0 /Applications/MAMP/htdocs/mag2/app/code/CustomVendor/Wishlist/Block/Customer/Wishlist.php(206): Magento\Catalog\Block\Product\ProductList\Toolbar->setCollection(Object(Magento\Wishlist\Model\ResourceModel\Item\Collection))
#1 /Applications/MAMP/htdocs/mag2/app/code/CustomVendor/Wishlist/Block/Customer/Wishlist.php(127): CustomVendor\Wishlist\Block\Customer\Wishlist->configureToolbar(Object(Magento\Catalog\Block\Product\ProductList\Toolbar), Object(Magento\Wishlist\Model\ResourceModel\Item\Collection))
#2 /Applications/MAMP/htdocs/mag2/app/code/CustomVendor/Wishlist/Block/Customer/Wishlist.php(110): CustomVendor\Wishlist\Block\Customer\Wishlist->addToolbarBlock(Object(Magento\Wishlist\Model\ResourceModel\Item\Collection))
#3 /Applications/MAMP/htdocs/mag2/vendor/magento/framew in /Applications/MAMP/htdocs/mag2/vendor/magento/module-catalog/Block/Product/ProductList/Toolbar.php on line 196

This is because I use another collection. How would you make any progress here? Or is there another way to include the toolbar that you would to prefer?

1

You got this error cause this collection haven't addAttributeToSort as function to sort so this is a solution for pass this problem :

The first is override the class Wishlist or specify a new class in your layout.

  • Override:

app/code/yourcompany/Wishlist/etc/di.xml

<?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\Wishlist\Block\Customer\Wishlist" type="yourcompany\Wishlist\Block\Customer\Wishlist" />
</config>

or

  • Layout:

wishlist_index_index.xml

<block class="yourcompany\Wishlist\Block\Customer\Wishlist" name="customer.wishlist" template="Magento_Wishlist::view.phtml" cacheable="false">
   ...
   ...
   ...
</block>

In your

app/code/yourcompany\Wishlist\Block\Product\ProductList\Toolbar.php

<?php 

namespace yourcompany\Wishlist\Block\Product\ProductList;

use Magento\Catalog\Helper\Product\ProductList;
use Magento\Catalog\Model\Product\ProductList\Toolbar as ToolbarModel;

/**
 * Product list toolbar
 *
 * @api
 * @author      Magento Core Team <core@magentocommerce.com>
 * @SuppressWarnings(PHPMD.TooManyFields)
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 * @since 100.0.2
 */
class Toolbar extends \Magento\Catalog\Block\Product\ProductList\Toolbar
{
    /**
     * Products collection
     *
     * @var \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory
     */
    protected $collectionFactory;

    /**
     * @param \Magento\Framework\View\Element\Template\Context $context
     * @param \Magento\Catalog\Model\Session $catalogSession
     * @param \Magento\Catalog\Model\Config $catalogConfig
     * @param ToolbarModel $toolbarModel
     * @param \Magento\Framework\Url\EncoderInterface $urlEncoder
     * @param ProductList $productListHelper
     * @param \Magento\Framework\Data\Helper\PostHelper $postDataHelper
     * @param \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $collectionFactory
     * @param array $data
     */
    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        \Magento\Catalog\Model\Session $catalogSession,
        \Magento\Catalog\Model\Config $catalogConfig,
        ToolbarModel $toolbarModel,
        \Magento\Framework\Url\EncoderInterface $urlEncoder,
        ProductList $productListHelper,
        \Magento\Framework\Data\Helper\PostHelper $postDataHelper,
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $collectionFactory,
        array $data = []
    ) {
        $this->_collectionFactory = $collectionFactory;
        parent::__construct($context, $catalogSession, $catalogConfig, $toolbarModel, $urlEncoder, $productListHelper, $postDataHelper, $data);
    }

    /**
     * Set collection to pager
     *
     * @param \Magento\Framework\Data\Collection $collection
     * @return $this
     */
    public function setCollection($collection)
    {
        $this->_collection = $collection;
        $this->_collection->setInStockFilter(true);
        $this->_collection->setCurPage($this->getCurrentPage());

        // we need to set pagination only if passed value integer and more that 0
        $limit = (int) $this->getLimit();
        if ($limit) {
            $this->_collection->setPageSize($limit);
        }

        if ($this->getCurrentOrder() == 'position') {
            $this->_collection->setOrder('added_at', $this->getCurrentDirection());

        } else {
            $this->setOrderByProductAttribute($this->_collection, $this->getCurrentOrder(), $this->getCurrentDirection());
        }

        return $this;
    }

    /**
     * Sets ordering by product name
     *
     * @param string $dir
     * @return $this
     */
    public function setOrderByProductAttribute($collection, $attribute, $dir)
    {
        $productOrderId = [];

        $collectionproduct = $this->_collectionFactory->create()->addAttributeToSelect('*')
            ->addAttributeToFilter('entity_id', array('in' => array($collection->getColumnValues('product_id'))))
            ->addAttributeToSort($attribute, $dir)->load();

        foreach ($collectionproduct as $productOrdering) {
            $productOrderId []= $productOrdering->getEntityId();
        }
        return $this->_collection->getSelect()->order("find_in_set(product_id,'" . implode(",",$productOrderId) . "')");
    }
}

In your

app/code/yourcompany/Wishlist/Block/Customer/Wishlist.php

<?php


namespace yourcompany\Wishlist\Block\Customer;

use Magento\Wishlist\Model\ResourceModel\Item\Collection;
use yourcompany\Wishlist\Block\Product\ProductList\Toolbar;

class Wishlist extends \Magento\Wishlist\Block\Customer\Wishlist
{
    /**
     * Default toolbar block name
     *
     * @var string
     */
    protected $_defaultToolbarBlock = Toolbar::class;

    /**
     * Wishlist constructor.
     *
     * @param \Magento\Catalog\Block\Product\Context $context
     * @param \Magento\Framework\App\Http\Context $httpContext
     * @param \Magento\Catalog\Helper\Product\ConfigurationPool $helperPool
     * @param \Magento\Customer\Helper\Session\CurrentCustomer $currentCustomer
     * @param \Magento\Framework\Data\Helper\PostHelper $postDataHelper
     * @param \Magento\Theme\Block\Html\Pager $pager
     * @param array $data
     */
    public function __construct(
        \Magento\Catalog\Block\Product\Context $context,
        \Magento\Framework\App\Http\Context $httpContext,
        \Magento\Catalog\Helper\Product\ConfigurationPool $helperPool,
        \Magento\Customer\Helper\Session\CurrentCustomer $currentCustomer,
        \Magento\Framework\Data\Helper\PostHelper $postDataHelper,
        array $data = []
    ) {
        parent::__construct(
            $context,
            $httpContext,
            $helperPool,
            $currentCustomer,
            $postDataHelper,
            $data
        );
    }

    /**
     * Add wishlist conditions to collection
     *
     * @param  \Magento\Wishlist\Model\ResourceModel\Item\Collection $collection
     * @return $this
     */
    protected function _prepareCollection($collection)
    {
        return $this;
    }

    /**
     * Retrieve Wishlist Product Items collection
     *
     * @return \Magento\Wishlist\Model\ResourceModel\Item\Collection
     */
    public function getWishlistItems()
    {
        if ($this->_collection === null) {
            $this->_collection = $this->_createWishlistItemCollection();
            $this->_prepareCollection($this->_collection);
        }

        return $this->_collection;
    }

    /**
     * Before rendering html, but after trying to load cache
     *
     * @return $this
     */
    protected function _beforeToHtml()
    {
        $collection = $this->getWishlistItems();

        $this->addToolbarBlock($collection);

        $collection->load();

        return $this;
    }

    /**
     * Add toolbar block from product listing layout
     *
     * @param Collection $collection
     */
    private function addToolbarBlock(Collection $collection)
    {
        $toolbarLayout = $this->getToolbarFromLayout();
        if ($toolbarLayout) {
            $this->configureToolbar($toolbarLayout, $collection);
        }
    }

    /**
     * Retrieve Toolbar block from layout or a default Toolbar
     *
     * @return Toolbar
     */
    public function getToolbarBlock()
    {
        $block = $this->getToolbarFromLayout();

        if (!$block) {
            $block = $this->getLayout()->createBlock($this->_defaultToolbarBlock, uniqid(microtime()));
        }

        return $block;
    }

    /**
     * Get toolbar block from layout
     *
     * @return bool|Toolbar
     */
    private function getToolbarFromLayout()
    {
        $blockName = $this->getToolbarBlockName();

        $toolbarLayout = false;

        if ($blockName) {
            $toolbarLayout = $this->getLayout()->getBlock($blockName);
        }

        return $toolbarLayout;
    }

    /**
     * Retrieve list toolbar HTML
     *
     * @return string
     */
    public function getToolbarHtml()
    {
        return $this->getChildHtml('toolbar');
    }

    /**
     * Configures the Toolbar block with options from this block and configured product collection.
     *
     * The purpose of this method is the one-way sharing of different sorting related data
     * between this block, which is responsible for product list rendering,
     * and the Toolbar block, whose responsibility is a rendering of these options.
     *
     * @param \Magento\Catalog\Model\Product\ProductList\Toolbar $toolbar
     * @param Collection $collection
     * @return void
     */
    private function configureToolbar(Toolbar $toolbar, Collection $collection)
    {
        // use sortable parameters
        $orders = $this->getAvailableOrders();
        if ($orders) {
            $toolbar->setAvailableOrders($orders);
        }
        $sort = $this->getSortBy();
        if ($sort) {
            $toolbar->setDefaultOrder($sort);
        }
        $dir = $this->getDefaultDirection();
        if ($dir) {
            $toolbar->setDefaultDirection($dir);
        }
        $modes = $this->getModes();
        if ($modes) {
            $toolbar->setModes($modes);
        }
        // set collection to toolbar and apply sort
        $toolbar->setCollection($collection);

        $this->setChild('toolbar', $toolbar);
    }

}

In your layout

wishlist_index_index.xml

     <referenceBlock name="customer.wishlist">
        <block class="yourcompany\Wishlist\Block\Product\ProductList\Toolbar" name="product_list_toolbar" template="Magento_Wishlist::product/list/toolbar.phtml">
              <block class="Magento\Theme\Block\Html\Pager" name="product_list_toolbar_pager"/>
        </block>
        <action method="setToolbarBlockName">
            <argument name="name" xsi:type="string">product_list_toolbar</argument>
        </action>
    </referenceBlock>

We load the collection with the good sorting in our toolbar.php but the foreach reinitialise it, so we must pass by the variable goodorder for keep the order...

In your

app/design/yourcompany/theme/Magento_Wishlist/item/list.phtml

<?php
/** @var \Magento\Wishlist\Block\Customer\Wishlist\Items $block
 *
 */
$columns = $block->getColumns();

$goodOrder = $block->getItems()->getData();
?>
<div class="products-grid wishlist">
    <?php $iterator = 1;?>
    <?php if (count($block->getItems())): ?>
    <ol class="product-items">
        <?php foreach ($goodOrder as $item): ?>
        <?php $item = $block->getItems()->getItemByColumnValue("product_id", $item['product_id']);?>
        <?=/* @noEscape */($iterator++ == 1) ? '<li data-row="product-item" class="product-item" id="item_' . $block->escapeHtmlAttr($item->getId()) . '">' : '</li><li class="product-item" id="item_' . $block->escapeHtmlAttr($item->getId()) . '">'?>
            <div class="product-item-info" data-container="product-grid">
                <?php foreach ($columns as $column): ?>
                    <?=$column->setItem($item)->toHtml()?>
                <?php endforeach;?>
            </div>
        <?=($iterator == count($block->getItems()) + 1) ? '</li>' : ''?>
        <?php endforeach;?>
    </ol>
    <?php else: ?>
        <div class="message info empty">
            <span><?=$block->escapeHtml(__('This Wish List has no Items'))?></span>
        </div>
    <?php endif;?>
</div>

<?php foreach ($columns as $column): ?>
    <?=$column->getAdditionalHtml()?>
<?php endforeach;?>

In your view.phtml of the module or template:

app/design/yourcompany/theme/Magento_Wishlist/templates/view.phtml

You need add in the code the next:

<div class="toolbar--top">
    <?= $block->getToolbarHtml() ?>
</div>
...
...
<div class="toolbar--bottom">
    <?= $block->getToolbarHtml() ?>
</div>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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