Reputation: 10121
I have a global directive, that is in charge of getting the error message from the controller, compiling, and displaying it.
In case there is a server validation error such as
This email already exists
, I would like to focus on this element, and set it validity to false, e.g. $setValidity(false)
.
This directive is not the form, and it doesn't contain the form.
What would you suggest (already tried everything which is commented out)
directive('messageCompile', function ( $compile, $window, $rootScope ) {
return {
restrict: 'A',
scope: true,
link: function ( scope, element, attrs ) {
var el;
attrs.$observe( 'template', function ( tpl ) {
if ( angular.isDefined( tpl ) ) {
// compile the provided template against the current scope
el = $compile( tpl )( scope );
// stupid way of emptying the element
element.html("");
// add the template content
element.append( el );
}
});
attrs.$observe('focus', function(val){
if ( angular.isDefined( val ) && Boolean(val)) {
var el = angular.element('[name="' + attrs.focus + '"]');
var form = el.parents().find('form');
var formName = form.attr('name');
el.focus();
// scope[formName].$setValidity(val, false);
// el.scope().$setValidity(false);
// scope[formName][val].$setValidity(false);
//$rootScope.scope[formName][val].$setValidity(false);
//$rootScope.scope[formName].$setValidity(val, false);
}
});
var windowEl = angular.element($window);
windowEl.on('scroll', function() {
if(window.scrollY > 46){
element.parent().parent().addClass('stayTop');
// alert('here');
}
else{
// alert('here2');
element.parent().parent().removeClass('stayTop');
}
});
},
}
}).
Upvotes: 2
Views: 4600
Reputation: 10121
Well, I've managed to solve this in a way that gives a sufficient result:
attrs.$observe('focus', function(val){
if (angular.isDefined(val) && Boolean(val)) {
var el = angular.element('[name="' + attrs.focus + '"]');
var form = el.parents().find('form');
var formName = form.attr('name');
el.focus();
el.removeClass('ng-valid').addClass('ng-invalid');
el.bind('keyup', function(){
el.removeClass('ng-invalid');
el.unbind('keyup');
});
}
});
Of course the keyup event can be replaced by a change event, or any other event.
Upvotes: 0
Reputation: 40298
In order to use $scope[formName]
the controller must be on the form element. Either by defining directly:
<form name="theForm" ng-controller="TheCtrl">
Or as a directive:
directive("myDirective", function() {
return {
template: "<form name='theForm'>...</form>",
controller: ["$scope", function($scope) {
...
}],
...
};
});
If one these conditions is met, then you have to define the name attribute for every element that you need to access:
<form name="theForm" ...>
<input name="theInput" ...>
Then you can access $setValidity()
, inside the corresponding controller, as defined above:
$scope.theForm.theInput.$setValidity(false);
AGAIN REMEMBER: In order for a controller to access the form, it must be at the same element as the form, or maybe at a child scope.
Upvotes: 4