Textarea ng-bind,其中 value 有前缀和后缀
Posted
技术标签:
【中文标题】Textarea ng-bind,其中 value 有前缀和后缀【英文标题】:Textarea ng-bind, where value has a prefix and suffix 【发布时间】:2016-10-26 19:59:36 【问题描述】:在我看来,我正在尝试完成一些应该相当简单的事情。当使用诸如文本输入之类的东西时也是如此。我正在尝试在 textarea 上创建模型绑定,当用户键入时,其中的值显示为带有前缀和后缀。前缀和后缀是引号:
“My awesome quote”
问题是,我目前正在使用 ng-model,我当然不能使用它。我正在考虑绑定到一个变量,保留没有前缀和后缀的值,然后观察该变量。当具有原始值的变量发生变化时,我会将带有前缀和后缀的值写入范围内的另一个变量。当用户键入时,该变量将显示在文本区域中。唯一的问题是,与输入字段不同,textarea 没有 value 属性。
这可能吗?
编辑
如果我在哪里使用输入文本字段来实现这一点,我将创建一个名为 A 的变量,以保存在用户键入时更改的原始值。 当 A 更改时,我将获取原始值,在其周围加上引号并将新值存储在另一个变量中,也在范围内。这个新变量称为 B
然后输入字段将在 A 变量上使用 ng-bind,并使用输入字段值属性显示 B 变量的内容。如下所示:
<input type="text" ng-bind="A" value="B">
我现在没有时间制作小提琴,但我会在本周晚些时候尝试制作。上面的描述都是理论上的,因为我还没有测试过。
【问题讨论】:
澄清一下,您希望在textarea中添加前缀和后缀而不影响模型值? 是的,完全正确。如果可以的话,我的意思是。如果需要,在发布值之前删除引号没有问题。我现在有办法做到这一点,但问题是光标处于“错误”位置。 “我的报价”(光标在这里) 如果我可以在 textarea 周围加上引号,那就太好了,但是 textarea 没有动态宽度。我当然可以写一些 javascript 来调整你输入的宽度。 使用可编辑的段落标签怎么样?使用内容可编辑。然后用引号括起来 您说使用输入而不是文本区域来实现这种效果非常简单。你能在 jsfiddle 上创建一个例子吗? 【参考方案1】:您的需求非常有趣,可以分为两个主要功能:
1。在不影响模型值的情况下为视图值添加前缀和后缀
这是使用NgModelController 实现的。我在ngModelController.$viewValue
上创建了一个观察者,每当它发生变化时,如果它不包含前缀或后缀,我就会添加这些值。
2。不允许用户干扰前缀或后缀
这有点棘手,但我发现 a clever way on SO 可以获取和设置输入或文本区域元素的插入符号位置。
这是一个工作示例:
angular
.module('myApp', [])
.directive('beautifyText', function()
return
link: function(scope, iElement, iAttrs, ngModelController)
// Adds the prefix and suffix
(function()
var prefix = iAttrs.beautifyTextWithPrefix;
var suffix = iAttrs.beautifyTextWithSuffix;
ngModelController.$parsers.push(function(value)
if (angular.isString(value))
return value.replace(new RegExp('^' + prefix), '').replace(new RegExp(suffix + '$'), '');
return '';
);
scope.$watch(function()
return ngModelController.$viewValue;
, function(newValue)
if (angular.isString(newValue) && newValue.length > 0)
if (angular.isString(ngModelController.$modelValue) && ngModelController.$modelValue.length === 0 && newValue.length === 1)
ngModelController.$viewValue = '';
ngModelController.$render();
return;
if (!isBeautifiedWithPrefix(newValue))
ngModelController.$viewValue = prefix + newValue;
if (!isBeautifiedWithSuffix(newValue))
ngModelController.$viewValue = newValue + suffix;
ngModelController.$render();
else
ngModelController.$viewValue = '';
ngModelController.$render();
);
function isBeautifiedWithPrefix(value)
return value.match(new RegExp('^' + prefix)) !== null;
function isBeautifiedWithSuffix(value)
return value.match(new RegExp(suffix + '$')) !== null;
)();
// Changes the caret position
(function()
var element = iElement[0];
// https://***.com/questions/7745867/how-do-you-get-the-cursor-position-in-a-textarea#answer-7745998
function getCursorPos()
if ("selectionStart" in element && document.activeElement == element)
return
start: element.selectionStart,
end: element.selectionEnd
;
else if (element.createTextRange)
var sel = document.selection.createRange();
if (sel.parentElement() === element)
var rng = element.createTextRange();
rng.moveToBookmark(sel.getBookmark());
for (var len = 0; rng.compareEndPoints("EndToStart", rng) > 0; rng.moveEnd("character", -1))
len++;
rng.setEndPoint("StartToStart", element.createTextRange());
for (var pos =
start: 0,
end: len
; rng.compareEndPoints("EndToStart", rng) > 0; rng.moveEnd("character", -1))
pos.start++;
pos.end++;
return pos;
return -1;
// https://***.com/questions/7745867/how-do-you-get-the-cursor-position-in-a-textarea#answer-7745998
function setCursorPos(start, end)
if (arguments.length < 2)
end = start;
if ("selectionStart" in element)
element.selectionStart = start;
element.selectionEnd = end;
else if (element.createTextRange)
var rng = element.createTextRange();
rng.moveStart("character", start);
rng.collapse();
rng.moveEnd("character", end - start);
rng.select();
iElement.bind('mousedown mouseup keydown keyup', function()
if (ngModelController.$viewValue.length > 0)
var caretPosition = getCursorPos();
if (caretPosition.start === 0)
setCursorPos(1, caretPosition.end < 1 ? 1 : caretPosition.end);
if (caretPosition.end === ngModelController.$viewValue.length)
setCursorPos(caretPosition.start, ngModelController.$viewValue.length - 1);
);
)();
,
restrict: 'A',
require: 'ngModel'
);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<div ng-app="myApp">
<textarea ng-model="myVariable" beautify-text beautify-text-with-prefix="“" beautify-text-with-suffix="”"></textarea>
<p>myVariable: myVariable </p>
</div>
【讨论】:
这是一个非常聪明的解决方案!唯一缺少的是在值为空时删除引号。我可能可以自己添加!谢谢! @ThomasTeilmann 这很简单。我已经更新了我的代码。if (angular.isString(ngModelController.$modelValue) && ngModelController.$modelValue.length === 0 && newValue.length === 1)
成功了。【参考方案2】:
更新
所以我使用 ng focus 和 blur 来删除和添加引号,当他使用 textarea 时它不会生效,但它会工作
angular.module('myApp', [])
.controller('demoCtrl', ['$scope',
function($scope)
$scope.myModel = '';
$scope.removeQuotes = function()
$scope.myModel = $scope.myModel.replace(/“|”/gm, ''); // remove the quotes
$scope.addQuotes = function()
if ($scope.myModel == '')
$scope.myModel = ''; // dont add the quotes for an empty value
return;
$scope.myModel = "“" + $scope.myModel + "”" // add the quotes again
])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="demoCtrl">
<textarea ng-model="myModel" ng-focus='removeQuotes()' ng-blur='addQuotes()'></textarea>
</div>
</div>
【讨论】:
您发布的第一个解决方案实际上比这个更好,因为您让用户在 textarea 中输入,这对于我的场景来说是必需的。使用输入字段时,我无法查看您的答案。您的第一个答案的唯一问题是光标位于引号的错误一侧。我想那是不可能的 这实际上是一个非常好的主意。由于它不是 100% 解决问题的方法,所以在接受它之前,我会让它挂起一段时间!为你点赞!以上是关于Textarea ng-bind,其中 value 有前缀和后缀的主要内容,如果未能解决你的问题,请参考以下文章