指令在 ngroute 后加载不正确



我在自定义指令中遇到了一个孤立作用域的问题。

我已经建立了一个自定义指令。当我没有使用父作用域在指令中设置作用域属性时,它就起作用了。

是什么干的?它呈现了一个本机JavaScript控件。每次加载站点时,都会初始化控件,并将控件的数据插入父作用域。

为什么我需要一个独立的示波器?因为我想在一页纸上写两次指令。对于数据,我想放入不同的变量中。

怎么了?每次我加载页面时,一切都很好。然后我使用ng路由切换到另一个站点。在那里,我使用$Location.Path将路线重置为第一页。我的控件初始化了,但似乎没有呈现它的内容。例如,没有keydown工作。

这里有一些代码:指令:

 <people-picker instancename="peoplePicker" labeltext="Mitarbeiter" singleusermode="true" useonlyallowedusers="true"
                                                   allowedusers="AllowedUsers" selectedusers="selectedUsers" instance="instance"
                                                   callbackwhenuserchanged="dataChanged(currentSelectedUsers)">
                                    </people-picker>

指令:

.directive('peoplePicker', function () {
    return {
        restrict: 'E',
        templateUrl: '../DirectiveTemplates/PeoplePicker.html',
        scope: {
            instancename: '@',
            labeltext: '@',
            singleusermode: '@',
            selectedusers: '=',
            useonlyallowedusers: '@',
            allowedusers: '=',
            callbackwhenuserchanged: '&',
            instance: '='
        },
        controller: function ($scope, utilities, spContextProvider) {
            $scope.singleusermode = $scope.singleusermode !== undefined && $scope.singleusermode.toUpperCase() === 'TRUE';
            $scope.useonlyallowedusers = $scope.useonlyallowedusers !== undefined && $scope.useonlyallowedusers.toUpperCase() === 'TRUE';
            $scope.peoplePicker = {};
            $scope.idSpanAdministrators = 'spanAdministrators' + $scope.instancename;
            $scope.idInputAdministrators = 'inputAdministrators' + $scope.instancename;
            $scope.idDivAdministratorsSearch = 'divAdministratorsSearch' + $scope.instancename;
            $scope.idHdnAdministrators = 'hdnAdministrators' + $scope.instancename;
           ...
            $scope.initializePeoplePicker = function () {
                var context = spContextProvider.GetSharePointContext();
                $scope.peoplePicker = new CAMControl.PeoplePicker(
                $scope.instancename,
                context,
                $('#' + $scope.idSpanAdministrators),
                $('#' + $scope.idInputAdministrators),
                $('#' + $scope.idDivAdministratorsSearch),
                $('#' + $scope.idHdnAdministrators));
                ...
                $scope.peoplePicker.Initialize();
                $scope.addSelectedUsers($scope.selectedusers);
            }
            $scope.addSelectedUsers = function (selectedUsers) {
                if (selectedUsers !== null) {
                    angular.forEach(selectedUsers, function (item) {
                        $scope.peoplePicker.RecipientSelected(item.Login, item.Name, item.Email);
                    });
                }
            }
            $scope.$watchCollection($scope.selectedusers, function () {
                $scope.addSelectedUsers($scope.selectedusers);
            }, true);
            spContextProvider.CallSharePointWithFunction($scope.initializePeoplePicker);
        }

这个peoplepicker使用一个控件,该控件可处理4个html元素。必须初始化遗嘱。

对于完整的代码,我将发布控件(由于长度限制,删除了一些行)。

var CAMControl;
(function (CAMControl) {
    var PeoplePicker = (function () {
        // Constructor
        function PeoplePicker(InstanceName, SharePointContext, PeoplePickerControl, PeoplePickerEdit, PeoplePickerDisplay, PeoplePickerData) {
            //public properties
            this.SharePointContext = SharePointContext;
            this.PeoplePickerControl = PeoplePickerControl;
            this.PeoplePickerEdit = PeoplePickerEdit;
            this.PeoplePickerDisplay = PeoplePickerDisplay;
            this.PeoplePickerData = PeoplePickerData;
            this.InstanceName = InstanceName;
            // optionally show more/less entries in the people picker dropdown, 5 is the default
          ...
            window.document[this.InstanceName] = this;
        }
        // Property wrapped in function to allow access from event handler
        PeoplePicker.prototype.GetPrincipalType = function () {
            return this.PrincipalType;
        }
        ...
        // HTML encoder
        PeoplePicker.prototype.HtmlEncode = function (html) {
            return document.createElement('a').appendChild(document.createTextNode(html)).parentNode.innerHTML;
        }
        // HTML decoder
        PeoplePicker.prototype.HtmlDecode = function (html) {
            var a = document.createElement('a');
            a.innerHTML = html;
            return a.textContent;
        }
      ...
        PeoplePicker.prototype.LoadScript = function (url, callback) {
            var head = document.getElementsByTagName("head")[0];
            var script = document.createElement("script");
            script.src = url;
            // Attach handlers for all browsers
            var done = false;
            script.onload = script.onreadystatechange = function () {
                if (!done && (!this.readyState
                            || this.readyState == "loaded"
                            || this.readyState == "complete")) {
                    done = true;
                    // Continue your code
                    callback();
                    // Handle memory leak in IE
                    script.onload = script.onreadystatechange = null;
                    head.removeChild(script);
                }
            };
            head.appendChild(script);
        }
       ...
        // Generates the html for a resolved user
        PeoplePicker.prototype.ConstructResolvedUserSpan = function (login, name) {
            var login = login.replace(/\/g, '\\');
            resultDisplay = 'Remove person or group {0}';
            if (typeof deleteUser != 'undefined') {
                resultDisplay = deleteUser;
            }
            resultDisplay = this.Format(resultDisplay, name);
            var userDisplaySpanTemplate = '<span class="peoplepicker-userSpan"><span class="entity-resolved">{0}</span><a title="{3}" class="peoplepicker-delImage" onclick="{1}.DeleteProcessedUser({2}); return false;" href="#">x</a></span>';
            return this.Format(userDisplaySpanTemplate, name, this.InstanceName, "'" + login + "'", resultDisplay);
        }
        // Create a html representation of the resolved user array
        PeoplePicker.prototype.ResolvedUsersToHtml = function () {
            var userHtml = '';
            for (var i = 0; i < this._ResolvedUsers.length; i++) {
                userHtml += this.ConstructResolvedUserSpan(this._ResolvedUsers[i].Login, this._ResolvedUsers[i].Name);
            }
            return userHtml;
        }
        // Returns a resolved user object
        PeoplePicker.prototype.ResolvedUser = function (login, name, email) {
            var user = new Object();
            user.Login = login;
            user.Name = name;
            user.Email = email;
            return user;
        }
        // Add resolved user to array and updates the hidden field control with a JSON string
        PeoplePicker.prototype.PushResolvedUser = function (resolvedUser) {
            if (this.AllowDuplicates) {
                this._ResolvedUsers.push(resolvedUser);
            } else {
                var duplicate = false;
                for (var i = 0; i < this._ResolvedUsers.length; i++) {
                    if (this._ResolvedUsers[i].Login == resolvedUser.Login) {
                        duplicate = true;
                    }
                }
                if (!duplicate) {
                    this._ResolvedUsers.push(resolvedUser);
                }
            }
            this.PeoplePickerData.val(JSON.stringify(this._ResolvedUsers));
        }

        // Function called then the clientPeoplePickerSearchUser succeeded
        PeoplePicker.prototype.QuerySuccess = function (queryNumber, searchResult) {
            var results = this.SharePointContext.parseObjectFromJsonString(searchResult.get_value());
            var txtResults = '';
            var baseDisplayTemplate = '<div class='ms-bgHoverable' style='width: 400px; padding: 4px;' onclick='javascript:{0}.RecipientSelected("{1}", "{2}", "{3}")'>{4}';
            var displayTemplate = '';
            if (this.ShowLoginName && this.ShowTitle) {
                displayTemplate = baseDisplayTemplate + ' ({5})<br/>{6}</div>';
            } else if (this.ShowLoginName) {
                displayTemplate = baseDisplayTemplate + ' ({5})</div>';
            } else if (this.ShowTitle) {
                displayTemplate = baseDisplayTemplate + ' ({6})</div>';
            } else {
                displayTemplate = baseDisplayTemplate + '</div>';
            }
            if (results) {
                ...
                if (results.length > 0) {
                    // if this function is not the callback from the last issued query then just ignore it. This is needed to ensure a matching between
                    // what the user entered and what is shown in the query feedback window
                    if (queryNumber < this._lastQueryID) {
                        return;
                    }
                    displayCount = results.length;
                    if (displayCount > this.MaxEntriesShown) {
                        displayCount = this.MaxEntriesShown;
                    }
                    for (var i = 0; i < displayCount; i++) {
                        var item = results[i];
                        var oldLoginName = item['Key'];
                        var loginName = oldLoginName.replace(/\/g, '\\');
                        var displayLoginName = oldLoginName.split('|')[1].replace(/\/g, '\');
                        var displayName = item['DisplayText'];
                        var title = item['EntityData']['Title'];
                        var email = item['EntityData']['Email'];
                        txtResults += this.Format(displayTemplate, this.InstanceName, loginName, this.HtmlEncode(displayName), email, displayName, displayLoginName, title);
                    }
                    var resultDisplay = '';
                    txtResults += '<div class='ms-emphasisBorder' style='width: 400px; padding: 4px; border-left: none; border-bottom: none; border-right: none; cursor: default;'>';
                    if (results.length == 1) {
                        resultDisplay = 'Showing {0} result';
                        if (typeof resultsSingle != 'undefined') {
                            resultDisplay = resultsSingle;
                        }
                        txtResults += this.Format(resultDisplay, results.length) + '</div>';
                    } else if (displayCount != results.length) {
                        resultDisplay = "Showing {0} of {1} results. <B>Please refine further<B/>";
                        if (typeof resultsTooMany != 'undefined') {
                            resultDisplay = resultsTooMany;
                        }
                        txtResults += this.Format(resultDisplay, displayCount, results.length) + '</div>';
                    } else {
                        resultDisplay = "Showing {0} results";
                        if (typeof resultsMany != 'undefined') {
                            resultDisplay = resultsMany;
                        }
                        txtResults += this.Format(resultDisplay, results.length) + '</div>';
                    }
                    this.PeoplePickerDisplay.html(txtResults);
                    //display the suggestion box
                    this.ShowSelectionBox();
                }
                else {
                    var searchbusy = '<div class='ms-emphasisBorder' style='width: 400px; padding: 4px; border-left: none; border-bottom: none; border-right: none; cursor: default;'>No results found</div>';
                    this.PeoplePickerDisplay.html(searchbusy);
                    //display the suggestion box
                    this.ShowSelectionBox();
                }
            }
            else {
                //hide the suggestion box since results are null
                this.HideSelectionBox();
            }
        }
        // Initialize
        PeoplePicker.prototype.Initialize = function () {
            var scriptUrl = "";
            var scriptRevision = "";
            $('script').each(function (i, el) {
                if (el.src.toLowerCase().indexOf('peoplepickercontrol.js') > -1) {
                    scriptUrl = el.src;
                    scriptRevision = scriptUrl.substring(scriptUrl.indexOf('.js') + 3);
                    scriptUrl = scriptUrl.substring(0, scriptUrl.indexOf('.js'));
                }
            })
            // Load translation files
            var resourcesFile = scriptUrl + "_resources." + this.Language.substring(0, 2).toLowerCase() + ".js";
            if (scriptRevision.length > 0) {
                resourcesFile += scriptRevision;
            }
            this.LoadScript(resourcesFile, function () {
            });

            // is there data in the hidden control...if so show it
            if (this.PeoplePickerData.val() !== undefined && this.PeoplePickerData.val().length > 0) {
                // Deserialize JSON string into list of resolved users
                this._ResolvedUsers = JSON.parse(this.PeoplePickerData.val());
                // update the display of resolved users
                this.PeoplePickerControl.html(this.ResolvedUsersToHtml());
            }
            var parent = this;
            this.PeoplePickerEdit.keydown(function (event) {
                var keynum = event.which;
                //backspace
                if (keynum == 8) {
                    //hide the suggestion box when backspace has been pressed
                    parent.HideSelectionBox();
                    // do we have text entered
                    var unvalidatedText = parent.PeoplePickerEdit.val();
                    if (unvalidatedText.length > 0) {
                        // delete the last entered character...meaning do nothing as this delete will happen as part of the keypress
                    }
                    else {
                        // are there resolved users, if not there's nothing to delete
                        if (parent._ResolvedUsers.length > 0) {
                            // remove the last added user
                            parent.PopResolvedUser();
                            // update the display
                            parent.PeoplePickerControl.html(parent.ResolvedUsersToHtml());
                            // focus back to input control
                            parent.PeoplePickerEdit.focus();
                            // Eat the backspace key
                            return false;
                        }
                    }
                }
                    // An ascii character or a space has been pressed
                else if (keynum >= 48 && keynum <= 90 || keynum == 32) {
                    // get the text entered before the keypress processing (so the last entered key is missing here)    
                    var txt = parent.PeoplePickerEdit.val();
                    // keynum is not taking in account shift key and always results inthe uppercase value
                    if (event.shiftKey == false && keynum >= 65 && keynum <= 90) {
                        keynum += 32;
                    }
                    // Append the last entered character: since we're handling a keydown event this character has not yet been added hence the returned value misses the last character
                    txt += String.fromCharCode(keynum);
                    // we should have at least 1 character
                    if (txt.length > 0) {
                        var searchText = txt;
                        //ensure that MinimalCharactersBeforeSearching >= 1
                        if (parent.GetMinimalCharactersBeforeSearching() < 1) {
                            parent.SetMinimalCharactersBeforeSearching(1);
                        }
                        // only perform a query when we at least have two chars and we do not have a query running already
                        if (searchText.length >= parent.GetMinimalCharactersBeforeSearching()) {
                            resultDisplay = 'Searching...';
                            if (typeof resultsSearching != 'undefined') {
                                resultDisplay = resultsSearching;
                            }
                            var searchbusy = parent.Format('<div class='ms-emphasisBorder' style='width: 400px; padding: 4px; border-left: none; border-bottom: none; border-right: none; cursor: default;'>{0}</div>', resultDisplay);
                            parent.PeoplePickerDisplay.html(searchbusy);
                            //display the suggestion box
                            parent.ShowSelectionBox();
                            var query = new SP.UI.ApplicationPages.ClientPeoplePickerQueryParameters();
                            query.set_allowMultipleEntities(false);
                            query.set_maximumEntitySuggestions(2000);
                            query.set_principalType(parent.GetPrincipalType());
                            query.set_principalSource(15);
                            query.set_queryString(searchText);
                            var searchResult = SP.UI.ApplicationPages.ClientPeoplePickerWebServiceInterface.clientPeoplePickerSearchUser(parent.SharePointContext, query);
                            // update the global queryID variable so that we can correlate incoming delegate calls later on
                            parent._queryID = parent._queryID + 1;
                            var queryIDToPass = parent._queryID;
                            parent._lastQueryID = queryIDToPass;
                            // make the SharePoint request
                            parent.SharePointContext.executeQueryAsync(Function.createDelegate(this, function () { parent.QuerySuccess(queryIDToPass, searchResult); }),
                                                                       Function.createDelegate(this, function (a, arguments) { parent.QueryFailure(queryIDToPass, arguments); }));
                        }
                    }
                }
                    //tab or escape
                else if (keynum == 9 || keynum == 27) {
                    //hide the suggestion box
                    parent.HideSelectionBox();
                }
            });
        }
        return PeoplePicker;
    })();
    CAMControl.PeoplePicker = PeoplePicker;
})(CAMControl || (CAMControl = {}));

路由提供商:

.config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/summary', {
        templateUrl: 'PresenceSummary.html'
    })
        .when('/details/:workingDay', {
            templateUrl: 'PresenceDetails.html'
        })
        .otherwise({ redirectTo: '/summary' });
}]);

从详细信息页面,我将通过单击ng返回到摘要页面。在被称为我使用:

$location.path("/");

如果这很重要,按钮在另一个指令中。

人员选择器指令的parentcontroller看起来是这样的:

angular.module('presenceSummary', [])
    .controller('presenceSummary', function ($scope, $location, hrDbService, hrUserService, hrUiControlService) {
        ...
    });
我找到了答案。该指令在dom准备就绪之前呈现。我的控制不可用。

我设置了一个超时。这篇文章给了我这样的提示:http://blog.brunoscopelliti.com/run-a-directive-after-the-dom-has-finished-rendering

谢谢你的帮助!

最新更新