Jump to content

Edit History

Gionatan

Gionatan


corrected second route dummy name

Seems a bit of an old post, but I'm replying in case OP is still interested or somebody else stumbles upon this problem

I've ran into the same issue and solved as follows; beside the solution I'm providing a bit of an explanation and some stuff I've checked before resolving.

Check out this notes before reading if you want, as some thoughts to keep in mind for the future. Feel free to skip:

  1. PrestaShop version is not mentioned in your post
  2. I'm working with 1.7.7.3 development version
  3. I'm working with doc for 1.7
  4. This is a personal opinion and is not meant to disrespect the work of the mantainers: some sections of the doc seem incomplete and a work in progress (bottom page has the latest update which show many pages have been recently updated) and some require a bit of Symfony knowledge or may assume other knowledge (npm, webpack etc.) or knowledge from other sections that you may have not read because they are outside your area of interest (e.g. theme development) or just overlooked. All of this is more than fine by me, it's just an indication that you may want to look into other stuff beside the doc itself

As for the grid issue:

Quote

It really seems to me that no js is linked to my grid template so nothing is triggered.

This is indeed the problem; in this section of the doc (which isn't the module development but the core reference) is explained how to add JS features to your grid which, by default, has none. Such features are implemented inside the folder "admin-dev/themes/new-theme/js/components" and "admin-dev/themes/new-theme/js/app/utils".

However, as stated, the guide is meant for core and not module development so it will most likely fail or feel lacking of details.

Here's what you need to do:

  1. Create a JS file that initializes the required components described in the docs (SortingExtension, FiltersResetExtension and such, depending on which ones you want to use). This is how it's done in the doc:
     
    import Grid from '../../components/grid/grid';
    import SortingExtension from '../../components/grid/extension/sorting-extension';
    import FiltersResetExtension from '../../components/grid/extension/filters-reset-extension';
    import ReloadListActionExtension from '../../components/grid/extension/reload-list-extension';
    import ColumnTogglingExtension from '../../components/grid/extension/column-toggling-extension';
    import SubmitRowActionExtension from '../../components/grid/extension/action/row/submit-row-action-extension';
    import SubmitBulkExtension from '../../components/grid/extension/submit-bulk-action-extension';
    import BulkActionCheckboxExtension from '../../components/grid/extension/bulk-action-checkbox-extension';
    import ExportToSqlManagerExtension from '../../components/grid/extension/export-to-sql-manager-extension';
    
    const $ = window.$;
    
    $(() => {
      const taxGrid = new Grid('tax');
    
      taxGrid.addExtension(new ExportToSqlManagerExtension());
      taxGrid.addExtension(new ReloadListActionExtension());
      taxGrid.addExtension(new SortingExtension());
      taxGrid.addExtension(new FiltersResetExtension());
      taxGrid.addExtension(new ColumnTogglingExtension());
      taxGrid.addExtension(new SubmitRowActionExtension());
      taxGrid.addExtension(new SubmitBulkExtension());
      taxGrid.addExtension(new BulkActionCheckboxExtension());
    });

    But as you can see, the imports are using relative paths that are not correct for a module.
    You can probably change them to fit the "modules" directory but that may result in errors when working on a different environment (beside being a bad habit).

  2. In order to avoid using the relative paths, you need to implement webpack to use the appropriate ones. Luckily, inside this official tutorial there is already one that has everything you need. Download it and check out the "js" directory where you'll find:

    1. ".webpack" directory which contains the configuration scripts for webpack needed bundled to your final JS file

    2. "quotes" directory which contains the actual JS files that will be bundled. After renaming it to fit your grid (e.g. If you have a grid that's called 'ProductGrid', you can rename it to "product") you will place your extension loading file inside it

    3. package.json and webpack.config.js which are the npm and webpack config files

  3. Create the same directory structure under the root of your module (e.g. "modules/mymodule/js") including all subdirectories with "quotes" renamed as you wish. Inside your "views" directory ("modules/mymodule/views"*) create a "js" directory.

    *this is the place where you should place all the FE stuff, if you chose a different one you need to update the "output" definition for webpack inside "common.js" but you should use it as it is suggested.

  4. Copy the very same files in the same folders

  5. Now you need to:

    1. Update webpack entries in common.js:

      //original
      module.exports = {
        externals: {
          jquery: 'jQuery',
        },
        entry: {
          quotes: './quotes',
          quote_form: './quotes/form',
        },
      
      //modified
      module.exports = {
        externals: {
          jquery: 'jQuery',
        },
        entry: {
          mygrid: './mygrid',
        },

      where "mygrid" is the name you chose at point 2.2

    2. Update the resolution paths in the same file:

      //this block is at the top of the file
      const psRootDir = path.resolve(process.env.PWD, '../../../');
      const psJsDir = path.resolve(psRootDir, 'admin-dev/themes/new-theme/js');
      const psComponentsDir = path.resolve(psJsDir, 'components');
      //add an app dir which is needed by other components on which the extensions depend 
      const psAppDir = path.resolve(psJsDir, 'app');
      
      //this block is a bit below the exports we changed before
      resolve: {
          extensions: ['.js', '.vue', '.json'],
          alias: {
            //this is already present
            '@components': psComponentsDir,
             //this is what you add
            '@app': psAppDir,
          },
        },

       

    3. Rename the grid as explained in the doc to match the grid_id you have defined inside the GridDefinitionFactory in "index.js". You should also remove any extensions you are not using as not to load them needlessly

Now you can navigate from a terminal to your "js" folder and run "npm install" and once its finished "npm run dev" or "npm run build". If everything works fine, you'll see no errors (they are pretty clear and marked red) and the terminal will hang if you have used run dev (since inside the npm script definition inside "package.json" there is a watch flag that recompiles whenever the file changes); you can just interrupt it.

At this point, inside "views/js" you'll find a js file whose name starts with the grid name you chose at point 5.1 + bundle.js (e.g. "mygrid.bundle.js"). This is the final file that you need to include inside the twig template as per docs, like:

{% block javascripts %}
  {{ parent() }}
  <script src="{{ asset('../modules/mymodule/views/js/mygrid.bundle.js') }}"></script>
  <script src="{{ asset('themes/default/js/bundle/pagination.js') }}"></script>
{% endblock %}

Reload the page (check that you have disable caches from the BO performance section and if not do it and clean the cache) and try to clear filters.

As for the controller issue:

Quote

Moreover in the documentation, you describe a search action to be implemented. But nowhere is described how this route is called and when. So I really don't understand the process of Grid filters. And for the admin_common_reset_search, it uses a controller value and action. It does not say where should we configure or set this controller value so it can match...

I've not used the custom search action but the common one. Regardless, keep in mind that the grid filters are a form that POST onto itself which means you can define two different Symfony routes that answer two different HTTP verbs, POST and GET, like this:

//route for list action which is your index method inside the controller
my_route_summary_index:
  path: //path to your controller
  methods: [GET]
  defaults:
    _controller: //reference to the index method of your controller
    _legacy_controller: //same values you'd use for installTabs method (the one to get links in BO sidebar)
    _legacy_link: //same values you'd use for installTabs method (the one to get links in BO sidebar)

my_route_product_summary_search:
  path: //path to your controller, the same as above but below we put POST instead of GET
  methods: [POST]
  defaults:
    //this call the common search controller but you can use your own
    _controller: PrestaShopBundle:Admin\Common:searchGrid
    gridDefinitionFactoryServiceId: //your grid service
    redirectRoute: my_route_summary_index
    _legacy_controller: //same values as above
    _legacy_link: //same values as above followed by ":submitFilter<mygridname>" e.g. AdminMyModuleMyGrid:submitFiltermygrid

And you're done.

Edit: There is an ongoing debate among PrestaShop developers on whether or not to provide something to avoid the hassle of going through the steps required to enable the extension. See GitHub issues: https://github.com/PrestaShop/PrestaShop/pull/20591 and https://github.com/PrestaShop/PrestaShop/pull/21016

Gionatan

Gionatan


forgot to mention github issues on the topic

Seems a bit of an old post, but I'm replying in case OP is still interested or somebody else stumbles upon this problem

I've ran into the same issue and solved as follows; beside the solution I'm providing a bit of an explanation and some stuff I've checked before resolving.

Check out this notes before reading if you want, as some thoughts to keep in mind for the future. Feel free to skip:

  1. PrestaShop version is not mentioned in your post
  2. I'm working with 1.7.7.3 development version
  3. I'm working with doc for 1.7
  4. This is a personal opinion and is not meant to disrespect the work of the mantainers: some sections of the doc seem incomplete and a work in progress (bottom page has the latest update which show many pages have been recently updated) and some require a bit of Symfony knowledge or may assume other knowledge (npm, webpack etc.) or knowledge from other sections that you may have not read because they are outside your area of interest (e.g. theme development) or just overlooked. All of this is more than fine by me, it's just an indication that you may want to look into other stuff beside the doc itself

As for the grid issue:

Quote

It really seems to me that no js is linked to my grid template so nothing is triggered.

This is indeed the problem; in this section of the doc (which isn't the module development but the core reference) is explained how to add JS features to your grid which, by default, has none. Such features are implemented inside the folder "admin-dev/themes/new-theme/js/components" and "admin-dev/themes/new-theme/js/app/utils".

However, as stated, the guide is meant for core and not module development so it will most likely fail or feel lacking of details.

Here's what you need to do:

  1. Create a JS file that initializes the required components described in the docs (SortingExtension, FiltersResetExtension and such, depending on which ones you want to use). This is how it's done in the doc:
     
    import Grid from '../../components/grid/grid';
    import SortingExtension from '../../components/grid/extension/sorting-extension';
    import FiltersResetExtension from '../../components/grid/extension/filters-reset-extension';
    import ReloadListActionExtension from '../../components/grid/extension/reload-list-extension';
    import ColumnTogglingExtension from '../../components/grid/extension/column-toggling-extension';
    import SubmitRowActionExtension from '../../components/grid/extension/action/row/submit-row-action-extension';
    import SubmitBulkExtension from '../../components/grid/extension/submit-bulk-action-extension';
    import BulkActionCheckboxExtension from '../../components/grid/extension/bulk-action-checkbox-extension';
    import ExportToSqlManagerExtension from '../../components/grid/extension/export-to-sql-manager-extension';
    
    const $ = window.$;
    
    $(() => {
      const taxGrid = new Grid('tax');
    
      taxGrid.addExtension(new ExportToSqlManagerExtension());
      taxGrid.addExtension(new ReloadListActionExtension());
      taxGrid.addExtension(new SortingExtension());
      taxGrid.addExtension(new FiltersResetExtension());
      taxGrid.addExtension(new ColumnTogglingExtension());
      taxGrid.addExtension(new SubmitRowActionExtension());
      taxGrid.addExtension(new SubmitBulkExtension());
      taxGrid.addExtension(new BulkActionCheckboxExtension());
    });

    But as you can see, the imports are using relative paths that are not correct for a module.
    You can probably change them to fit the "modules" directory but that may result in errors when working on a different environment (beside being a bad habit).

  2. In order to avoid using the relative paths, you need to implement webpack to use the appropriate ones. Luckily, inside this official tutorial there is already one that has everything you need. Download it and check out the "js" directory where you'll find:

    1. ".webpack" directory which contains the configuration scripts for webpack needed bundled to your final JS file

    2. "quotes" directory which contains the actual JS files that will be bundled. After renaming it to fit your grid (e.g. If you have a grid that's called 'ProductGrid', you can rename it to "product") you will place your extension loading file inside it

    3. package.json and webpack.config.js which are the npm and webpack config files

  3. Create the same directory structure under the root of your module (e.g. "modules/mymodule/js") including all subdirectories with "quotes" renamed as you wish. Inside your "views" directory ("modules/mymodule/views"*) create a "js" directory.

    *this is the place where you should place all the FE stuff, if you chose a different one you need to update the "output" definition for webpack inside "common.js" but you should use it as it is suggested.

  4. Copy the very same files in the same folders

  5. Now you need to:

    1. Update webpack entries in common.js:

      //original
      module.exports = {
        externals: {
          jquery: 'jQuery',
        },
        entry: {
          quotes: './quotes',
          quote_form: './quotes/form',
        },
      
      //modified
      module.exports = {
        externals: {
          jquery: 'jQuery',
        },
        entry: {
          mygrid: './mygrid',
        },

      where "mygrid" is the name you chose at point 2.2

    2. Update the resolution paths in the same file:

      //this block is at the top of the file
      const psRootDir = path.resolve(process.env.PWD, '../../../');
      const psJsDir = path.resolve(psRootDir, 'admin-dev/themes/new-theme/js');
      const psComponentsDir = path.resolve(psJsDir, 'components');
      //add an app dir which is needed by other components on which the extensions depend 
      const psAppDir = path.resolve(psJsDir, 'app');
      
      //this block is a bit below the exports we changed before
      resolve: {
          extensions: ['.js', '.vue', '.json'],
          alias: {
            //this is already present
            '@components': psComponentsDir,
             //this is what you add
            '@app': psAppDir,
          },
        },

       

    3. Rename the grid as explained in the doc to match the grid_id you have defined inside the GridDefinitionFactory in "index.js". You should also remove any extensions you are not using as not to load them needlessly

Now you can navigate from a terminal to your "js" folder and run "npm install" and once its finished "npm run dev" or "npm run build". If everything works fine, you'll see no errors (they are pretty clear and marked red) and the terminal will hang if you have used run dev (since inside the npm script definition inside "package.json" there is a watch flag that recompiles whenever the file changes); you can just interrupt it.

At this point, inside "views/js" you'll find a js file whose name starts with the grid name you chose at point 5.1 + bundle.js (e.g. "mygrid.bundle.js"). This is the final file that you need to include inside the twig template as per docs, like:

{% block javascripts %}
  {{ parent() }}
  <script src="{{ asset('../modules/mymodule/views/js/mygrid.bundle.js') }}"></script>
  <script src="{{ asset('themes/default/js/bundle/pagination.js') }}"></script>
{% endblock %}

Reload the page (check that you have disable caches from the BO performance section and if not do it and clean the cache) and try to clear filters.

As for the controller issue:

Quote

Moreover in the documentation, you describe a search action to be implemented. But nowhere is described how this route is called and when. So I really don't understand the process of Grid filters. And for the admin_common_reset_search, it uses a controller value and action. It does not say where should we configure or set this controller value so it can match...

I've not used the custom search action but the common one. Regardless, keep in mind that the grid filters are a form that POST onto itself which means you can define two different Symfony routes that answer two different HTTP verbs, POST and GET, like this:

//route for list action which is your index method inside the controller
my_route_summary_index:
  path: //path to your controller
  methods: [GET]
  defaults:
    _controller: //reference to the index method of your controller
    _legacy_controller: //same values you'd use for installTabs method (the one to get links in BO sidebar)
    _legacy_link: //same values you'd use for installTabs method (the one to get links in BO sidebar)

naor_product_summary_search:
  path: //path to your controller, the same as above but below we put POST instead of GET
  methods: [POST]
  defaults:
    //this call the common search controller but you can use your own
    _controller: PrestaShopBundle:Admin\Common:searchGrid
    gridDefinitionFactoryServiceId: //your grid service
    redirectRoute: my_route_summary_index
    _legacy_controller: //same values as above
    _legacy_link: //same values as above followed by ":submitFilter<mygridname>" e.g. AdminMyModuleMyGrid:submitFiltermygrid

And you're done.

Edit: There is an ongoing debate among PrestaShop developers on whether or not to provide something to avoid the hassle of going through the steps required to enable the extension. See GitHub issues: https://github.com/PrestaShop/PrestaShop/pull/20591 and https://github.com/PrestaShop/PrestaShop/pull/21016

Gionatan

Gionatan

Seems a bit of an old post, but I'm replying in case OP is still interested or somebody else stumbles upon this problem

I've ran into the same issue and solved as follows; beside the solution I'm providing a bit of an explanation and some stuff I've checked before resolving.

Check out this notes before reading if you want, as some thoughts to keep in mind for the future. Feel free to skip:

  1. PrestaShop version is not mentioned in your post
  2. I'm working with 1.7.7.3 development version
  3. I'm working with doc for 1.7
  4. This is a personal opinion and is not meant to disrespect the work of the mantainers: some sections of the doc seem incomplete and a work in progress (bottom page has the latest update which show many pages have been recently updated) and some require a bit of Symfony knowledge or may assume other knowledge (npm, webpack etc.) or knowledge from other sections that you may have not read because they are outside your area of interest (e.g. theme development) or just overlooked. All of this is more than fine by me, it's just an indication that you may want to look into other stuff beside the doc itself

As for the grid issue:

Quote

It really seems to me that no js is linked to my grid template so nothing is triggered.

This is indeed the problem; in this section of the doc (which isn't the module development but the core reference) is explained how to add JS features to your grid which, by default, has none. Such features are implemented inside the folder "admin-dev/themes/new-theme/js/components" and "admin-dev/themes/new-theme/js/app/utils".

However, as stated, the guide is meant for core and not module development so it will most likely fail or feel lacking of details.

Here's what you need to do:

  1. Create a JS file that initializes the required components described in the docs (SortingExtension, FiltersResetExtension and such, depending on which ones you want to use). This is how it's done in the doc:
     
    import Grid from '../../components/grid/grid';
    import SortingExtension from '../../components/grid/extension/sorting-extension';
    import FiltersResetExtension from '../../components/grid/extension/filters-reset-extension';
    import ReloadListActionExtension from '../../components/grid/extension/reload-list-extension';
    import ColumnTogglingExtension from '../../components/grid/extension/column-toggling-extension';
    import SubmitRowActionExtension from '../../components/grid/extension/action/row/submit-row-action-extension';
    import SubmitBulkExtension from '../../components/grid/extension/submit-bulk-action-extension';
    import BulkActionCheckboxExtension from '../../components/grid/extension/bulk-action-checkbox-extension';
    import ExportToSqlManagerExtension from '../../components/grid/extension/export-to-sql-manager-extension';
    
    const $ = window.$;
    
    $(() => {
      const taxGrid = new Grid('tax');
    
      taxGrid.addExtension(new ExportToSqlManagerExtension());
      taxGrid.addExtension(new ReloadListActionExtension());
      taxGrid.addExtension(new SortingExtension());
      taxGrid.addExtension(new FiltersResetExtension());
      taxGrid.addExtension(new ColumnTogglingExtension());
      taxGrid.addExtension(new SubmitRowActionExtension());
      taxGrid.addExtension(new SubmitBulkExtension());
      taxGrid.addExtension(new BulkActionCheckboxExtension());
    });

    But as you can see, the imports are using relative paths that are not correct for a module.
    You can probably change them to fit the "modules" directory but that may result in errors when working on a different environment (beside being a bad habit).

  2. In order to avoid using the relative paths, you need to implement webpack to use the appropriate ones. Luckily, inside this official tutorial there is already one that has everything you need. Download it and check out the "js" directory where you'll find:

    1. ".webpack" directory which contains the configuration scripts for webpack needed bundled to your final JS file

    2. "quotes" directory which contains the actual JS files that will be bundled. After renaming it to fit your grid (e.g. If you have a grid that's called 'ProductGrid', you can rename it to "product") you will place your extension loading file inside it

    3. package.json and webpack.config.js which are the npm and webpack config files

  3. Create the same directory structure under the root of your module (e.g. "modules/mymodule/js") including all subdirectories with "quotes" renamed as you wish. Inside your "views" directory ("modules/mymodule/views"*) create a "js" directory.

    *this is the place where you should place all the FE stuff, if you chose a different one you need to update the "output" definition for webpack inside "common.js" but you should use it as it is suggested.

  4. Copy the very same files in the same folders

  5. Now you need to:

    1. Update webpack entries in common.js:

      //original
      module.exports = {
        externals: {
          jquery: 'jQuery',
        },
        entry: {
          quotes: './quotes',
          quote_form: './quotes/form',
        },
      
      //modified
      module.exports = {
        externals: {
          jquery: 'jQuery',
        },
        entry: {
          mygrid: './mygrid',
        },

      where "mygrid" is the name you chose at point 2.2

    2. Update the resolution paths in the same file:

      //this block is at the top of the file
      const psRootDir = path.resolve(process.env.PWD, '../../../');
      const psJsDir = path.resolve(psRootDir, 'admin-dev/themes/new-theme/js');
      const psComponentsDir = path.resolve(psJsDir, 'components');
      //add an app dir which is needed by other components on which the extensions depend 
      const psAppDir = path.resolve(psJsDir, 'app');
      
      //this block is a bit below the exports we changed before
      resolve: {
          extensions: ['.js', '.vue', '.json'],
          alias: {
            //this is already present
            '@components': psComponentsDir,
             //this is what you add
            '@app': psAppDir,
          },
        },

       

    3. Rename the grid as explained in the doc to match the grid_id you have defined inside the GridDefinitionFactory in "index.js". You should also remove any extensions you are not using as not to load them needlessly

Now you can navigate from a terminal to your "js" folder and run "npm install" and once its finished "npm run dev" or "npm run build". If everything works fine, you'll see no errors (they are pretty clear and marked red) and the terminal will hang if you have used run dev (since inside the npm script definition inside "package.json" there is a watch flag that recompiles whenever the file changes); you can just interrupt it.

At this point, inside "views/js" you'll find a js file whose name starts with the grid name you chose at point 5.1 + bundle.js (e.g. "mygrid.bundle.js"). This is the final file that you need to include inside the twig template as per docs, like:

{% block javascripts %}
  {{ parent() }}
  <script src="{{ asset('../modules/mymodule/views/js/mygrid.bundle.js') }}"></script>
  <script src="{{ asset('themes/default/js/bundle/pagination.js') }}"></script>
{% endblock %}

Reload the page (check that you have disable caches from the BO performance section and if not do it and clean the cache) and try to clear filters.

As for the controller issue:

Quote

Moreover in the documentation, you describe a search action to be implemented. But nowhere is described how this route is called and when. So I really don't understand the process of Grid filters. And for the admin_common_reset_search, it uses a controller value and action. It does not say where should we configure or set this controller value so it can match...

I've not used the custom search action but the common one. Regardless, keep in mind that the grid filters are a form that POST onto itself which means you can define two different Symfony routes that answer two different HTTP verbs, POST and GET, like this:

//route for list action which is your index method inside the controller
my_route_summary_index:
  path: //path to your controller
  methods: [GET]
  defaults:
    _controller: //reference to the index method of your controller
    _legacy_controller: //same values you'd use for installTabs method (the one to get links in BO sidebar)
    _legacy_link: //same values you'd use for installTabs method (the one to get links in BO sidebar)

naor_product_summary_search:
  path: //path to your controller, the same as above but below we put POST instead of GET
  methods: [POST]
  defaults:
    //this call the common search controller but you can use your own
    _controller: PrestaShopBundle:Admin\Common:searchGrid
    gridDefinitionFactoryServiceId: //your grid service
    redirectRoute: my_route_summary_index
    _legacy_controller: //same values as above
    _legacy_link: //same values as above followed by ":submitFilter<mygridname>" e.g. AdminMyModuleMyGrid:submitFiltermygrid

And you're done.

×
×
  • Create New...