Dynamic items selector from multiple content types Sitefinity [Part 2] [closed]

ぐ巨炮叔叔 提交于 2021-02-04 16:48:05

问题


  • Part 1 Link

Part-2

  1. Add sf-list-selector.js file under common folder and paste following javascript code:
(function ($) {
    angular.module('sfSelectors')
        .directive('sfListSelector', ['serverContext', '$q', function (serverContext, $q) {
            return {
                restrict: 'E',
                transclude: true,
                scope: {
                    //For single selection
                    sfSelectedItemId: '=?',
                    sfSelectedItem: '=?',
                    //For multiple selection
                    sfSelectedItems: '=?',
                    sfSelectedIds: '=?',
                    //For selected providers and item types
                    sfSelectedProviders: '=?',
                    sfSelectedItemtypes: '=?',
                    sfMissingSelectedItems: "=?",
                    sfProvider: '=?',
                    sfChange: '=',
                    sfSortable: '=?',
                    sfItemType: '=?',
                    sfIdentifierField: '@?',
                    sfDialogHeader: '@?',
                    sfKeepSelectedItemsBound: '@?',
                    sfExternalPages: '=?',
                    sfOpenExternalsInNewTab: '=',
                    sfTitle: '@?',
                    sfMaxItemsLimitation: '='
                },
                controller: function ($scope) {
                    this.defaultIdentifierField = 'Title';
                    this.identifierField = $scope.sfIdentifierField || this.defaultIdentifierField;
                    this.setIdentifierField = function (identifier) {
                        this.identifierField = identifier;
                        $scope.sfIdentifierField = identifier;
                    };
                    this.bindIdentifierField = function (item) {
                        if (item) {
                            var mainField = item[this.identifierField];
                            var valueProp = 'Value';
                            if (!mainField) { return item.Id; }
                            if (typeof mainField === 'string') { return mainField; }
                            else if (valueProp in mainField) { return mainField.Value; }
                        }
                    };
                    this.removeUnselectedItems = function () {
                        if ($scope.multiselect) {
                            var reoderedItems = [];
                            if ($scope.selectedItemsViewData && $scope.selectedItemsViewData.length > 0) {
                                for (var i = 0; i < $scope.selectedItemsViewData.length; i++) {
                                    for (var j = 0; j < $scope.selectedItemsInTheDialog.length; j++) {
                                        if ($scope.selectedItemsInTheDialog[j].Id === $scope.selectedItemsViewData[i].Id) {
                                            reoderedItems.push($scope.selectedItemsInTheDialog[j]);break;
                                        }
                                    }
                                }
                                $scope.selectedItemsInTheDialog = [];
                                Array.prototype.push.apply($scope.selectedItemsInTheDialog, reoderedItems);
                            }
                            $scope.selectedItemsViewData = [];
                        }
                    };
                    this.$scope = $scope;
                    this.canPushSelectedItemFirst = function () { return true;};
                    this.onSelectedItemsLoadedSuccess = function (data) {this.updateSelection(data.Items);};
                    this.updateSelection = function (selectedItems) {
                        selectedItems.sort(compareFunction);
                        var firstItem = selectedItems[0];
                        $scope.sfSelectedItem = firstItem;
                        $scope.sfSelectedItemId = firstItem && firstItem.Id;
                        $scope.sfSelectedItems = selectedItems;
                        $scope.sfSelectedIds = selectedItems.map(function (item) {return item.Id;});
                    };
                    this.pushSelectedItemToTheTop = function (items) {
                        if ($scope.items.length === 0 && $scope.sfSelectedItems && $scope.sfSelectedItems.length > 0) {$scope.items.push($scope.sfSelectedItems[0]);
                        }
                        else {
                            var ids = $scope.getSelectedIds();
                            if ($scope.items.length === 0 && ids && ids.length > 0) {
                                Array.prototype.push.apply($scope.items,
                                    items.filter(function (item) { return ids.indexOf(item.Id) === 0; }));
                            }
                        }
                    };
                    this.pushNotSelectedItems = function (items) {
                        var ids = $scope.getSelectedIds();
                        Array.prototype.push.apply($scope.items,
                            items.filter(function (item) { return ids.indexOf(item.Id) < 0; }));
                    };
                    this.onFilterItemSucceeded = function (items) {};
                    this.onItemSelected = function (item) {};
                    this.onPostLinkComleted = function () {};
                    this.onResetItems = function () {};
                    this.onCancel = function () {};
                    this.onDoneSelecting = function () {};
                    this.onOpen = function () {};
                    this.resetItems = function () {
                        $scope.paging.skip = 0;
                        $scope.paging.areAllItemsLoaded = false;
                        $scope.filter.isEmpty = true;
                        $scope.filter.searchString = null;
                        $scope.items = [];
                        $scope.selectedItemsInTheDialog = [];
                        $scope.selectedItemsViewData = [];
                        if (this.onResetItems) { this.onResetItems(); }
                    };
                    this.OnItemsFiltering = function (items) { return items; };
                    var compareFunction = function (item1, item2) {
                        var orderedIds = $scope.getSelectedIds();
                        var index1 = orderedIds.indexOf(item1.Id);
                        var index2 = orderedIds.indexOf(item2.Id);
                        if (index1 < index2) {return -1; }
                        if (index1 > index2) { return 1; }
                        return 0;
                    };
                    this.onError = function (error) {
                        var errorMessage = '';
                        if (error && error.data && error.data.ResponseStatus) {
                            errorMessage = error.data.ResponseStatus.Message;
                        }
                        else if (error && error.statusText) {
                            if (error.statusText === 'canceled') {  return; }
                            errorMessage = error.statusText;
                        }
                        $scope.showError = true;
                        $scope.errorMessage = errorMessage;
                    };

                    this.fetchSelectedItems = function () {
                        var ids = $scope.getSelectedIds();
                        currentSelectedIds = ids;
                        if (ids.length === 0)
                            return;
                        // get selected items providers
                        var providers = $scope.getSelectedProviders();
                        // get selected items item types
                        var itemtypes = $scope.getSelectedItemtypes();
                        var that = this;
                        return this.getSpecificItems(ids, providers, itemtypes)
                            .then(function (data) {
                                $scope.sfMissingSelectedItems = data.Items.length < ids.length;
                                that.onSelectedItemsLoadedSuccess(data);
                            }, that.onError);
                    };
                },
                templateUrl: function (elem, attrs) {
                    var assembly = attrs.sfTemplateAssembly || 'Telerik.Sitefinity.Frontend';
                    var url = attrs.sfTemplateUrl || 'client-components/selectors/common/sf-list-selector.sf-cshtml';
                    return serverContext.getEmbeddedResourceUrl(assembly, url);
                },
                link: {
                    pre: function (scope) {
                        if (!scope.sfExternalPages)
                            scope.sfExternalPages = [];
                        var kendoRenderedHandler = function (event) {
                            for (var i = 0; i < scope.kendoTabStrips.length; i++) {
                                scope.kendoTabStrips[i].activateTab('li.k-state-active');
                            }
                        };
                        scope.kendoTabStrips = [];
                        scope.$on('kendoWidgetCreated', function (event, widget) {
                            if (widget.wrapper && widget.wrapper.is('.k-tabstrip')) {
                                scope.kendoTabStrips.push(widget);
                            } else {
                                try { kendoRenderedHandler(event);
                                } catch (err) {
                                }
                            }
                        });
                        scope.$on('kendoRendered', kendoRenderedHandler);
                    },
                    post: function (scope, element, attrs, ctrl, transclude) {
                        var onFirstPageLoadedSuccess = function (data) {
                            scope.noItemsExist = !data.Items.length;
                            scope.paging.skip += data.Items.length;
                            if (scope.multiselect || ctrl.selectorType === 'LibrarySelector') {
                                Array.prototype.push.apply(scope.items, data.Items);
                            }
                            else {
                                ctrl.pushSelectedItemToTheTop(data.Items);
                                ctrl.pushNotSelectedItems(data.Items);
                            } return scope.items;
                        };
                        var onItemsFilteredSuccess = function (data) {
                            scope.paging.skip += data.Items.length;
                            if (!scope.multiselect && !scope.filter.searchString && ctrl.canPushSelectedItemFirst()) {
                                scope.items = [];
                                ctrl.pushSelectedItemToTheTop();
                                ctrl.pushNotSelectedItems(data.Items);
                            }
                            else { scope.items = ctrl.OnItemsFiltering(data.Items);
                            }
                            if (ctrl.onFilterItemSucceeded) { ctrl.onFilterItemSucceeded(scope.items);
                            }
                        };
                        var emptyGuid = '00000000-0000-0000-0000-000000000000';
                        var currentSelectedIds;
                        var updateSelectedItems = function () {
                            ctrl.removeUnselectedItems();
                            if (scope.sfChange) {
                                var oldSelectedItems = [];
                                Array.prototype.push.apply(oldSelectedItems, scope.sfSelectedItems);
                                var changeArgs = {
                                    "newSelectedItems": scope.selectedItemsInTheDialog,
                                    "oldSelectedItems": oldSelectedItems
                                };
                                scope.sfChange.call(scope.$parent, changeArgs);
                            }
                            if (scope.selectedItemsInTheDialog.length > 0) {
                                scope.sfSelectedItem = scope.selectedItemsInTheDialog[0];
                                scope.sfSelectedItemId = scope.selectedItemsInTheDialog[0].Id;
                                if (scope.sfSelectedItems) { scope.sfSelectedItems.length = 0;}
                                else { scope.sfSelectedItems = [];}
                                Array.prototype.push.apply(scope.sfSelectedItems, scope.selectedItemsInTheDialog);
                                scope.sfSelectedIds = scope.sfSelectedItems.map(function (item) {
                                    return item.Id;
                                });
                                //set selectedProviders and Itemtypes
                                if (attrs.sfSelectedProviders && attrs.sfSelectedItemtypes) {
                                    scope.sfSelectedProviders = scope.sfSelectedItems.map(function (item) {
                                        return item.ProviderName;
                                    });
                                    scope.sfSelectedItemtypes = scope.sfSelectedItems.map(function (item) {
                                        return item.SysItemType;
                                    });
                                }
                            }
                            else {
                                scope.sfSelectedItem = null;
                                scope.sfSelectedItemId = null;
                                scope.sfSelectedItems = [];
                                scope.sfSelectedIds = [];
                                scope.sfSelectedProviders = [];
                                scope.sfSelectedItemtypes = [];
                            }
                        };
                        ctrl.ensureSelectionIsUpToDate = function () {
                            $q.when(ctrl.fetchSelectedItems()).then(function () {
                                updateSelectionInTheDialog();
                                scope.collectSelectedItems();
                            });
                        };
                        var updateSelectionInTheDialog = function () {
                            if (scope.sfSelectedItems) {
                                scope.selectedItemsInTheDialog = [];
                                Array.prototype.push.apply(scope.selectedItemsInTheDialog, scope.sfSelectedItems);
                            }
                        };
                        var areArrayEquals = function (arr1, arr2) {
                            if (arr1 && arr2) {
                                var clonedArr1 = [].concat(arr1);
                                var clonedArr2 = [].concat(arr2);
                                return clonedArr1.sort().toString() === clonedArr2.sort().toString();
                            }
                            return false;
                        };
                        var isJsonArray = function (str) {
                            try {
                                var jsonObject = JSON.parse(str);
                                var isArray = jsonObject instanceof Array;
                                return isArray;
                            } catch (e) {
                                return false;
                            }
                        };
                        ctrl.beginLoadingItems = function () {
                            scope.showLoadingIndicator = true;
                            scope.sfMaxItemsLimitation.showErrorMessage = false;
                            scope.itemsPromise = ctrl.getItems(scope.paging.skip, scope.paging.take)
                                .then(onFirstPageLoadedSuccess, ctrl.onError);
                            scope.itemsPromise.finally(function () {
                                scope.showLoadingIndicator = false;
                            });
                            ctrl.ensureSelectionIsUpToDate();
                        };
                        scope.$watch('sfProvider', function (newProvider, oldProvider) {
                            if (newProvider !== oldProvider) {
                                if (ctrl.selectorType === 'NewsSelector' ||
                                    ctrl.selectorType === 'DynamicItemsSelector' ||
                                    ctrl.selectorType === 'LibrarySelector' ||
                                    ctrl.selectorType === 'ListsSelector') {
                                    scope.sfSelectedItems = null;
                                    scope.sfSelectedIds = null;
                                }
                            }
                        });
                        scope.$watchCollection('sfSelectedIds', function (newIds, oldIds) {
                            if (newIds && newIds.length > 0 && !areArrayEquals(newIds, currentSelectedIds)) {
                                ctrl.fetchSelectedItems();
                            }
                        });
                        scope.showError = false;
                        scope.sfMaxSelectedItemsCount = 100;
                        scope.sfMaxItemsLimitation = { showErrorMessage: false };
                        scope.selectedItemsViewData = [];
                        scope.items = [];
                        scope.filter = {
                            placeholder: 'Narrow by typing',
                            timeoutMs: 500,
                            search: function (keyword) {
                                scope.paging.areAllItemsLoaded = false;
                                var endlessScroll = angular.element($("[sf-endless-scroll]"))[0];
                                if (endlessScroll) {
                                    endlessScroll.scrollTop = 0;
                                }
                                scope.showLoadingIndicator = true;
                                scope.paging.skip = 0;
                                var skip = scope.paging.skip;
                                var take = scope.paging.take;
                                var languages = serverContext.getFrontendLanguages();
                                return ctrl.getItems(skip, take, keyword, languages)
                                    .then(onItemsFilteredSuccess, ctrl.onError)
                                    .finally(function () {
                                        scope.showLoadingIndicator = false;
                                    });
                            }
                        };
                        scope.paging = {
                            skip: 0,
                            take: 20,
                            areAllItemsLoaded: false,
                            getPage: function () { return ctrl.getItems(this.skip, this.take, scope.filter.searchString);},
                            pageLoaded: function (items) {
                                if (!scope.multiselect && !scope.filter.searchString) { ctrl.pushNotSelectedItems(items); }
                                else { Array.prototype.push.apply(scope.items, items);}
                            }
                        };
                        scope.itemClicked = function (index, item) {
                            if (typeof index === 'object' && !item) item = index;
                            if (ctrl.onItemSelected) {ctrl.onItemSelected(item); }
                            if (scope.itemDisabled(item)) {  return;}
                            var alreadySelected;
                            var selectedItemIndex;
                            for (var i = 0; i < scope.selectedItemsInTheDialog.length; i++) {
                                if (scope.selectedItemsInTheDialog[i].Id === item.Id) {
                                    alreadySelected = true;
                                    selectedItemIndex = i; break;
                                }
                            }
                            if (alreadySelected) {
                                scope.selectedItemsInTheDialog.splice(selectedItemIndex, 1);
                            }
                            else {
                                if (scope.multiselect) {scope.selectedItemsInTheDialog.push(item);
                                }
                                else {scope.selectedItemsInTheDialog.splice(0, 1, item);
                                }
                                if (scope.sfKeepSelectedItemsBound) {updateSelectedItems();
                                }
                            }
                            scope.sfMaxItemsLimitation.showErrorMessage = scope.getSelectedItemsCount() > scope.sfMaxSelectedItemsCount;
                        };
                        scope.doneSelecting = function () {
                            updateSelectedItems();ctrl.resetItems();
                            if (ctrl.onDoneSelecting) { ctrl.onDoneSelecting();}
                            scope.$uibModalInstance.close();
                        };
                        scope.cancel = function () {
                            ctrl.resetItems();
                            if (ctrl.onCancel) {ctrl.onCancel();}
                            scope.$uibModalInstance.close();
                        };
                        scope.open = function () {
                            if (ctrl.onOpen) {
                                ctrl.onOpen();
                            }
                            if (scope.$openModalDialog) { scope.$openModalDialog();} ctrl.beginLoadingItems();
                        };
                        scope.getDialogTemplate = function () {
                            var assembly = attrs.sfTemplateAssembly || 'Telerik.Sitefinity.Frontend';
                            var url = attrs.sfDialogTemplate || ctrl.dialogTemplateUrl;
                            return serverContext.getEmbeddedResourceUrl(assembly, url);
                        };
                        scope.getClosedDialogTemplate = function () {
                            var assembly = attrs.sfTemplateAssembly || 'Telerik.Sitefinity.Frontend';
                            var url = attrs.sfClosedDialogTemplate || ctrl.closedDialogTemplateUrl;
                            return serverContext.getEmbeddedResourceUrl(assembly, url);
                        };
                        scope.isItemSelected = function () {
                            var ids = scope.getSelectedIds().filter(function (id) {
                                return id !== emptyGuid;
                            }); return ids.length > 0;
                        };
                        scope.isItemSelectedInDialog = function (item) {
                            if (!item) return false;
                            for (var i = 0; i < scope.selectedItemsInTheDialog.length; i++) {
                                if (scope.selectedItemsInTheDialog[i].Id === item.Id) {return true;}
                            }
                        };
                        scope.getSelectedItemsCount = function () { return scope.selectedItemsInTheDialog.length; };
                        scope.getSelectedIds = function () {
                            if (scope.multiselect) {
                                if (scope.sfSelectedIds && scope.sfSelectedIds.length) {
                                    var selectedIdsArray = isJsonArray(scope.sfSelectedIds) ? JSON.parse(scope.sfSelectedIds) : scope.sfSelectedIds;
                                    return selectedIdsArray.filter(function (id) {
                                        return id;
                                    });
                                }
                                else if (scope.sfSelectedItems && scope.sfSelectedItems.length > 0) {
                                    return scope.sfSelectedItems.map(function (item) {  return item.Id;
                                    }).filter(function (id) {return id;
                                    });
                                }
                            }
                            else {
                                var id = (scope.sfSelectedItem && scope.sfSelectedItem.Id) || scope.sfSelectedItemId;
                                if (id && id !== emptyGuid) { return [id]; }
                            }
                            return [];
                        };
                        //custom method to get providers
                        scope.getSelectedProviders = function () {
                            if (scope.multiselect) {
                                if (scope.sfSelectedProviders && scope.sfSelectedProviders.length) {
                                    var selectedProvidersArray = isJsonArray(scope.sfSelectedProviders) ? JSON.parse(scope.sfSelectedProviders) : scope.sfSelectedProviders;

                                    return selectedProvidersArray.filter(function (provider) {
                                        return provider;
                                    });
                                }
                            }
                            return [];
                        };
                        // custom method to get itemTypes
                        scope.getSelectedItemtypes = function () {
                            if (scope.multiselect) {
                                if (scope.sfSelectedItemtypes && scope.sfSelectedItemtypes.length) {
                                    var selectedItemtypesArray = isJsonArray(scope.sfSelectedItemtypes) ? JSON.parse(scope.sfSelectedItemtypes) : scope.sfSelectedItemtypes;
                                    return selectedItemtypesArray.filter(function (itemtype) {
                                        return itemtype;
                                    });
                                }
                            }
                            return [];
                        };

                        attrs.$observe('sfMultiselect', function () {
                            scope.multiselect = (attrs.sfMultiselect && attrs.sfMultiselect.toLowerCase() === 'true') ? true : false;
                            if (!scope.multiselect && scope.sfSelectedItems && scope.sfSelectedItems.length > 1) {
                                ctrl.updateSelection([scope.sfSelectedItems[0]]);
                            }
                        });
                        scope.multiselect = (attrs.sfMultiselect && attrs.sfMultiselect.toLowerCase() === 'true') ? true : false;
                        var selectedIds = scope.getSelectedIds();
                        if (!scope.sfSelectedItemId && selectedIds && selectedIds.length)
                            scope.sfSelectedItemId = selectedIds[0];
                        scope.selectButtonText = attrs.sfSelectButtonText;
                        scope.changeButtonText = attrs.sfChangeButtonText;
                        scope.selectedItemsInTheDialog = [];
                        scope.showLoadingIndicator = true;
                        scope.bindIdentifierField = function (item) {
                            return ctrl.bindIdentifierField(item);
                        };
                        scope.getChildren = function (parentId) {return ctrl.getChildren(parentId, scope.filter.searchString);};
                        scope.getPredecessors = function (itemId) {return ctrl.getPredecessors(itemId);};
                        scope.itemDisabled = function (item) {
                            if (ctrl.itemDisabled) {
                                return ctrl.itemDisabled(item);
                            }
                            return false;
                        };
                        scope.collectSelectedItems = function () {
                            if (scope.multiselect) {
                                scope.selectedItemsViewData = [];
                                Array.prototype.push.apply(scope.selectedItemsViewData, scope.selectedItemsInTheDialog);
                            }
                        };
                        scope.removeUnselectedItems = ctrl.removeUnselectedItems;
                        ctrl.fetchSelectedItems();
                        transclude(scope, function (clone) {
                            var hasContent;
                            for (var i = 0; i < clone.length; i++) {
                                var currentHtml = clone[i] && clone[i].outerHTML;
                                //check if the content is not empty string or white space only
                                hasContent = currentHtml && !/^\s*$/.test(currentHtml);

                                if (hasContent) {
                                    element.find('#selectedItemsPlaceholder').empty().append(clone); break;
                                }
                            }
                        });
                        ////NOTE: Emit indication when initial setup is completed so child directives can be notified.
                        if (ctrl.onPostLinkComleted) {ctrl.onPostLinkComleted();}
                    }
                }
            };
        }]);
})(jQuery);

Part 3 Link

来源:https://stackoverflow.com/questions/65811532/dynamic-items-selector-from-multiple-content-types-sitefinity-part-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!