- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的自定义指令中的隔离范围有问题。
我已经构建了一个自定义指令。当我没有使用父作用域在指令中设置作用域属性时,它起作用了。
它做了什么?它呈现了一个原生的 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);
}
此人员选择器使用一个可在 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-click 从详细信息页面返回到摘要页面。在称为 I 的函数中使用:
$location.path("/");
如果这很重要,按钮在另一个指令中。
people-picker-directive 的父 Controller 看起来是这样的:
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
感谢您的帮助!
关于javascript - ngroute 后指令加载不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26123493/
我正在尝试在现有指令的基础上构建一个新指令,但我在我的过程中停止了。加载页面时,我面临以下错误: Multiple directives [directive#1, directive#2] aski
我是 angularjs 世界的新手,我只需要在数字类型的输入中输入从 1 到 10 的数字。不使用 HTML5 的 min 和 max 属性 我在 Jquery 中找到了一个示例,能否帮我将其转换为
我想使用 ionic与 Material 设计。我被困在使用带有自定义 CSS 的 ionic 指令和 angular-material 之间。 我读过使用 ionic 指令我们得到了很多高效的特性,
我创建了以下代码: var node = document.getElementById('TreeList'); var keys = Object.keys(model[0]); var trac
在 AngularJs 中没有提供 ng-enabled 指令。是否有任何适当的理由不在框架中提供该指令,因为当您可以使用 ng- 时,我们同时拥有 ng-show 和 ng-hide隐藏来实现我们的
我最近制作的程序有问题。基本上,它是 John Conway 人生游戏的简单版本,但它运行不正常。问题出在读取单元格及其邻居的状态并决定该单元格的 future 状态的代码中。这是代码的一部分(有点长
Dockerfile reference关于 FROM 指令的内容如下: FROM can appear multiple times within a single Dockerfile in or
我一直在尝试理解指令中孤立作用域和继承作用域之间的区别。这是我准备让自己理解的一个例子: HTML Inside isolated scope directive: {{m
知道如何从指令内部访问属性值吗? angular.module('portal.directives', []) .directive('languageFlag', ['$r
我正在通过将 c 程序与其等价的汇编程序进行比较来学习汇编。 这是代码。 .file "ex3.c" .section .rodata .LC0: .string "I am %d
我正在尝试写一个 Jenkinsfile并行执行一系列步骤。目标是拥有两个 agents (又名。 nodes )。一个应该进行 Windows 构建,另一个应该进行 linux 构建。但是,我不希望
我想知道为什么指令 FYL2XP1在 x86 架构上精确计算数学公式 y · log2(x + 1)。 这个公式有什么特别之处? 最佳答案 y操作数通常是编译时常量,暂时忘记 x + 1 . 自 lo
这个问题已经有答案了: Parameterize an SQL IN clause (41 个回答) 已关闭 8 年前。 第一个声明: Select GroupMember FROM Group 结果
我从 this question fork 并编辑了一个 plunker 我想做的是在数据加载后更新/填充 SELECT 元素(组合框),但有些事情不对劲。我检索数据,它位于 SELECT 元素的范围
我想创建一个简单的 markdown 指令,它接受元素中的一些内容,解析它并用 html 替换它。 所以这样: #Heading 或这个(其中 $scope.heading = '#Heading';
我对 Ansible 还很陌生,对于我对 local_action 指令的理解有一个简单的问题。 这是否意味着该命令完全在本地执行?假设你有这样的东西: local_action: command w
我有以下 HTML: ... ... 以及以下指令: myApp.directive('specialInput', ['$timeout', function($timeout)
如何在 .htaccess 中创建 Apache 指令强制文件 .mp4和 .pdf去下载?目前它们出现在浏览器窗口中。相反,我希望出现一个下载文件对话框。 最佳答案 将以下内容添加到 .htacce
我的问题是关于 C 中的 fork() 指令。我有以下程序: void main(){ int result, status; result = fork(); if(result=
我想要一个类似于 ng-model 的属性指令。我只想另外将一个输入字段值绑定(bind)到一个范围变量(只是在一个方向输入字段 ->范围变量)。所以我刚刚尝试了这个指令,但无论如何我都无法调用该指令
我是一名优秀的程序员,十分优秀!