3

我在自定义指令中遇到了隔离范围的问题。ngroute后指令无法正确加载

我已经构建了一个自定义指令。它在我没有使用父作用域设置指令中的scope-attribute时起作用。

它是什么?它呈现了一个原生的JavaScript控制。每次加载该网站时,都会初始化该控件,并将该控件的数据插入到父范围中。

为什么我需要一个独立的范围?因为我想在页面上放两次指令。对于我想要放入不同变量的数据。

有什么问题?每次我加载页面时都可以正常工作。然后我使用ng-route切换到另一个站点。在那里我使用$ 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 = {})); 

Routeprovider:

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

从detailspage我将回到通过使用NG-点击资源简介。在被称为我使用的函数中:

$location.path("/"); 

如果这件事情按钮在另一个指令。

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

angular.module('presenceSummary', []) 
    .controller('presenceSummary', function ($scope, $location, hrDbService, hrUserService, hrUiControlService) { 

     ... 
    }); 
+1

我想你需要向我们展示更多的指令,即控制器和链接功能(如果有的话)。 – 2014-09-30 15:24:53

+0

用更多代码更新帖子 – 2014-09-30 15:34:38

+0

请添加您的路由配置和控制器,即父范围。 – 2014-09-30 15:46:28

回答