Reading list Switch to dark mode

    How to Create Custom DataGrid using Akeneo

    Updated 13 August 2018

    In Akeneo, If you want to display a list of item in a grid system with CRUD functionalities. You can use Akeneo Datagrid. the benefits of Akeneo grid component are filtering, sorting, pagination, and search item. Using Akeneo you can define the form to edit or display an item easily.  Let’s start with an example with multi credentials for a connector.

    First, you need to create an entity for data grid items. As Akeneo relies heavily on standard tools like Doctrine,

     

    # /src/Webkul/CustomBundle/Entity/CredentialsConfig.php
    
    <?php
    
    namespace Webkul\CustomBundle\Entity;
    
    /**
     * CredentialsConfig
     */
    class CredentialsConfig
    {
        /**
         * @var integer
         */
        private $id;
    
        /**
         * @var string
         */
        private $url;
    
        /**
         * @var string
         */
        private $apiUser;
    
        /**
         * @var string
         */
        private $apiKey;
    
        /**
         * @var boolean
         */
        private $active = 0;
    
    
        /**
         * Get id
         *
         * @return integer
         */
        public function getId()
        {
            return $this->id;
        }
    
        /**
         * Set url
         *
         * @param string $url
         *
         * @return CredentialsConfig
         */
        public function setUrl($url)
        {
            $this->url = $url;
    
            return $this;
        }
    
        /**
         * Get url
         *
         * @return string
         */
        public function getUrl()
        {
            return $this->url;
        }
    
        /**
         * Set apiUser
         *
         * @param string $apiUser
         *
         * @return CredentialsConfig
         */
        public function setApiUser($apiUser)
        {
            $this->apiUser = $apiUser;
    
            return $this;
        }
    
        /**
         * Get apiUser
         *
         * @return string
         */
        public function getApiUser()
        {
            return $this->apiUser;
        }
    
        /**
         * Set apiKey
         *
         * @param string $apiKey
         *
         * @return CredentialsConfig
         */
        public function setApiKey($apiKey)
        {
            $this->apiKey = $apiKey;
    
            return $this;
        }
    
        /**
         * Get apiKey
         *
         * @return string
         */
        public function getApiKey()
        {
            return $this->apiKey;
        }
    
        /**
         * Set active
         *
         * @param boolean $active
         *
         * @return CredentialsConfig
         */
        public function setActive($active)
        {
            $this->active = $active;
    
            return $this;
        }
    
        /**
         * Get active
         *
         * @return boolean
         */
        public function getActive()
        {
            return $this->active;
        }
    
        /**
         * Change the active value vice-versa
         */
        public function activation() 
        {
            $this->active = !$this->active;
    
            return $this;
        }
        /**
         * @var string
         */
        private $resources;
    
    
        /**
         * Set resources
         *
         * @param string $resources
         *
         * @return CredentialsConfig
         */
        public function setResources($resources)
        {
            $this->resources = $resources;
    
            return $this;
        }
    
        /**
         * Get resources
         *
         * @return string
         */
        public function getResources()
        {
            return $this->resources;
        }
    }
    

     

    Now create a Datagrid.

    Searching for an experienced
    Akeneo Company ?
    Find out More
    #src/Webkul/CustomBundle/Resources/config/datagrid
    datagrid:
        webkul-custom-credentials-mapping-grid:
            extended_entity_name: Webkul\CustomBundle\Entity\CredentialsConfig
            options:
                entityHint: CredentialsConfig
                manageFilters: false
            source:
                acl_resource: webkul_custom_connector_configuration
                type: custom_datasource_credentials
                entity: 'Webkul\CustomBundle\Entity\CredentialsConfig'
                query:
                    select:
                        - wem.id
                        - wem.url
                        - wem.apiUser
                        - wem.apiKey
                        - wem.active
                    from:
                        - { table: 'Webkul\CustomBundle\Entity\CredentialsConfig', alias: wem }
            columns:
                url:
                    label: webkul_custom.credentials.grid.export_mappings.columns.url
                    frontend_type: label
                apiUser:
                    label: webkul_custom.credentials.grid.export_mappings.columns.apiUser
                active:
                    label: Activated
                    type: twig
                    template: PimDataGridBundle:Property:activated.html.twig
                    frontend_type: html
    
            properties:
                id: ~
                edit_link:
                    type: url
                    route: webkul_custom_credentials_edit
                    params:
                        - id
                toggle_link:
                    type: url
                    route: webkul_custom_credentials_change_status
                    params:
                        - id
                delete_link:
                    type: url
                    route: webkul_custom_credentials_delete
                    params:
                        - id
            sorters:
                columns:
                    url:
                        data_name: wem.url
                    apiUser:
                        data_name: wem.apiUser
                    active:
                        data_name: wem.active
                default:
                    url: '%oro_datagrid.extension.orm_sorter.class%::DIRECTION_ASC'
    
            filters:
                columns:
                    url:
                        type: search
                        data_name: wem.url
                        
                    active:
                        type:      boolean
                        label:     Activated
                        data_name: wem.active
    
            actions:
                toggle:
                    launcherOptions:
                        className: AknIconButton AknIconButton--small AknIconButton--switch
                    type:         navigate
                    label:        Change status
                    link:         toggle_link
                    acl_resource: webkul_custom_connector_configuration
                edit:
                    launcherOptions:
                        className: AknIconButton AknIconButton--small AknIconButton--edit
                    type:      navigate
                    label:     Edit
                    link:      edit_link
                    acl_resource: webkul_custom_connector_configuration
                    rowAction: true
                delete:
                    launcherOptions:
                        className: AknIconButton AknIconButton--small AknIconButton--trash
                    type:          delete
                    label:         Delete
                    link:          delete_link
                    acl_resource:  webkul_custom_connector_configuration

     

    you need to define the data source service for datagrid.

    #src/Webkul/customBundle/Resources/config
    
    services:    
        webkul_custom_datagrid.datasource.credentails:
            class: Webkul\customBundle\Datasource\CredentailsDatasource
            arguments:
                - '@webkul_custom.repository.credentials'
                - '@pim_datagrid.datasource.result_record.hydrator.default'
            tags:
                - { name: oro_datagrid.datasource, type: custom_datasource_credentials }

    Define the Datasource class which is used in data source service.

    <?php
    
    namespace Webkul\CustomBundle\Datasource;
    
    use Pim\Bundle\DataGridBundle\Datasource\Datasource;
    use Webkul\CustomBundle\Repository\CustomCredentailsRepository;
    use Pim\Bundle\DataGridBundle\Datasource\ResultRecord\HydratorInterface;
    
    
    class CredentailsDatasource extends Datasource
    {
        /** @var CustomCredentailsRepository */
        protected $repository;
    
        /** @var CustomObjectIdHydrator */
        protected $hydrator;
    
        /** @var array */
        protected $parameters = [];
    
        /**
         * @param CustomCredentailsRepository $om
         * @param HydratorInterface          $hydrator
         */
        public function __construct(CustomCredentailsRepository $repository, HydratorInterface $hydrator)
        {
            $this->repository = $repository;
            $this->hydrator = $hydrator;
        }
    
        /**
         * @param string $method the query builder creation method
         * @param array  $config the query builder creation config
         *
         * @return Datasource
         */
        protected function initializeQueryBuilder($method, array $config = [])
        {
            $this->qb = $this->repository->$method('wem');
            
            return $this;
        }
    
        /**
         * {@inheritdoc}
         */
        public function getResults()
        {
            return $this->hydrator->hydrate($this->qb);
        }
    }
    

    Define the Access control list ( acl.yml )

    #src/Webkul/CustomBundle/Resource/config/acl.yml
    
    webkul_custom_connector_configuration:
        type: action
        label: Custom Connector
        group_name: ~
    
    
    

    Define the following routes as used in datagrid for actions edit, change status, delete.

    • webkul_custom_credentials_edit
    • webkul_custom_credentials_change_status
    • webkul_custom_credentials_delete
    #src/Webkul/customBundle/Resources/config/routing.yml
    
    webkul_custom_credentials_edit:
        path: /custom-configuration/rest/edit/{id}
        requirements:
            id: \d+
    
    webkul_custom_credentials_change_status:
        path: /custom-configuration/rest/toggle/{id}
        defaults: { _controller: customBundle:Rest\Configuration:toggle }
        requirements:
            id: \d+
    
    webkul_custom_credentials_delete:
      path: /custom-configuration/rest/credentials/{id}
      defaults: { _controller: customBundle:Rest\Configuration:deleteCredentail }
      requirements:
      id: \d+
      methods: [DELETE]
    
    
    Define the methods for changestatus, and delete
    # Webkul\CustomBundle\Controller\Rest\ConfigurationController
    
     /**
         * Remove url
         *
         * @AclAncestor("webkul_custom_connector_configuration")
         *
         * @return JsonResponse
         */
        public function deleteCredentailAction($id)
        {
            $mapping = $this->get('webkul_custom.repository.credentials')->find($id);
            if(!$mapping) {
                throw new NotFoundHttpException(
                        sprintf('Instance with id "%s" not found', $id)
                    );
            }
            $em = $this->getDoctrine()->getManager();
            $em->remove($mapping);
            $em->flush();
    
            return new Response(null, Response::HTTP_NO_CONTENT);
        }
    
    
    
        /**
         * Activate/Deactivate a credential instance
         *
         * @param CredentialsConfig $configValue
         *
         * @AclAncestor("webkul_custom_connector_configuration")
         *
         * @return JsonResponse
         */
        public function toggleAction(CredentialsConfig $configValue)
        {
            try{
                $em = $this->getDoctrine()->getManager();
    
                //change current active value
                $configValue->activation();
                $em->persist($configValue);
                $em->flush();
                
            } catch(Exception $e) {
                return new JsonResponse(['route' => 'webkul_custom_connector_configuration']);
            }
            
            return new JsonResponse(['route' => 'webkul_custom_connector_configuration']);
        }
    Model form to create credential Instance
    extensions:
        # Attribute Mapping Model
        webkul-custom-connector-create-instance-modal:
            module: custom/form/configuration/create/modal
            config:
                labels:
                    title: webkul_custom_connector.create_popin.title
                    subTitle: webkul_custom_connector.item.credential
                picture: illustrations/Groups.svg
                successMessage: pim_enrich.entity.group_type.message.created
                editRoute: webkul_custom_credentials_edit
                postUrl: webkul_custom_credentials_create
                routerKey: id
    
        webkul-custom-connector-create-instance-modal-host:
            module: custom/form/configuration/create/form
            parent: webkul-custom-connector-create-instance-modal
            targetZone: fields
            position: 10
            config:
                labels:
                    title: webkul_custom_connector.create_popin.title
                    subTitle: webkul_custom_connector.item.export_mapping
                identifier: host
                label: webkul_custom_connector.hostName
    Create the js module and registered in requirejs.yml
    #src/Webkul/customBundle/Resources/config/requirejs.yml
    config:
        paths:
            custom/form/configuration/create/modal: custom/js/form/configuration/create/modal
            custom/form/configuration/create/form: custom/js/form/configuration/create/form
    
        config:
            pim/controller-registry:
                controllers:
                    webkul_custom_credentials_change_status:
                        module: pim/controller/redirect
                    webkul_custom_credentials_edit:
                        module: custom/form/configuration/credentials/edit

    Create instance js module.

    // src/Webkul/customBundle/Resources/public/js/form/configuration/create/modal.js
    
    'use strict';
    
    define(
        [
            'jquery',
            'underscore',
            'oro/translator',
            'routing',
            'pim/form/common/creation/modal',
            'oro/loading-mask',
            'pim/router',
        ],
        function (
            $,
            _,
            __,
            Routing,
            BaseModal,
            LoadingMask,
            router,
        ) {
            return BaseModal.extend({
                validationErrors: {},
                
                /**
                 * {@inheritdoc}
                 */
                save() {
                    this.validationErrors = {};
    
                    const loadingMask = new LoadingMask();
                    this.$el.empty().append(loadingMask.render().$el.show());
    
                    let data = this.getFormData();
    
                    return $.ajax({
                        url: Routing.generate(this.config.postUrl),
                        type: 'POST',
                        data: JSON.stringify(data)
                    }).fail(function (response) {
                        this.validationErrors = response.responseJSON;
                        this.render();
                    }.bind(this))
                    .always(() => loadingMask.remove());
                }
            });
        }
    );
    
    Create the form for the above module.
    // src/Webkul/customBundle/Resources/public/js/form/configuration/create
    define([
        'jquery',
        'underscore',
        'custom/form/configuration/create/modal',
        'pim/user-context',
        'oro/translator',
        'pim/fetcher-registry',
        'pim/initselect2',
        'custom/template/configuration/tab/credential',
        'routing',
        'oro/messenger',
        'oro/loading-mask'
    ], function(
        $,
        _,
        BaseModal,
        UserContext,
        __,
        FetcherRegistry,
        initSelect2,
        template,
        Routing,
        messenger,
        LoadingMask
        ) {
    
        return BaseModal.extend({
            loadingMask: null,
                updateFailureMessage: __('error to fetch token'),
                updateSuccessMessage: __('pim_enrich.entity.info.update_successful'),
                label: __('pim_enrich.entity.save.label'),
                isGroup: true,
                label: __('custom.credential.tab'),
                template: _.template(template),
                code: 'custom_connector_credential',
                controls: [{
                    'label' : 'custom.form.properties.host_name.title',
                    'name': 'hostName',
                    'type': 'text'
                }, {
                    'label' : 'custom.form.properties.apiUser.title',
                    'name': 'apiUser',
                    'type': 'text'
                }, {
                    'label' : 'custom.form.properties.apiKey.title',
                    'name': 'apiKey',
                    'type': 'password'
                }],
    
                errors: [],
                events: {
                    'change .AknFormContainer-Credential input': 'updateModel',
                },
               
                 /**
                 * {@inheritdoc}
                 */
                render: function () {
                    $('#container .AknButtonList[data-drop-zone="buttons"] div:nth-of-type(1)').hide();
                    
                    self = this;
                    var controls;
                    var controls2;
                    
                    this.$el.html(this.template({
                        controls: self.controls,
                        controls2: self.controls2,
                        model: self.getFormData(),
                        errors: this.parent.validationErrors
                    }));
                    this.delegateEvents();
                },
                /**
                 * Update model after value change
                 *
                 * @param {Event} event
                 */
                updateModel: function (event) {
                    var data = this.getFormData();
                    switch(event.target.id) {
                        case 'pim_enrich_entity_form_hostName':
                            data['hostName'] = event.target.value
                            break;
                        case 'pim_enrich_entity_form_apiUser':
                            data['apiUser'] = event.target.value
                            break;
                        case 'pim_enrich_entity_form_apiKey':
                            data['apiKey'] = event.target.value
                    }
                    
                    this.setData(data);
                },
                
                stringify: function(formData) {
                    if('undefined' != typeof(formData['mapping']) && formData['mapping'] instanceof Array) {
                        formData['mapping'] = $.extend({}, formData['mapping']);
                    }
    
                    return JSON.stringify(formData);                
                },
    
                /**
                 * {@inheritdoc}
                 */
                getSaveUrl: function () {
                    var route = Routing.generate('webkul_custom_connector_configuration_post');
                    return route;
                },
                /**
                 * Sets errors
                 *
                 * @param {Object} errors
                 */
                setValidationErrors: function (errors) {
                    this.parent.validationErrors = errors.response;
                    this.render();
                },
    
                /**
                 * Resets errors
                 */
                resetValidationErrors: function () {
                    this.parent.validationErrors = {};
                    this.render();
                },
    
                            /**
                 * Show the loading mask
                 */
                showLoadingMask: function () {
                    this.loadingMask = new LoadingMask();
                    this.loadingMask.render().$el.appendTo(this.getRoot().$el).show();
                },
    
                /**
                 * Hide the loading mask
                 */
                hideLoadingMask: function () {
                    this.loadingMask.hide().$el.remove();
                },
             
        });
    });
    
    Now grid is ready to render.
    Additionally, you can add mass edit, delete options for items in the datagrid.
    .
    Referances:
    https://docs.akeneo.com/1.3/cookbook/custom_entity/creating_a_custom_entity.html
      
    https://docs.akeneo.com/1.6/cookbook/ui_customization/create_a_reference_data_crud.html
     .
    Thanks

    . . .

    Leave a Comment

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


    Be the first to comment.

    Back to Top

    Message Sent!

    If you have more details or questions, you can reply to the received confirmation email.

    Back to Home