Я пытаюсь создать директиву тега Angular, которая не слишком отличается от формы ввода тега Stack Overflow. Он использует div с рамкой для создания иллюзии формы, а затем div, содержащий список тегов слева от поля ввода, где вы можете ввести:
<div class="wrapper">
<div class="tag-wrapper">
<div class="tags" ng-repeat="tag in selectedTags">
<div>
[[ tag.name ]]
<span class="remove" ng-click="removeTag(tag)"></span>
</div>
</div>
</div>
<input type="text" class="tag-input"
ng-model="tagInput"
ng-style="{ width: inputLength + 'px'}"
ng-keypress="tagInputKeyPress($event)"
ng-keyup="updateSuggestionList()"
ng-focus="toggleSuggestionVisibility()"
ng-blur="toggleSuggestionVisibility()" />
</div>
Обратите внимание, что я использую [[]]
в качестве поставщика интерполяции для Angular, потому что у меня есть другой механизм шаблонов, уже использующий {{}}
.
Когда клавиша нажата на входе, она запускает функцию, чтобы проверить, является ли клавиша возвратом или вводом или пробелом для создания/удаления тега:
$scope.tagInputKeyPress = function(event) {
// Currently using jQuery.event.which to detect keypresses, keyCode is deprecated, use KeyboardEvent.key eventually:
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
// event.key == ' ' || event.key == 'Enter'
if (event.which == 32 || event.which == 13) {
event.preventDefault();
// Remove any rulebreaking chars
var tag = $scope.tagInput;
tag = tag.replace(/["']/g, "");
// Remove whitespace if present
tag = tag.trim();
$scope.createTag(tag);
// event.key == 'Backspace'
} else if (event.which == 8 && $scope.tagInput == "") {
event.preventDefault();
// grab the last tag to be inserted (if any) and put it back in the input
if ($scope.selectedTags.length > 0) {
$scope.tagInput = $scope.selectedTags.pop().name;
}
}
$scope.inputLength = $(element).find('input.tag-input').parent().innerWidth() - $(element).find('.tag-wrapper').outerWidth() - 1;
return true;
};
У меня проблемы с последней строкой перед оператором return. Что нужно сделать, так это пересчитать ширину элемента .tag-wrapper
и отрегулировать ширину элемента input
в соответствии с этим свойством ng-style
:
ng-style="{ width: inputLength + 'px'}"
Однако в настоящее время длина ввода всегда отстает от пользовательского интерфейса на один шаг, что приводит к переполнению ввода. Это потому что:
- Сначала он добавляет новый тег в список
selectedTags
. - Он вычисляет ширину
.tag-wrapper
. - Он возвращает true, пропуская исходное ключевое событие.
- Цикл дайджеста Angular запускается и добавляет новый тег в DOM. Ширина
.tag-wrapper
теперь больше, аinput
выходит за пределы.
Вот пример этого:
Прямо сейчас шаг 4 выполняется после шага 2. Мне нужно, чтобы шаг 2 выполнялся после шага 4.
Как я могу этого добиться?