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 !
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 .
php bin/magento setup:di:compile;
Pingback: UI component data source problem - gomagento2
I have the same problem Class DepartmentGridDataProvider does not exist could you send the correct source please?
php bin/magento setup:di:compile;
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
app/code/Maxime/Jobs/etc/di.xml
6: Maxime\Jobs\Model\Resource\Department\Collection
Suppose, should be ResourceModel, rather then Resource in namespace