AngularJS: 在自定义 contenteditable 指令中限制用户输入
AngularJS: Limiting the user input in custom contenteditable directive
在这里使用 angular js:
我有一个 HTML table 并为每行数据使用 contenteditable,例如:
<td contenteditable="true"
ng-repeat="column in targetTable.columns"
ng-model="r[column.id]"
ng-blur="!r.id? addNewRow(r[column.id], r): undefined">
</td>
我也有我的指令:
directive('contenteditable', ['$sce', function($sce) {
return {
link: function(scope, element, attrs, ngModel) {
var regex = /^[\w/\s_~`!@#$%^&*()_+-={}[\]|\:;/>\\'\"]$/;
element.on('keypress', (e) => {
char = String.fromCharCode(event.which);
if (!regexpInt.test(char)) {
event.preventDefault();
};
});
ngModel.$parsers.push(function (value) {
if (value.length > 5) {
value = value.substr(0, 5);
ngModel.$setViewValue(value);
ngModel.$render();
}
return value;
});
}
}
});
我只是发布指令中的相关代码。整个工作代码可以在下面的代码笔中看到。
在上面的指令中,我使用正则表达式允许用户键入与 spl 字符一起定义的字符集中的任何内容,space 工作正常。
我也在使用 ngModel.$parsers 试图将用户输入限制在特定字符限制(在本例中为 5 个),因此如果用户输入超过 5 个,我希望输入停止接受更多字符。在这里应用限制的原因是我将创建动态列,并根据列名应用每个列的最大长度,因此我无法在 html 中应用限制。
现在问题出在最大长度代码上,它的工作方式与预期的不完全一样。
如果您看到演示并开始输入超过 5 个字符,一旦您输入第 6 个字符,光标就会到达第一个字符,并且如果您输入更多字符,则会继续覆盖现有字符。
因为我想在输入中允许 space,如果你输入一些字符并添加 space 它会尝试添加 & n b s p;到输入。
我想从 maxlength 代码中得到的是,它应该接受 spaces,并且一旦您尝试输入超过 5 个字符,它就会阻止用户输入并自行停止。类似于正则表达式代码。
这是我下面的代码笔演示:
https://codepen.io/anon/pen/WKZJWw
有任何解决此问题的意见吗?
为了允许空格,我会在设置模型值之前将其删除。所以在 read
函数中:
html = html.replace(/ /g, ' ')
ngModel.$setViewValue(html);
要限制字符,为什么不在按键功能中停止输入
element.on('keypress', (e) => {
char = String.fromCharCode(event.which)
if (!regex.test(char)) {
event.preventDefault();
}
if (ngModel.$viewValue && ngModel.$viewValue.length >= maxLength) {
event.preventDefault();
}
});
其中 maxLength
是 5。但是在粘贴输入或用户输入速度非常快的情况下,您仍然需要重新渲染。要解决此问题,请在每次渲染后将插入符的位置设置为输入的末尾。
ngModel.$render = function() {
element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
var caretPosition = (ngModel.$viewValue && ngModel.$viewValue.length) || 0;
setCaretPosition(caretPosition);
};
感谢 Tim Down 关于如何设置插入符号位置的 answer。在这种情况下,它被定义为
var setCaretPosition = function(position) {
if (!element[0].childNodes[0]) {
return;
}
var range = document.createRange();
var selection = window.getSelection();
range.setStart(element[0].childNodes[0], position);
range.collapse(true);
selection.removeAllRanges();
selection.addRange(range);
};
查看更新codepen
在这里使用 angular js:
我有一个 HTML table 并为每行数据使用 contenteditable,例如:
<td contenteditable="true"
ng-repeat="column in targetTable.columns"
ng-model="r[column.id]"
ng-blur="!r.id? addNewRow(r[column.id], r): undefined">
</td>
我也有我的指令:
directive('contenteditable', ['$sce', function($sce) {
return {
link: function(scope, element, attrs, ngModel) {
var regex = /^[\w/\s_~`!@#$%^&*()_+-={}[\]|\:;/>\\'\"]$/;
element.on('keypress', (e) => {
char = String.fromCharCode(event.which);
if (!regexpInt.test(char)) {
event.preventDefault();
};
});
ngModel.$parsers.push(function (value) {
if (value.length > 5) {
value = value.substr(0, 5);
ngModel.$setViewValue(value);
ngModel.$render();
}
return value;
});
}
}
});
我只是发布指令中的相关代码。整个工作代码可以在下面的代码笔中看到。
在上面的指令中,我使用正则表达式允许用户键入与 spl 字符一起定义的字符集中的任何内容,space 工作正常。
我也在使用 ngModel.$parsers 试图将用户输入限制在特定字符限制(在本例中为 5 个),因此如果用户输入超过 5 个,我希望输入停止接受更多字符。在这里应用限制的原因是我将创建动态列,并根据列名应用每个列的最大长度,因此我无法在 html 中应用限制。
现在问题出在最大长度代码上,它的工作方式与预期的不完全一样。
如果您看到演示并开始输入超过 5 个字符,一旦您输入第 6 个字符,光标就会到达第一个字符,并且如果您输入更多字符,则会继续覆盖现有字符。
因为我想在输入中允许 space,如果你输入一些字符并添加 space 它会尝试添加 & n b s p;到输入。
我想从 maxlength 代码中得到的是,它应该接受 spaces,并且一旦您尝试输入超过 5 个字符,它就会阻止用户输入并自行停止。类似于正则表达式代码。
这是我下面的代码笔演示: https://codepen.io/anon/pen/WKZJWw
有任何解决此问题的意见吗?
为了允许空格,我会在设置模型值之前将其删除。所以在 read
函数中:
html = html.replace(/ /g, ' ')
ngModel.$setViewValue(html);
要限制字符,为什么不在按键功能中停止输入
element.on('keypress', (e) => {
char = String.fromCharCode(event.which)
if (!regex.test(char)) {
event.preventDefault();
}
if (ngModel.$viewValue && ngModel.$viewValue.length >= maxLength) {
event.preventDefault();
}
});
其中 maxLength
是 5。但是在粘贴输入或用户输入速度非常快的情况下,您仍然需要重新渲染。要解决此问题,请在每次渲染后将插入符的位置设置为输入的末尾。
ngModel.$render = function() {
element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
var caretPosition = (ngModel.$viewValue && ngModel.$viewValue.length) || 0;
setCaretPosition(caretPosition);
};
感谢 Tim Down 关于如何设置插入符号位置的 answer。在这种情况下,它被定义为
var setCaretPosition = function(position) {
if (!element[0].childNodes[0]) {
return;
}
var range = document.createRange();
var selection = window.getSelection();
range.setStart(element[0].childNodes[0], position);
range.collapse(true);
selection.removeAllRanges();
selection.addRange(range);
};
查看更新codepen