How do I create a custom search and filter? I have created a custom module to render forms on the front end (modules\custom_mod\src\Form\Contact\ContactUserForm.php) and stored the form values to a custom table.

I have also created a listing (admin end) of the stored data from table which I acheived with the help of controller (modules\custom_mod\src\Controller\Contact\ContactController.php).

In that listing, I have the Edit and Delete actions based on the ID from the table.

The file structure is below. 



modules/custom_mod/
├── js
├── css
├── custom_mod.routing.yml
├── custom_mod.info.yml
├── custom_mod.module
├── custom_mod.libraries.yml
└── src
    ├── Form
        └── Contact
            └── ContactUserForm.php
            └── ContactUserStorage.php
            └── ContactAdminForm.php
            └── ContactAdminEdit.php
    ├── Controller
        └── Contact
            └── ContactController.php


Now I need a search box, a From date and To date filter, with an Export (CSV) button above the listing, so that the administrator user can filter or search accordingly.

How can I achieve this?
I created a very easy month/year filter select box. For that I created a new form class which extends the FormBase class of Drupal 8. 

To add filter and search inputs I added following values to the returning array:

namespace Drupal\my_sandbox\Controllers;

use Drupal\Core\Controller\ControllerBase;

class TestController extends ControllerBase
{

public function test()
{

    $form = [];

    //add you custom code here...

    $form['form'] = [
        '#type'  =&gt; 'form',
    ];

    $form['form']['filters'] = [
        '#type'  =&gt; 'fieldset',
        '#title' =&gt; $this-&gt;t('Filter'),
        '#open'  =&gt; true,
    ];

    $form['form']['filters']['text'] = [
        '#title'         =&gt; 'text',
        '#type'          =&gt; 'search'
    ];

    $form['form']['filters']['year'] = [
        '#title'         =&gt; 'Year',
        '#type'          =&gt; 'select',
        '#empty_value'   =&gt; 'none',
        '#empty_option'  =&gt; '- None -',
        '#size'          =&gt; 0,
        '#options'       =&gt; ['value1' =&gt; 'label1', 'value2' =&gt; 'label2'],
        '#default_value' =&gt; 'none'
    ];

    $form['form']['filters']['actions'] = [
        '#type'       =&gt; 'actions'
    ];

    $form['form']['filters']['actions']['submit'] = [
        '#type'  =&gt; 'submit',
        '#value' =&gt; $this-&gt;t('Filter')
    ];

    //place the table in the form
    $form['table'] = array(
      '#type' =&gt; 'table',
      '#header' =&gt; $header,
      '#rows' =&gt; $rows,
      '#attributes' =&gt; array(
        'id' =&gt; 'bd-contact-table',
      ) 
    );

    return $form;



}

}


The array for the key 'filters' is the container in which all the filter will be placed. I choose the type 'fieldset', you can change the type of container to any element you want. 

Afterwards I added the search and filter input and at the end the button to submit the filter-form. If you use the a class that extends the FormBase class the form will be send the the submitForm method of your class.

A thing here to notice is that every "#type" key maps to Drupal element. All elements are located in the DRUPALCORE/lib/Drupal/Core/Render/Element folder. Example: The #type search will map to the file Search.php within the Element folder. Every file includes a comment where all options of the element are explained. 

I hope I could help you. 

Nicolas