Detecting unassigned values ββin angular directives
I have a directive that will get / set focus on an element based on the value.
When the element is focused or blurred, the directive will update the boolean. However, sometimes I only need to set focus when a condition is met, and I use a non-assignable value that causes this error:
Error: [$compile:nonassign] Expression '$last && !domain.url' used with directive 'focusWhen' is non-assignable!
WORKING DEMO HERE (check your console for errors)
I understand why it is throwing an error, but how can I define non-assignable values ββfrom within the directive and then prevent it from attaching focus / blur events that try to assign a value when the focus changes?
Here's an example of using a directive used with an untranslatable value. In this case, it will focus on the last element of the repeater if it is also empty
<div ng-repeat="domain in domainList">
<input type="text" ng-model="domain.url" focus-when="$last && !domain.url"/>
</div>
And here is the directive code
testApp.directive("focusWhen", ["$timeout", function ($timeout) {
function getLink($scope, $element) {
$scope.$watch("focusWhen", function (val) {
//only focus when needed and when this element doesn't already have focus
if (val && $element[0] !== document.activeElement) {
//Small delay needed before we can get focus properly
$timeout(function () {
$element.focus();
});
}
});
$element.on("blur.focusWhen", function () {
if ($scope.focusWhen) {
$timeout(function () {
$scope.focusWhen = false;
});
}
});
$element.on("focus.focusWhen", function () {
if (!$scope.focusWhen) {
$timeout(function () {
$scope.focusWhen = true;
});
}
});
}
return {
restrict: "A",
scope: {
focusWhen: "="
},
link: getLink
};
}]);
source to share
Update
The programmatic way of detecting this (instead of having another attribute) is using $parse
fn. This is how angular checks and throws an error. It tries to parse the bi-directional binding attribute, and if it has no destination attribute, it throws an error. ($parse($attrs['focusWhen']).assign)
...
Old answer:
How about another attribute indicating whether you want to return the focus value?
<input type="text" ng-model="domain.url" one-way="true" focus-when="$last && !domain.url"/>
$element.on("blur.focusWhen", function () {
if ($scope.focusWhen) {
$timeout(function () {
if (!$attr.oneWay) {
$scope.focusWhen = false;
}
});
}
});
source to share