Tabindex in AngularJS directive - angularjs

I have written a directive which produces a table including some rows. Each row has some drop-down list for selection and also some normal text areas to fill information.
The problem is, when I hit the tab key on Keyboard, the drop-down selections are ignored and not focused. The cursor jumps to the next text area. I tried to fix the problem with incremental tabindex attribute inside each column of rows, but still no difference.
Each column of each row is produced inside the directive by looping over an array using ng-repeat. Following produces a drop-down:
<td><ng-select ng-model="oneRow.XItem" ng-options="opt.name as opt.name for opt in selections.XItemList| orderBy:'name'" cs-option-init=""></ng-select></td>
Follwing produces a text area which is focused by pressing tab on keyboard.
<td><ng-input ng-model="oneRow.YItem" ></ng-input></td>
Please note all produced inside a directive NOT a static HTML.
The picture depicts the table. By hitting tab key, cursor jumps to next possible text area either in the same row or next row.

Not precisely sure what behavior you are describing here. However, by default your HTML will tab through properly formatted for fields from left-to-right before continuing to the next row.
Tab will allow the user to focus on the "next " form field, however, once a drop-down has focus, the arrow-up/down keys are used to select an option. Once an option is selected, pressing tab again moves to the next form field.
If something is skipped, I would check your HTML syntax.
Even via angular, the DOM is the DOM. If the syntax for your form fields is correct within the table, it will process correctly using tabs.
Non-anglar example because using angular should have zero effect on tabbing if you didn't force a tabindex: https://codepen.io/KarsunJason/pen/KqeOYg
<form>
<table style="width:75%">
<tr>
<td><select id="tableDropdown-useNgRepeatIndexHere0"><option value="volvo">Volvo</option><option value="saab">Saab</option><option value="mercedes">Mercedes</option><option value="audi">Audi</option>
</select></td>
<td><select id="tableDropdown-useNgRepeatIndexHere1"><option value="volvo">mr</option><option value="saab">mrs</option><option value="mercedes">Sir</option><option value="audi">Madame</option>
</select></td>
<td><select id="tableDropdown-useNgRepeatIndexHere2"><option value="volvo">1</option><option value="saab">2</option><option value="mercedes">3</option><option value="audi">4</option>
</select></td>
<td><input id="tableDropdown-useNgRepeatIndexHere4"></td>
<td><input id="tableDropdown-useNgRepeatIndexHere5"></td>
<td><select id="tableDropdown-useNgRepeatIndexHere6"><option value="volvo">5555</option><option value="saab">4444</option><option value="mercedes">3333</option><option value="audi">2222</option>
</select></td>
<td><input id="tableDropdown-useNgRepeatIndexHere7"></td>
</tr><tr>
<td><select id="tableDropdown-useNgRepeatIndexHere8"><option value="volvo">Volvo</option><option value="saab">Saab</option><option value="mercedes">Mercedes</option><option value="audi">Audi</option>
</select></td>
<td><select id="tableDropdown-useNgRepeatIndexHere9"><option value="volvo">mr</option><option value="saab">mrs</option><option value="mercedes">Sir</option><option value="audi">Madame</option>
</select></td>
<td><select id="tableDropdown-useNgRepeatIndexHere10"><option value="volvo">1</option><option value="saab">2</option><option value="mercedes">3</option><option value="audi">4</option>
</select></td>
<td><input id="tableDropdown-useNgRepeatIndexHere11"></td>
<td><input id="tableDropdown-useNgRepeatIndexHere12"></td>
<td><select id="tableDropdown-useNgRepeatIndexHere13"><option value="volvo">5555</option><option value="saab">4444</option><option value="mercedes">3333</option><option value="audi">2222</option>
</select></td>
<td><input id="tableDropdown-useNgRepeatIndexHere14"></td>
</tr>
</table>
</form>
Suggestions:
1) Check your form fields for proper syntax.
2) Either use tabindex="0" in each field (forces a tab stop within the natural order of the page) or remove tabindex entirely.

Related

Angular Js orderBy with input values

I'm having issues with the orderBy filter. The following code will order my initiative column just fine. When I type a value into the input, the filter automatically begins ordering the values just as I want it to.
However, if I type a value into the input that raises that character higher in the list the input will close out before I can finish typing that value.
If the value I type into the input drops the character lower down the list then that input does not close and allows me to finish typing my value.
Can anyone explain this behavior?
<tr ng-repeat="char in localChars | orderBy: '-initiative'">
<td>{{char.name}}</td>
<td ng-hide='show' ng-click='show = true'>{{char.initiative}}</td>
<td ng-show='show'>
<input ng-blur='initiative(char)' ng-model='char.initiative' type="text">
</td>
</tr>
Here is what I believe is the sequence of events:
User types in input changing the value of char.initiative.
This causes the list to reorder via the ng-repeat.
The scope of the ng-repeat is re-initialized causing the local show variable to lose its value (remember, ng-repeat has its own scope).
To fix this you'll need to use ng-model-options to control when the model value actually gets updated. You can choose to update on blur or use a debounce. Here is how to update on blur (my recommendation). You can find info on debouncing at the link.
<input ng-blur="initiative(char)"
ng-model="char.initiative"
ng-model-options="{ updateOn: 'blur' }"
type="text" />

ng-change does not work in the table row generated by ng-repeat

