5

I already have a products collection and an empty page, how would I load the products list layout and use my own products collection?

EDIT:

Better explanation hopefully. I have a form to select year, make, model, and then category, which works well. I got a product collection, I just want to display the collection in a standard product listing using the currently loaded theme but the solution eludes me.

The Year, make model and associated products are stored in their own models. I didn't see a good way to store them in standard magento attributes as most products have several combinations of year, make, models.

EDIT2:

Got somewhere by adding this to my layout but by default it just shows all products. Possible to change the products displayed in the block?

<block class="Magento\Catalog\Block\Product\ListProduct" name="ymmResult" template="Magento_Catalog::product/list.phtml" />
4
  • What is the purpose of this page?
    – Phil M
    Commented Dec 2, 2016 at 21:49
  • Basically I want to list specific products on a page using whatever is the currently default listing page. I already have a collection of products, just need them displayed.
    – Tyler
    Commented Dec 5, 2016 at 13:57
  • Why wouldn't you use a category? You can embed category blocks on non-category pages, like in this tutorial: fastcomet.com/tutorials/magento/display-products-homepage
    – Phil M
    Commented Dec 5, 2016 at 16:24
  • Yeah, I didnt explain myself well enough I guess. I created a custom extension that you can choose year make model, and category and it brings back products in a collection. If I could just pass that collection into a category dynamically that would be great.
    – Tyler
    Commented Dec 5, 2016 at 18:43

2 Answers 2

17
+50

Here is an example module that will allow you specify a product collection for a customized product list element, which you should be able to adapt to your needs. It works by extending the ListProduct class to allow it's backing collection to be set dynamically.

File Structure:

app/code/AAllen/CustomProdList
|
|   registration.php
|   
+---Block
|   \---Product
|           CustomList.php
|           
+---Controller
|   \---Index
|           Index.php
|           
+---etc
|   |   module.xml
|   |   
|   \---frontend
|           routes.xml
|           
\---view
    \---frontend
        \---layout
                customprodlist_index_index.xml

registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'AAllen_CustomProdList',
    __DIR__
);

CustomList.php is where we extend ListProduct by overriding the GetLoadedProductCollection method and adding a method to set the product collection.

<?php

namespace AAllen\CustomProdList\Block\Product;

use Magento\Catalog\Block\Product\ListProduct;
use Magento\Catalog\Model\ResourceModel\Collection\AbstractCollection;

class CustomList extends ListProduct
{
    public function getLoadedProductCollection()
    {
        return $this->_productCollection;
    }

    public function setProductCollection(AbstractCollection $collection)
    {
        $this->_productCollection = $collection;
    }
}

Index.php is an example of a controller where we set a product collection on the CustomList block which will be placed in the layout file.

<?php

namespace AAllen\CustomProdList\Controller\Index;


use AAllen\CustomProdList\Block\Product\CustomList;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;

class Index extends Action
{
    /** @var PageFactory */
    protected $pageFactory;

    /** @var  \Magento\Catalog\Model\ResourceModel\Product\Collection */
    protected $productCollection;

    public function __construct(
        Context $context,
        PageFactory $pageFactory,
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $collectionFactory
    )
    {
        $this->pageFactory = $pageFactory;
        $this->productCollection = $collectionFactory->create();

        parent::__construct($context);
    }

    public function execute()
    {
        $result = $this->pageFactory->create();

        // obtain product collection.
        $this->productCollection->addIdFilter(5); // do some filtering
        $this->productCollection->addFieldToSelect('*');

        // get the custom list block and add our collection to it
        /** @var CustomList $list */
        $list = $result->getLayout()->getBlock('custom.products.list');
        $list->setProductCollection($this->productCollection);

        return $result;
    }
}

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="AAllen_CustomProdList" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Catalog"/>
        </sequence>
    </module>
</config>

routes.xml defines an example route where we want to display the product list.

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="customprodlist" frontName="customprodlist">
            <module name="AAllen_CustomProdList"/>
        </route>
    </router>
</config>

customprodlist_index_index.xml is the layout for the above route. This is where we place our block element as well as some child blocks which I copied from catalog_category_view.xml.

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <title>Custom Product List</title>
    </head>
    <body>
        <referenceContainer name="content">
            <block class="AAllen\CustomProdList\Block\Product\CustomList" name="custom.products.list" as="product_list" template="Magento_Catalog::product/list.phtml">
                <container name="category.product.list.additional" as="additional" />
                <block class="Magento\Framework\View\Element\RendererList" name="category.product.type.details.renderers" as="details.renderers">
                    <block class="Magento\Framework\View\Element\Template" as="default"/>
                </block>
                <block class="Magento\Catalog\Block\Product\ProductList\Item\Container" name="category.product.addto" as="addto">
                    <block class="Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare"
                           name="category.product.addto.compare" as="compare"
                           template="Magento_Catalog::product/list/addto/compare.phtml"/>
                </block>
                <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>
            </block>
        </referenceContainer>
    </body>
</page>
6
  • This is exactly what I needed, thanks so much! It says I can award bounty in 38 minutes.
    – Tyler
    Commented Dec 7, 2016 at 15:12
  • 1
    @Aaron Allen How to set layer navigation for this collection?
    – Sathish
    Commented Mar 27, 2017 at 10:02
  • This works :) thanks! Although it does not show me the sidebar with the filters. But you saved me hours with this. Commented Aug 28, 2017 at 17:03
  • @Aaron Allen Thanks for this post. Could you please tell me that, how to add layered navigation in this page? Commented Nov 8, 2017 at 8:06
  • swatches are not showing...? Commented Apr 13, 2019 at 11:31
0

Only for complet your answer, if you want to show the swatches you have to call the block in customprodlist_index_index.xml

<block class="Magento\LayeredNavigation\Block\Navigation\Category" name="catalog.leftnav" before="-" template="Magento_LayeredNavigation::layer/view.phtml">
    <block class="Magento\LayeredNavigation\Block\Navigation\State" name="catalog.navigation.state" as="state" />
    <block class="Magento\LayeredNavigation\Block\Navigation\FilterRenderer" name="catalog.navigation.renderer" as="renderer" template="Magento_LayeredNavigation::layer/filter.phtml"/>
</block>
2
  • If you put this block it shows the navigation layer, yes, but it's not related with the custom product collection shown. Do you know how to do it properly?
    – ElTête
    Commented Feb 3, 2022 at 9:50
  • @ElTête Did you found any solution to do that ? magento.stackexchange.com/questions/365942/…
    – Claims
    Commented Apr 4, 2023 at 21:50

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.