Magento 2 Training : Unit 4 – Lesson A

Layout declaration

To create page content, we must declare it in a layout.
Remember, the layout’s name is associated with the controller.

Our action is jobs/department, so our layout name is jobs_department_index

You can create the following file :
app/code/Maxime/Jobs/view/adminhtml/layout/jobs_department_index.xml

With this content :

<?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">
            <uiComponent name="jobs_department_listing"/>
        </referenceContainer>
    </body>
</page>

We define the part “content” of our page on this XML. It will contain an element “uiComponent” named “jobs_department_listing”.

It’s easy to understand, but now we must to learn what is an uiComponent.

uiComponent creation

In an uiComponent, we can put a lot of things. Buttons, columns, filters etc…
We will begin with creating the structure of the component. We will add elements inside after.

In order to create the uiComponent, you can create the file :
app/code/Maxime/Jobs/view/adminhtml/ui_component/jobs_department_listing.xml

With this content :

<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <!-- Integration -->
    <argument name="data" xsi:type="array">
        <item name="js_config" xsi:type="array">
            <!-- we define a provider -->
            <item name="provider" xsi:type="string">jobs_department_listing.jobs_department_listing_data_source</item>
            <!-- same string as above -->
            <item name="deps" xsi:type="string">jobs_department_listing.jobs_department_listing_data_source</item>
        </item>
    </argument>
    <!-- Data source -->
    <dataSource name="jobs_department_listing_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <argument name="class" xsi:type="string">DepartmentGridDataProvider</argument> <!-- Data provider class -->
            <argument name="name" xsi:type="string">jobs_department_listing_data_source</argument> <!-- provider defined above -->
            <argument name="primaryFieldName" xsi:type="string">entity_id</argument> <!-- Primary key -->
            <argument name="requestFieldName" xsi:type="string">id</argument> <!-- URL name parameter -->

            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
                    <item name="update_url" xsi:type="url" path="mui/index/render"/>
                    <item name="storageConfig" xsi:type="array">
                        <!-- Primary key column name -->
                        <item name="indexField" xsi:type="string">entity_id</item>
                    </item>
                </item>
            </argument>
        </argument>
    </dataSource>
</listing>

On the first part “Integration”, we define a provider. This provider has the type “jobs_department_listing_data_source”.

This data source is declared below, on the part “Data source”.
– class : the object which allow us to give the content we will put on the grid
– name : the dataProvider’s name. We put the same as tjhe dataSource.
– primaryFieldName : primary key name
– requestFieldName : name of the parameter sent on the url for the primaryFieldName

The next part is static and call Magento’s elements.
The only thing we must change is the indexField, which is the primary key of our table.

Now, we will use the dependency injection to create an object “DepartmentGridDataProvider”.

Dependency injection (di.xml)

Create the file :
app/code/Maxime/Jobs/etc/di.xml

Put it inside :

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <!-- Create our type DepartmentGridDataProvider -->
    <virtualType name="DepartmentGridDataProvider" type="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider">
        <arguments>
            <argument name="collection" xsi:type="object" shared="false">Maxime\Jobs\Model\Resource\Department\Collection</argument>
            <argument name="filterPool" xsi:type="object" shared="false">DepartmentGridFilterPool</argument> <!-- Define new object for filters -->
        </arguments>
    </virtualType>

    <!-- Create our type DepartmentGridFilterPool -->
    <virtualType name="DepartmentGridFilterPool" type="Magento\Framework\View\Element\UiComponent\DataProvider\FilterPool">
        <arguments>
            <argument name="appliers" xsi:type="array">
                <item name="regular" xsi:type="object">Magento\Framework\View\Element\UiComponent\DataProvider\RegularFilter</item>
                <item name="fulltext" xsi:type="object">Magento\Framework\View\Element\UiComponent\DataProvider\FulltextFilter</item>
            </argument>
        </arguments>
    </virtualType>

    <!-- Type for jobs_department_listing_data_source -->
    <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
        <arguments>
            <argument name="collections" xsi:type="array">
                <item name="jobs_department_listing_data_source" xsi:type="string">Maxime\Jobs\Model\ResourceModel\Grid\Department\Collection</item>
            </argument>
        </arguments>
    </type>

    <!-- Simulate our class Maxime\Jobs\Model\ResourceModel\Grid\Department\Collection -->
    <virtualType name="Maxime\Jobs\Model\ResourceModel\Grid\Department\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult">
        <arguments>
            <argument name="mainTable" xsi:type="string">maxime_department</argument>
            <argument name="resourceModel" xsi:type="string">Maxime\Jobs\Model\ResourceModel\Department</argument>
        </arguments>
    </virtualType>
</config>

On the first time, we create our DepartmentGridDataProvider object, defined by two elements :
– collection : it’s a department collection, so we put our class Maxime\Jobs\Model\Resource\Department\Collection
– filterPool : We give a new object we will define after.

On a second time, we create the DepartmentGridFilterPool object, which need 2 Magento classes. You can check the content of its if you want, but I will not give details here.

If you remember, we create a dataProvider jobs_department_listing_data_source above. It was named jobs_department_listing_data_source. We create it one the 3rd part of the XML, and use an non-existing class “Maxime\Jobs\Model\ResourceModel\Grid\Department\Collection”.

We will not create this class, we will simulate it on the di.xml (4th part of the XML) :
– mainTable : the table containing our elements
– resourceModel : the resource model class of our element

What can I see ?

You can go on the Magento backoffice.
Jobs > Department

You will see an empty page with a loader.
The loader never end.
It’s normal !

We’ve got the structure of our grid, we will put elements on it during the next lessons !

Continue training
Return to previous lesson
Create an uiComponent with Magento 2
Tagged on:         

7 thoughts on “Create an uiComponent with Magento 2

  • 06/11/2016 at 09:32
    Permalink

    Class DepartmentGridDataProviderdoes not exist , maybe the VirtualType dose not work .
    how can download the source code ?.could you give us a link to download the job project .

    Reply
    • 11/24/2017 at 06:02
      Permalink

      php bin/magento setup:di:compile;

      Reply
  • Pingback: UI component data source problem - gomagento2

  • 07/18/2017 at 22:29
    Permalink

    I have the same problem Class DepartmentGridDataProvider does not exist could you send the correct source please?

    Reply
    • 11/24/2017 at 06:02
      Permalink

      php bin/magento setup:di:compile;

      Reply
  • 01/30/2018 at 13:49
    Permalink

    Fatal error: Method Magento\Ui\TemplateEngine\Xhtml\Result::__toString() must not throw an exception, caught TypeError: Argument 1 passed to Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider::searchResultToOutput() must implement interface Magento\Framework\Api\Search\SearchResultInterface, instance of Perficient\Cron\Model\ResourceModel\Configuration\Collection given, called in /vagrant/vendor/magento/framework/View/Element/UiComponent/DataProvider/DataProvider.php on line 284 in /vagrant/vendor/magento/module-ui/Component/Wrapper/UiComponent.php on line 0

    Reply
  • 09/04/2019 at 14:34
    Permalink

    app/code/Maxime/Jobs/etc/di.xml
    6: Maxime\Jobs\Model\Resource\Department\Collection

    Suppose, should be ResourceModel, rather then Resource in namespace

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

We use cookies to ensure that we give you the best experience on our website.
Ok