[英]directive doesn't load correct after 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' });
}]);
從詳細信息頁面,我將使用ng-click返回摘要頁面。 在我使用的dunction中使用:
$location.path("/");
如果這很重要按鈕是另一個指令。
people-picker-directive的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
謝謝你的幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.