volume_up

A critical vulnerability was discovered in React Server Components (Next.js). Our systems remain protected but we advise to update packages to newest version. Learn More

volume_up

A critical vulnerability was discovered in React Server Components (Next.js). Our systems remain protected but we advise to update packages to newest version. Learn More

Extending dgrid formatters

I'm looking for ways to improve experience for editors by adding some more information into the block search reusults or the tooltip:

I've explored a lot of files, and I think what I have to do is to add or override default formatter to \epi_modules\CMS\11.24.1\ClientResources\epi-cms\dgrid\formatters. Haven't found much resources.

What I tried so far:

  1. Copied ClientResources\epi-cms\dgrid\formatters.js.uncompressed.js to \ClientResources\Scripts\AlloyFormatters.js
  2. Created Initializer.js file:
    define([
        "dojo",
        'dojo/_base/declare',
        // Parent class
        'epi/_Module',
        // Commands
        'alloy/AlloyFormatters'
    ], function (
        // Dojo
        dojo,
        declare,
        // Parent class
        _Module,
        AlloyFormatters
    ) {
     
        return declare([_Module], {
     
            initialize: function () {
                this.inherited(arguments);
            }
        });
    });​
  3. Updated module config to initialize my module after Shell and CMS:
    <?xml version="1.0" encoding="utf-8"?>
    <module>
        <assemblies>
    	    <!-- This adds the Alloy template assembly to the "default module" -->
            <add assembly="AlloyDemo" />
        </assemblies>
        <clientResources>
            <add name="epi-cms.widgets.base" path="Styles/Styles.css" resourceType="Style"/>
        </clientResources>
      <clientModule initializer="alloy.Initializer">
        <moduleDependencies>
          <add dependency="Shell" type="RunAfter" />
          <add dependency="CMS" type="RunAfter" />
        </moduleDependencies>
      </clientModule>
        <dojo>
            <!-- Add a mapping from alloy to ~/ClientResources/Scripts to the dojo loader configuration -->
            <paths>
                <add name="alloy" path="Scripts" />
            </paths>
        </dojo>
    </module>​

What I observe in when I debug the code is following:

  1. Default formatters register, by calling Formatter.addFormatter() method:
  2. My module is initialized, and calls method Formatter.addFormatter("contentItem", module.contentItemFactory, true); effectively overriding default implementation provided by default modules:

  3. However, when I type something in the block search field, and break in the JS, the formatter that is being picked is always the default one:

As you can see, it's the default implementation of contentItem formatter resolved, and not mine from AlloyFormatters.

As I'm no dojo-expert, I feel like I'm missing something very simple.

#223789
Edited, Jun 04, 2020 12:43
Vote:

I figured it out. The actual place to look into is/was epi-cms/widget/ReadOnlyContentList  - this component has a protected method, called _getBaseSettings() which returns configuration item, with direct reference to formatters.contentItemFactory() method.

So what I did, in module initializer I have put together following code:

define([
    "dojo",
    'dojo/_base/declare',
    // Parent class
    'epi/_Module',
    // Commands
    'alloy/AlloyFormatters',
    "epi-cms/widget/ReadOnlyContentList",
    // epi
    "epi/shell/dgrid/Formatter",

    "epi-cms/core/ContentReference",
    "epi-cms/dgrid/formatters"
], function (
    // Dojo
    dojo,
    declare,
    // Parent class
    _Module,
    AlloyFormatters,
    ReadOnlyContentList,
    Formatter,
    ContentReference,
    formatters
) {

    return declare([_Module], {

        initialize: function () {
            this.inherited(arguments);

            /*
             * Overriding default implementation of _getBaseSettings() method
             */
            ReadOnlyContentList.prototype._getBaseSettings = function (contextMenu) {
                
                /*
                 * This part is copy/pasted from original implementation
                 */
                var titleSelector = function (item) {
                    var reference = new ContentReference(item.contentLink);

                    return formatters.title(item.name, reference.id, item.contentTypeName);
                };

                var thumbnailSelector = function (item) {
                    return item.thumbnailUrl;
                };
                
                /*
                 * Here I build reference to my implementation of contentItemFactory() implementation
                 */
                var alloyFormatter = AlloyFormatters.contentItemFactory("name",
                    titleSelector,
                    null,
                    contextMenu,
                    thumbnailSelector,
                    undefined,
                    undefined,
                    true);

                /*
                 * Returning object  - only `formatters` option is overriden, rest is as in default implementation
                 */
                return {
                    store: this.store,
                    queryOptions: this.queryOptions,
                    formatters: [alloyFormatter],
                    deselectOnRefresh: true,
                    sort: this.queryOptions && this.queryOptions.sort
                };
            }
        }
    });
});

now my code runs :)

#223862
Edited, Jun 05, 2020 12:07
error This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.