Introduction
ItemsList is a type of X-Cart widget that displays records about entities in a structured format. Examples of ItemsList widgets are below:
This article explains how to create such ItemsLists.
For the sake of example, we will create an ItemsList of products that cost more than $10, and this list will be sortable by price.
Implementation
We start with creating an empty module with developer ID XCExample and module ID ItemsListAdminDemo. Then we create a new page admin.php?target=items_list_demo
in admin area. For that we create:
a controller class
\XLite\Module\XCExample\ItemsListAdminDemo\Controller\Admin\ItemsListDemo
with the following content:<?php
// vim: set ts=4 sw=4 sts=4 et:
namespace XLite\Module\XCExample\ItemsListAdminDemo\Controller\Admin;
/**
* Items list demo controller
*/
class ItemsListDemo extends \XLite\Controller\Admin\AAdmin
{
}a simple page viewer class
\XLite\Module\XCExample\ItemsListAdminDemo\View\Page\Admin\ItemsListDemo
with the following content:<?php
// vim: set ts=4 sw=4 sts=4 et:
namespace XLite\Module\XCExample\ItemsListAdminDemo\View\Page\Admin;
/**
* Items list demo page view
*
* @ListChild (list="admin.center", zone="admin")
*/
class ItemsListDemo extends \XLite\View\AView
{
/**
* Return list of allowed targets
*
* @return array
*/
public static function getAllowedTargets()
{
return array_merge(parent::getAllowedTargets(), array('items_list_demo'));
}
/**
* Return widget default template
*
* @return string
*/
protected function getDefaultTemplate()
{
return 'modules/XCExample/ItemsListAdminDemo/page/items_list_demo/body.twig';
}
}an empty page template
<X-Cart>/skins/admin/en/modules/XCExample/ItemsListAdminDemo/page/items_list_demo/body.twig
.
Now we start creating our ItemsList widget. We create file <X-Cart>/classes/XLite/Module/XCExample/ItemsListAdminDemo/View/ItemsList/ItemsListDemo.php
with the following content:
<?php
namespace XLite\Module\XCExample\ItemsListAdminDemo\View\ItemsList;
class ItemsListDemo extends \XLite\View\ItemsList\Model\Table
{
const SORT_BY_MODE_PRICE = 'p.price';
protected function defineRepositoryName()
{
return '\XLite\Model\Product';
}
protected function defineColumns()
{
return array(
'sku' => array(
static::COLUMN_NAME => 'SKU',
static::COLUMN_ORDERBY => 100,
),
'name' => array(
static::COLUMN_NAME => 'Name',
static::COLUMN_ORDERBY => 200,
static::COLUMN_MAIN => true,
static::COLUMN_LINK => 'product',
),
'price' => array(
static::COLUMN_NAME => 'Price',
static::COLUMN_SORT => static::SORT_BY_MODE_PRICE,
static::COLUMN_ORDERBY => 300,
),
);
}
public function __construct(array $params = array())
{
$this->sortByModes += array(
static::SORT_BY_MODE_PRICE => 'Price',
);
parent::__construct($params);
}
protected function getSearchCondition()
{
$result = parent::getSearchCondition();
$result->{\XLite\Model\Repo\Product::P_ORDER_BY} = $this->getOrderBy();
$result->moreThan10 = true;
return $result;
}
protected function getSortByModeDefault()
{
return static::SORT_BY_MODE_PRICE;
}
}
Let us have a look at the key parts of this widget implementation:
Every ItemsList in admin area extends the
\XLite\View\ItemsList\Model\Table
class, so we are doing the same:class ItemsListDemo extends \XLite\View\ItemsList\Model\Table
We need to point our ItemsList to some model. It will tell the widget what entities will be displayed. In our case, this entity is a product, so we point our ItemsList to the
\XLite\Model\Product
model class:protected function defineRepositoryName()
{
return 'XLite\Model\Product';
}The next step is to define what columns must be displayed in our ItemsList. We want to display SKU, Product Name (as a link to product details page) and Price. The Price field must support the sorting option.
In order to implement this configuration, we define the following
defineColumns()
method:protected function defineColumns()
{
return array(
'sku' => array(
static::COLUMN_NAME => 'SKU',
static::COLUMN_ORDERBY => 100,
),
'name' => array(
static::COLUMN_NAME => 'Name',
static::COLUMN_ORDERBY => 200,
static::COLUMN_MAIN => true,
static::COLUMN_LINK => 'product',
),
'price' => array(
static::COLUMN_NAME => 'Price',
static::COLUMN_SORT => static::SORT_BY_MODE_PRICE,
static::COLUMN_ORDERBY => 300,
),
);
}The key of the array's element must be one of Model's properties so that X-Cart could assign this field with Model's propertyu automatically. The value must be an array that describes the column.
The SKU column is very simple, we just define its column name as SKU and its orderby as 100.
The Name column is a bit more complex. It has
COLUMN_NAME
andCOLUMN_ORDERBY
as well, but it additionally has theCOLUMN_MAIN = true
param, which defines that this column must be the widest among ones in the ItemsList. It also has theCOLUMN_LINK
parameter that defines the link where you can see product details. As you can see, we just define target parameter asproduct
, and X-Cart will build a proper URL for a particular product itself, so it would becomeadmin.php?target=product&product_id=ID
.The Price column is a bit complex as well. It has the same
COLUMN_NAME
andCOLUMN_ORDERBY
parameters and it supports sorting as defined by theCOLUMN_SORT
param. Aside from specifying this param in the column, we must also create a constant calledSORT_BY_MODE_PRICE
as it refers to it:
const SORT_BY_MODE_PRICE = 'p.price';
The value of this constant will be passed into the
getOrderBy()
method of ItemsList class (see the implementation of the\XLite\View\ItemsList\AItemsList
class), and then it will be used in thegetSearchCondition()
method (we will have a look at it a bit later in this article).Also, we must add this sorting option to the
sortByModes()
method, so we extend the__construct()
method:public function __construct(array $params = array())
{
$this->sortByModes += array(
static::SORT_BY_MODE_PRICE => 'Price',
);
parent::__construct($params);
}We implement the
getSearchCondition()
method in our ItemsList as follows:protected function getSearchCondition()
{
$result = parent::getSearchCondition();
$result->{\XLite\Model\Repo\Product::P_ORDER_BY} = $this->getOrderBy();
$result->moreThan10 = true;
return $result;
}We need to use this version in order to allow search() method in the
\XLite\Model\Repo\Product
repository to work properly.We let it know that sorting must be done according to user's selected condition:
$result->{\XLite\Model\Repo\Product::P_ORDER_BY} = $this->getOrderBy();
Here we use the
getOrderBy()
method mentioned earlier.We also add our condition of displaying products. It must display only products which are more expensive than $10:
$result->moreThan10 = true;
Finally, we need to add the
getSortByModeDefault()
method that will define the sorting option when it has not been chosen yet:protected function getSortByModeDefault()
{
return static::SORT_BY_MODE_PRICE;
}
Everything is good except that the search()
method of the \XLite\Model\Repo\Product
class cannot handle our moreThan10 condition yet. In order to fix that, we need to decorate the \XLite\Model\Repo\Product
class. We create the file <X-Cart>/classes/XLite/Module/XCExample/ItemsListAdminDemo/Model/Repo/Product.php
with the following content:
<?php
// vim: set ts=4 sw=4 sts=4 et:
namespace XLite\Module\XCExample\ItemsListAdminDemo\Model\Repo;
/**
* The "product" model repository
*/
abstract class Product extends \XLite\Model\Repo\Product implements \XLite\Base\IDecorator
{
const P_MORE_THAN_10 = 'moreThan10';
protected function getHandlingSearchParams()
{
$params = parent::getHandlingSearchParams();
$params[] = self::P_MORE_THAN_10;
return $params;
}
protected function prepareCndMoreThan10(\Doctrine\ORM\QueryBuilder $queryBuilder, $value)
{
$result = $queryBuilder;
if ($value) {
$result
->andWhere('p.price > :price')
->setParameter('price', 10.00);
}
return $result;
}
}
If you need more info about search()
method implementation, please refer to documentation here: search() method.
Finally, we need to display our ItemsList widget on the page, so we go to the <X-Cart>/skins/admin/en/modules/XCExample/ItemsListAdminDemo/page/items_list_demo/body.twig
template and define its content as follows:
{{ widget('\\XLite\\Module\\XCExample\\ItemsListAdminDemo\\View\\ItemsList\\ItemsListDemo') }}
That is it. Now we need to re-deploy the store and you will see our ItemsList on the admin.php?target=items_list_demo
page.
Module pack
You can download this module's example from here: XCExample-ItemsListAdminDemo-v5_3_0.tar