Use a custom property in Action.isVisible or isEnabled

Sometimes, we want to use a custom property to decide if an action should be displayed, enabled or hidden. The items provided by ICN as parameters of these functions are items as they are shown in the view, as rows. They don’t have all properties fetched, only the system ones and the ones you configured to be shown as extra columns (since they have to be fetched in order to be displayed).

As you may have noticed when overriding the isVisible and isEnabled functions, they are synchronous and they expect an immediate return. That means fetching the attributes using the item.retrieveAttributes function won’t work since it’s an asynchronous function (there is one round trip made to the ICN server to fetch them).

In this post, we’ve seen how to fetch custom attributes for all rows without showing them in a column. We will now see another way to do this, by making the ContextMenu actually asynchronous. Since the isVisible and isEnabled functions are synchronous, we will actually retrieve the attributes before showing the Context Menu for the item.

Note that I don’t really like this method, because it will delay the Context Menu and makes ICN less reactive, which is not really confortable for users. Therefore, I would rather use one of the others ways here. But this way is easier and faster to implement so this is still good to know.

The idea is to replace the ResultSet.loadContextMenu function to first fully retrieve all items, then call normally the loadContextMenu function. Instead of calling retrieveAttribute individually on all items, we will use Repository.retrieveMultiItem to do only one server round-trip and make the menu more reactive. Downside of this method is that it will disconnect the items from their parent, and we need to reconnect it after retrieval if some functions (including your isVisible and isEnabled) are making use of it.

require(["dojo/_base/declare",
         "dojo/_base/lang",
         "dojo/_base/array",
         "dojo/aspect",
         "ecm/model/ResultSet"],
    function (declare, lang, array, aspect, ResultSet) {
        aspect.around(ResultSet.prototype, "loadContextMenu", function (original) {
            return function (items, callback) {
                if (items && items.length >= 1) {
                    var ids = [], parentFolder = items[0].parent;
                    // Create the array of ids
                    array.forEach(items, function (item) {
                        ids.push(item.id);
                    });
                    // Fetch attributes for all items
                    items[0].repository.retrieveMultiItem(ids, lang.hitch(this, function (res) {
                        // Restore parent because it might be important later in the code
                        array.forEach(res, function (r) {
                            r.parent = parentFolder;
                        });
                        original.call(this, res, callback);
                    }));
                } else {
                    original.call(this, items, callback);
                }
            };
        });
    });

When isVisible or isEnabled are called, items should now have all properties fetched.

Leave a Reply