I have a simple table row.
The row is generated by below code.
<tr ng-init="cacheChanged">
<td>Expiration Period</td>
<td ng-repeat="system in tableData.regions[0].systems">
<input type="text" ng-model="system.cacheDuration" ng-change="cacheChanged=true">
<span>h</span>
</td>
<td>
<button type="button" ng-click="saveCache()" ng-disabled="!cacheChanged">Save</button>
</td>
</tr>
When any of the four values changed, the save button is supposed to be enabled. However, it is still disabled all the time. Anyone knows why? Thanks in advance!
In your case you should use $parent.cacheChanged instead of cacheChanged variable. As ng-repeat does create child scope for each loop while rendering DOM. In short the cacheChanged variable inside ng-repeat is not same as that of cacheChanged used there on button.
Markup
<td ng-repeat="system in tableData.regions[0].systems">
<input type="text" ng-model="system.cacheDuration" ng-change="$parent.cacheChanged=true">
<span>h</span>
</td>
There is better way to go for it will be using Dot rule while defining ng-model, look at this detailed answer here.

Validating form using Angular when name field has dots and brackets

The form to be validated is master detail i.e. it has two portions. master portion contains two fields while detail portion initially has two rows but they can be increased by pressing a button on DOM. The form looks like the following
The problem is that in detail portion I have to create the inputs using ng-repeat like
<div class="form-group">
<table style="margin-left:10%;">
<tr>
<th>Account id</th>
<th>Amount</th>
</tr>
<tr class="edit-row" ng-repeat ="entry in model.Entries">
<td>
<input type="text" ng-model="model.Entries[$index].AccountId" required name="Entries[{{$index}}].AccountId"/>
</td>
<td>
<input type="text" ng-model="model.Entries[$index].Amount" required name="Entries[{{$index}}].Amount"/>
<span class="field-validation-error text-danger" ng-show="transactionForm['Entries['{{$index}}'].Amount'].$invalid && transactionForm['Entries['{{$index}}'].Amount'].$dirty">
Amount is Required
</span>
</td>
</tr>
</table>
</div>
But the ng-show attribute is not working fine for the detail portion. This is because, I have dots (.) and brackets ([) in the name of input fields. How can I perform validation in such scenario. Someone may argue to change the names of the input but I have to use this convention for input names in the detail portion. In current code, I have used bracket notation in ng-show attribute of Amount field as described in This SO question, but to no avail. you can find complete example at plunker
Can you do something like this?
ng-show="model.Entries[$index].Amount === ''"
Rather than trying to check the form value check the actual model value. This will work assuming you are just checking to make sure there is a value other than the empty string. You will have to make the check more specific to what you are looking for. You can also set the type="number" if you only want to allow the user to enter a numeric value.

AngularJS - Search Filter nested array

AngularJS newbie trying to limit a search filter to one very nested array item. Here's a shot of my output:
<div ng-controller="listController">
<input type="text" ng-model="searchMe" />
<table class="table">
<tr>
<th>Product Name</th>
<th>Color</th>
<th>Size</th>
<th>Features</th>
</tr>
<tr ng-repeat="p in prods | filter:searchMe">
<td>{{p.products.1.ProductName}}</td>
<td>{{p.products.1.Color}}</td>
<td>{{p.products.1.Size}}</td>
<td>
<ul ng-repeat="feats in p.features">
<li>{{feats}}</li>
</ul>
</td>
</tr>
</table>
</div>
Which displays all the items in the list correctly, including the additional features. Now there are at least another dozen items in the products array, including description, price, etc. The issue is if I search something in the box, it searches the entire array. Now I've tried changing the search input to:
<input type="text" ng-model="search.products.1.ProductName" />
<input type="text" ng-model="search.p.products.1.ProductName" />
<input type="text" ng-model="search.ProductName" />
However as soon as I type one character everything disappears. Yes I've also taken the "me" off the search filter (| filter:search). How can I bind the search to a specific item in a nested array? I'll also need to be able to search by features, but I'm hoping by solving this first it'll lead my to the features. Also my content is being pulled in by a json file if that makes a difference. The search features will eventually be checkboxes as well, and not text inputs, but I figure it shouldn't matter, I will still need to target the specific items (name, color, size, etc).
Thoughts/ideas/suggestions?
My solution for the time being is restructuring the json file. Maybe when my knowledge of Angular expands I'll be able to revisit.

ng-model table show data angularjs

I ma very beginner in Angularjs and pardon my silly mistakes. I have a table which shows data in three columns and i want to filter this table based on a condition and hide unnecessary data in one column which contains integers. I have used ng-show with some condition linked to ng-model and this is working perfect if i enter data in my ng-model only after loading total form. But, i want to show all the table data in the beginning and then hide unnecessary data based on ng-show condition.
How can i do this? I am struggling!
<tr ng-show= "change > val1 " ng-repeat="change in montlyProjection();" >
<td>some data</td>
<td class="number">some data</td>
<td class="number" ng-class="positiveNegative(convertToNumber(startBalance) + change)">some data</td>
</tr>
</strong><input type="text" ng-model="val1" placeholder="Enter Amount" />
<tr ng-show="((change > val1) || !val1)" ng-repeat="change in monthlyProjection()">
Try adding additional conditions to the ng-show directive. If !val doesn't work try using "angular.equals(val1,'')" or "angular.isDefined(val1)"

Resources