Reputation: 235
I am trying to focus the first tab which contains invalid field on a form submit. I did manage to focus on the first input field but it doesn't work if the field is in another tab and I have no idea how to make it works.
Here is my html file:
<uib-tabset justified="true">
<uib-tab heading="{{ 'PERSONAL_INFORMATION' | translate }}">
inputs...
</uib-tab>
<uib-tab heading="{{ 'BANK_ACCOUNTS' | translate }}">
inputs...
</uib-tab>
<uib-tab heading="{{ 'CONNECTIVITY' | translate }}">
inputs...
</uib-tab>
</uib-tabset>
The directive that focus on the first invalid input:
app.directive('focus', function() {
return {
restrict : 'A',
link : function(scope, elem) {
// set up event handler on the form element
elem.on('submit', function() {
// find the first invalid element
var firstInvalid = elem[0].querySelector('.ng-invalid');
// if we find one, set focus
if (firstInvalid) {
firstInvalid.focus();
}
});
}
};
});
I would appreciate any help.
Upvotes: 0
Views: 2269
Reputation: 614
after you identify the first invalid element with
var firstInvalid = elem[0].querySelector('.ng-invalid');
you can find the controller of the tab it belongs to with:
var tab = angular.element(firstInvalid).parents('div.tab-pane').scope().tab
and you can call that controller's select function:
tab.select()
That will select the tab containing the firstInvalid element, which I think is what you mean by "focus the tab".
I had a further requirement, which was to show all tabs containing invalid controls with a background-color
. This is more difficult as you need to identify the <li>
containing the tab heading, and the tab scope doesn't have anything identifying the element.
I marked each tab with a class like this:
<uib-tab ng-repeat="(roomtype, roominfo) in data.roomtypes track by roomtype" heading="{{roominfo.title}}" class="roomtype-{{roomtype}}" >
and the roomtype property of the tab containing the invalid control is
var roomtype = tab.$parent.roomtype;
and I can set a class to indicate invalid like:
angular.element('li.roomtype-' + roomtype ).addClass('tab-invalid');
This statement relies on full jQuery being loaded as jqLite doesn't do lookups by CSS selector.
Upvotes: 0
Reputation: 1075
If I'm understanding your question correctly, you want to focus on the first tab that contains the invalid element. To do that, give each tab an ngForm
directive.
This will force the parent form controller to validate each of the tabs as an independent form (although they will continue to belong to the parent controller). As such, each will be treated like the a form, which will also be given an ng-invalid
class. Assuming your tabs are focusable, it should work.
<form name="myForm" test>
<uib-tabset justified="true">
<uib-tab heading="{{ 'PERSONAL_INFORMATION' | translate }}" ng-form="form1">
inputs...
</uib-tab>
<uib-tab heading="{{ 'BANK_ACCOUNTS' | translate }}" ng-form="form2">
inputs...
</uib-tab>
<uib-tab heading="{{ 'CONNECTIVITY' | translate }}" ng-form="form3">
inputs...
</uib-tab>
</uib-tabset>
</form>
You can see an (admittedly rudimentary) example on this plunk.
Upvotes: 0