Keyboard navigation on Angular uib-dropdown is not working - javascript

I'm using Angular Bootstrap 2.2.0 with Angular 1.5.
The keyboard navigation doesn't work on UIB dropdowns even with the keyboard-nav option enabled. Here's my code:
<div class="btn-group"
uib-dropdown
keyboard-nav="true"
on-toggle="vm.setTouchNgModel(open)">
<button type="button"
class="btn btn-secondary btn-dropdown"
ng-class="{'text-muted': !vm.selectedOptionLabel }"
uib-dropdown-toggle
ng-disabled="vm.selectDisabled">
{{ vm.selectedOptionLabel || ((vm.selectPlaceholder | translate) || vm.selectPlaceholder) }}
<i class="caret"></i>
</button>
<ul class="dropdown-menu"
uib-dropdown-menu
role="menu"
aria-labelledby="btn-append-to-single-button">
<li ng-if="vm.inlineOption">
<a ng-click="vm.setSelectModel(vm.inlineOption)">{{ vm.inlineOption[vm.labelProperty] }}</a>
</li>
<li ng-repeat="option in ((vm.filterName && vm.applyFilter(vm.options, vm.filterName, vm.filterOptions, vm.filterExpression)) || vm.options)">
<a role="menuitem" ng-click="vm.setSelectModel(option)">{{ ((option[vm.labelProperty] || option.label || option) | translate) || ((option[vm.labelProperty] || option.label || option) | translate) }}</a>
</li>
</ul>
</div>

I have found the solution, there needs to be a href attribute in the choices <a> tag, for the keyboard-nav to work.

<a> tags need a tabindex attribute to be able to be focused.
Add tabindex="0" to all of them. A value of "0" makes them tabbable in document order.

Related

AngularJS ng-click not working properly

Code:
<div class="input-dropdown-wrapper d-flex space-between vertical-center margin-right-12"
ng-class="{'active': historyController.showFilterHistoryDurationDropdown === true}"
ng-click="historyController.showFilterHistoryDurationDropdown = true"
when-clicked-off="historyController.showFilterHistoryDurationDropdown = false">
<p>
Show {{historyController.filter}}
</p>
<i class="fas fa-angle-down"></i>
<ul class="input-dropdown"
ng-if="historyController.showFilterHistoryDurationDropdown">
<li ng-class="{'active': historyController.filter === 'All'}"
ng-click="historyController.filter = 'All';
historyController.showFilterHistoryDurationDropdown = false">
Show All
</li>
<li ng-class="{'active': historyController.filter === 'In Progress'}"
ng-click="historyController.filter = 'In Progress';
historyController.showFilterHistoryDurationDropdown = false">
Show In Progress
</li>
<li ng-class="{'active': historyController.filter === 'Completed'}"
ng-click="historyController.filter = 'Completed';
historyController.showFilterHistoryDurationDropdown = false">
Show Completed
</li>
</ul>
</div>
All of this works perfectly. When the <div class="input-dropdown-wrapper...> gets clicked, the <ul> appears as it should.
What I don't understand is why the second part of the ng-click of each <li> doesn't work at all.
Specifically talking about this part: historyController.showFilterHistoryDurationDropdown = false".
Setting this value to false should hide the <ul>, just like when you click the <div>, it sets the value to true, causing the <ul> to appear.
If you are looking for some Toggle view solution, ng-click logic should toggle the showFilterHistoryDurationDropdown value Like :
ng-click="historyController.showFilterHistoryDurationDropdown
? historyController.showFilterHistoryDurationDropdown = false
: historyController.showFilterHistoryDurationDropdown = true"
So that when you click on the div having the ng-class will show the list (<ul>), on second click it will hide the list (<ul>)
So your final code should look something like:
<div class="input-dropdown-wrapper d-flex space-between vertical-center margin-right-12"
ng-class="{'active': historyController.showFilterHistoryDurationDropdown === true}"
ng-click="historyController.showFilterHistoryDurationDropdown ? historyController.showFilterHistoryDurationDropdown = false : historyController.showFilterHistoryDurationDropdown = true"
when-clicked-off="historyController.showFilterHistoryDurationDropdown = false">
<p>
Show {{historyController.filter}} <br>
showFilterHistoryDurationDropdown : {{historyController.showFilterHistoryDurationDropdown}}
</p>
<i class="fas fa-angle-down"></i>
<ul class="input-dropdown"
ng-if="historyController.showFilterHistoryDurationDropdown">
<li ng-class="{'active': historyController.filter === 'All'}"
ng-click="historyController.filter = 'All';
historyController.showFilterHistoryDurationDropdown = false">
Show All
</li>
<li ng-class="{'active': historyController.filter === 'In Progress'}"
ng-click="historyController.filter = 'In Progress';
historyController.showFilterHistoryDurationDropdown = false">
Show In Progress
</li>
<li ng-class="{'active': historyController.filter === 'Completed'}"
ng-click="historyController.filter = 'Completed';
historyController.showFilterHistoryDurationDropdown = false">
Show Completed
</li>
</ul>
Hope this helps.. :)

Pagination shown even though there is no data in angular

