First, add or update the following file
app/code/Examples/FirstModule/etc/di.xml
Add the following:
Note: If you followed the Magento 2: CRUD Models, Repositories & Interfaces post you will have this file and already have some preferences set.
<?xml version="1.0" encoding="utf-8" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
<arguments>
<argument name="collections" xsi:type="array">
<item name="examples_firstmodule_post_listing_data_source" xsi:type="string">Examples\FirstModule\Model\ResourceModel\Post\Grid\Collection</item>
</argument>
</arguments>
</type>
<virtualType name="Examples\FirstModule\Model\ResourceModel\Post\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult">
<arguments>
<argument name="mainTable" xsi:type="string">examples_firstmodule_post</argument>
<argument name="resourceModel" xsi:type="string">Examples\FirstModule\Model\ResourceModel\Post</argument>
</arguments>
</virtualType>
</config>
Next, add the menu item to point to the index listing page. Update the file added in Magento 2: Adding A New Admin Menu Item
app/code/Examples/FirstModule/etc/adminhtml/menu.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
<menu>
<!-- Top Level Menu Item -->
<add id="Examples_FirstModule::level_zero" title="Examples" translate="title" module="Examples_FirstModule"
sortOrder="10" resource="Examples_FirstModule::first_module"/>
<!-- First Grouping -->
<add id="Examples_FirstModule::level_one" title="Examples Level One" translate="title" module="Examples_FirstModule"
parent="Examples_FirstModule::level_zero" resource="Examples_FirstModule::first_module"/>
<add id="Examples_FirstModule::level_two" title="Posts" translate="title" module="Examples_FirstModule"
parent="Examples_FirstModule::level_one" sortOrder="10" dependsOnModule="Examples_FirstModule"
action="examples/examples/posts" resource="Examples_FirstModule::first_module"/>
<add id="Examples_FirstModule::posts_listing" title="Posts Listing" translate="title" module="Examples_FirstModule"
parent="Examples_FirstModule::level_one" sortOrder="20" dependsOnModule="Examples_FirstModule"
action="examples/examples/index" resource="Examples_FirstModule::first_module"/>
<!-- Second Grouping -->
<add id="Examples_FirstModule::level_one_second" title="Examples Level One (2nd)" translate="title" module="Examples_FirstModule"
parent="Examples_FirstModule::level_zero" resource="Examples_FirstModule::first_module"/>
<add id="Examples_FirstModule::level_two_second" title="Posts (2nd)" translate="title" module="Examples_FirstModule"
parent="Examples_FirstModule::level_one_second" sortOrder="10" dependsOnModule="Examples_FirstModule"
action="examples/examples/posts" resource="Examples_FirstModule::first_module"/>
</menu>
</config>
Add the layout file
app/code/Examples/FirstModule/view/adminhtml/layout/examples_examples_index.xml
add the following code to it:
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<update handle="styles"/>
<body>
<referenceContainer name="content">
<uiComponent name="examples_firstmodule_post_listing"/>
</referenceContainer>
</body>
</page>
Now add the UI component for the grid
app/code/Examples/FirstModule/view/adminhtml/ui_component/examples_firstmodule_post_listing.xml
with the following code:
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">examples_firstmodule_post_listing.examples_firstmodule_post_listing_data_source</item>
<item name="deps" xsi:type="string">examples_firstmodule_post_listing.examples_firstmodule_post_listing_data_source</item>
</item>
<item name="spinner" xsi:type="string">spinner_columns</item>
<item name="buttons" xsi:type="array">
<item name="add" xsi:type="array">
<item name="name" xsi:type="string">add</item>
<item name="label" xsi:type="string" translate="true">Add New Post</item>
<item name="class" xsi:type="string">primary</item>
<item name="url" xsi:type="string">*/*/edit</item>
</item>
</item>
</argument>
<dataSource name="examples_firstmodule_post_listing_data_source">
<argument name="dataProvider" xsi:type="configurableObject">
<argument name="class" xsi:type="string">Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider</argument>
<argument name="name" xsi:type="string">examples_firstmodule_post_listing_data_source</argument>
<argument name="primaryFieldName" xsi:type="string">post_id</argument>
<argument name="requestFieldName" xsi:type="string">id</argument>
<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">
<item name="indexField" xsi:type="string">post_id</item>
</item>
</item>
</argument>
</argument>
</dataSource>
<listingToolbar name="listing_top">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="sticky" xsi:type="boolean">true</item>
</item>
</argument>
<massaction name="listing_massaction">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/tree-massactions</item>
</item>
</argument>
<action name="delete">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="type" xsi:type="string">delete</item>
<item name="label" xsi:type="string" translate="true">Delete</item>
<item name="url" xsi:type="url" path="examples/examples/massDelete"/>
<item name="confirm" xsi:type="array">
<item name="title" xsi:type="string" translate="true">Delete Post</item>
<item name="message" xsi:type="string" translate="true">Are you sure you want to delete selected items?</item>
</item>
</item>
</argument>
</action>
</massaction>
<filters name="listing_filters" />
<filterSearch name="fulltext"/>
<columnsControls name="columns_controls"/>
<bookmark name="bookmarks"/>
<exportButton name="export_button"/>
<paging name="listing_paging"/>
</listingToolbar>
<columns name="spinner_columns">
<selectionsColumn name="ids">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="resizeEnabled" xsi:type="boolean">false</item>
<item name="resizeDefaultWidth" xsi:type="string">55</item>
<item name="indexField" xsi:type="string">post_id</item>
</item>
</argument>
</selectionsColumn>
<column name="post_id">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="filter" xsi:type="string">textRange</item>
<item name="sorting" xsi:type="string">asc</item>
<item name="label" xsi:type="string" translate="true">ID</item>
</item>
</argument>
</column>
<column name="author_name">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="filter" xsi:type="string">text</item>
<item name="editor" xsi:type="array">
<item name="editorType" xsi:type="string">text</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="boolean">true</item>
</item>
</item>
<item name="label" xsi:type="string" translate="true">Author Name</item>
</item>
</argument>
</column>
<column name="email">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="filter" xsi:type="string">text</item>
<item name="editor" xsi:type="array">
<item name="editorType" xsi:type="string">text</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="boolean">true</item>
</item>
</item>
<item name="label" xsi:type="string" translate="true">Author Email</item>
</item>
</argument>
</column>
<column name="created" class="Magento\Ui\Component\Listing\Columns\Date">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="filter" xsi:type="string">dateRange</item>
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item>
<item name="dataType" xsi:type="string">date</item>
<item name="label" xsi:type="string" translate="true">Created</item>
</item>
</argument>
</column>
<column name="updated" class="Magento\Ui\Component\Listing\Columns\Date">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="filter" xsi:type="string">dateRange</item>
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item>
<item name="dataType" xsi:type="string">date</item>
<item name="label" xsi:type="string" translate="true">Updated</item>
</item>
</argument>
</column>
</columns>
</listing>
Tell Magento about the changes using the CLI command bin/magento c:f
