Reputation: 2812
I'd like users to be able to enter multiple answers to a question, so I have an ng-repeat of text inputs that grows as the user adds more answers.
This is working fine in chrome, but in safari, the last element steals the focus as soon as it's added spreading a fast typing user's answer across several inputs.
In iOS safari it's even worse, as it's causing the browser to hang.
Here's the code for the form
<form class="form-horizontal sparse"
ng-controller="AssessmentController as assessment">
<fieldset>
<div class="form-group alt-uses-list" ng-repeat="response in answer.responses">
<label for="answer{{$index}}" class="col-xs-1 control-label">{{$index + 1}}.</label>
<div class="col-xs-10">
<input type="text" class="form-control"
id="response.uses{{$index}}"
autocomplete="off" tabIndex="{{$index + 1}}"
autofocus="{{$first}}" ng-model="response.value"
ng-change="assessment.addAnswerIfNeeded()">
</div>
</div>
</fieldset>
</form>
Here's the controller
function AssessmentController($scope, $log) {
$scope.answer = {};
$scope.answer.responses = [{id:0, value:""},{id:1, value:""}];
this.addAnswerIfNeeded = addAnswerIfNeeded;
// Add answer if the last two answers are non-empty
function addAnswerIfNeeded() {
var answers = $scope.answer.responses;
if ((answers[answers.length - 1].value != '') ||
(answers[answers.length - 2].value != '')) {
addAnswer();
}
}
// Adds a new answer if this is the last element
// isLast is needed to prevent non-lazy evaluation bugs
function addAnswer() {
$scope.answer.responses.push({
id:$scope.answer.responses.length, value: ""
});
};
}
I've created a jsfiddle.
Upvotes: 1
Views: 452
Reputation: 5179
The autofocus
attribute is a Boolean
type.
According to this link:
The value passed as the first parameter is converted to a boolean value, if necessary. If value is omitted or is 0, -0, null, false, NaN, undefined, or the empty string (""), the object has an initial value of false. All other values, including any object or the string "false", create an object with an initial value of true.
Do not confuse the primitive Boolean values true and false with the true and false values of the Boolean object
autofocus="{{$first}}"
generates autofocus="false"
on any item that is not the first item in the ng-repeat
. As the link states
All other values, including any object or the string "false", create an object with an initial value of true.
If you can update to a angular JS version that includes the ng-attr
directive you can update your code to be the following, I have updated you jsfiddle to show a working example
<form class="form-horizontal sparse" ng-controller="AssessmentController as assessment">
<fieldset>
<div class="form-group alt-uses-list" ng-repeat="response in answer.responses">
<label for="answer{{$index}}" class="col-xs-1 control-label">{{$index + 1}}.</label>
<div class="col-xs-10">
<input type="text" class="form-control" id="response.uses{{$index}}" autocomplete="off" tabIndex="{{$index + 1}}" ng-attr-autofocus="{{$first||undefined}}" ng-model="response.value" ng-change="assessment.addAnswerIfNeeded()">
</div>
</div>
</fieldset>
</form>
When the ng-attr-autofocus="{{$first||undefined}}"
evaluates to false, the autofocus
attribute gets the value of undefined
and thus the autofocus
gets removed from the dom.
Upvotes: 1