Here is my code:
Buttons:
<li ><a data-ng-click="Data1 = true;Data2 = false; search.status = ''" href="">ALL PROJECTS</a></li>
<li ><a data-ng-click="Data2 = true;Data1 = false" href="">NOTIFICATIONS</a></li>
Populated data on click of button:
<ul>
<li ng-show="Data1" dir-paginate="wd in workOrdersList | filter: search.status | filter: search.name | itemsPerPage: 10">
<a href="">
<h4>{{wd.name}}</h4>
</a>
<p>Status: {{wd.status}}</p>
</li>
<li ng-show="Data2">
<div ng-show="!notificationDataDashord.length">
<span>No Notifications</span>
</div>
</li>
</ul>
<dir-pagination-controls auto-hide="true"></dir-pagination-controls>
Inside the controller:
$scope.Data1 = true;
$scope.Data2 = false;
I am using pagination directive from this link:
https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination
Its a problem with the dirpagination that it doesnt update the collections after you load the data again.
See
https://github.com/michaelbromley/angularUtils/issues/208
https://github.com/michaelbromley/angularUtils/issues/137
As a work around obviously
<dir-pagination-controls ng-show="Data1" auto-hide="true"></dir-pagination-controls>

Nested elements and directives

I got an workaround here and need some help. It is a tree of categories. Some categores can be chosen by a checkbox.
I thougt the cleanest way to do that is via direction. On a <li kw-category-node> element put a on('click', function()) handler, which then does the choosing work (add object to data etc.).
So I came up with this HTML
<script type="text/ng-template" id="category_renderer.html">
<div ng-if="true == true" ng-mouseenter="over = true" ng-mouseleave="over = false">
<input type="checkbox"
ng-model="assignedCategories[category.category_id]"
ng-if="category.childs.length == 0"
ng-click="toggleCategory(category)">
</input> {{ category.name }}
<a href ng-if="over" ng-click="categories.remove(category)">
<small> <i class="fa fa-times"></i> Entf </small>
</a>
</div>
<ul class="list-unstyled">
<li ng-repeat="category in category.childs"
ng-include="'category_renderer.html'"
kw-category-node>
</li>
</ul>
</script>
<ul class="list-unstyled" kw-category-tree>
<li ng-repeat="category in categories.tree"
ng-include="'category_renderer.html'"
kw-category-node>
</li>
</ul>
And a directive like that
admin.directive('kwCategoryNode', ['$interval', 'dateFilter', function($interval, dateFilter) {
function link(scope, element, attrs) {
element.find('input').on('click', function() {
alert("wow, what a click!");
});
}
But element.find("input") wont give me that input element. Maybe the DOM is not loaded completly or I'm just in tilt.
Thanks

How to enable up and down arrow keys in bootstrap dropdown

Bootstrap 3 panel title contains dropdown using code below.
If dropdown is opened, up and down arrows do not move between items.
How to enable dropdown navigation using up and down arrow keys ?
<div class="panel panel-success grid-panel-header">
<div id='contentCaptionDiv' class="panel-heading">
<div class="panel-title form-inline">
<a class="btn" href="Show">
<i class="fa fa-male" aria-hidden="true"></i>
</a>
<a class="btn" href="Delete">
<i class="fa fa-female" aria-hidden="true"></i>
</a>
<div class="dropdown" type="button">
<div class="dropdown-toggle" data-toggle="dropdown" role="button" href="#">
<i class="glyphicon glyphicon-cog"></i>
<span class="caret"></span>
</div>
<ul class="dropdown-menu" role="menu">
<li>Action</li>
<li>Another action</li>
<li>Something else here</li>
</ul>
</div>
</div>
panel content here
</div>
The reason that you code doesn't work is because you use a <div> for .dropdown-toggle.
Make it a <button> and it will work.
Strange enough, not even this kind of element works: span.btn.btn-default.
Another reason that do not apply to your case:
Make sure your <a> elements inside the <li>s have an attribute of href="#" or href="" (ir that the attribute exists, in general).
href="#" works indeed for arrow keys. Using this causes page 404 redirect on item select. If you are not looking to redirect to another page use this work around: href="javascript:" instead of href="#"
<script type="text/javascript">
$(document).keydown(function(e) {
if(e.which == 40 || e.which == 38) {
openNavbar = $(".dropdown.open");
if(openNavbar[0]) {
menu = openNavbar.children(".dropdown-menu");
menu.find("a").css("outline", "none"); // remove the pesky blue outline
hovered = menu.find("li:hover");
if(hovered[0]) {
if(e.which == 40) hovered.next().children().focus();
else hovered.prev().children().focus();
}
else menu.find("li").first().children().focus();
}
}
});
</script>
I haven't found a built in solution, but I have made a snippet, that seems to do the job.

Change another directive angularjs

I have two directives to format text of elements.
app.directive("kilometersText", function(){
// writes number as kilometer
})
app.directive("metersText", function(){
// writes number as meter
})
HTML:
<ul>
<li ng-repeat="item in data">
<span kilometers-text="item.length"></span>
</li>
</ul>
I have two buttons that change view to meter or kilometer.
<button type="button"> meter </button>
<button type="button"> kilometer </button>
How can I change directive with these buttons?
Instead of changing the attribute, i suggest to use two spans, one for showing in KMs and other in meters. and then hide them conditionally based on the selected view.
<ul>
<li ng-repeat="item in data">
<span ng-show="item.view == 'kilometer'" kilometers-text="item.length"></span>
<span ng-show="item.view == 'meter'" kilometers-text="item.length"></span>
</li>
</ul>

Categories