Use CSS3 animations with a list in Angular - angularjs

I have a list of items with a checkbox for each item. I'm using CSS3 animations (this particular CSS http://daneden.github.io/animate.css/) and Angular to manipulate this list. I've managed to animate adding a new element to the list, but I'm having trouble animating removal of an item from the list (e.g. deleting or checking the checkbox).
This is what a list item looks like:
<li ng-class="{'animated fadeInDown' : task.isNew, 'animated fadeOutRight' : delete}" class="list-group-item" ng-repeat="task in tasks | filter:{is_done: false}" ng-mouseover="hovering = true" ng-mouseout="hovering = false">
<input type="checkbox" ng-model="task.is_done" ng-click="toggleDone(task)">
<span class="done-{{task.is_done}}" ng-hide="editing" ng-dblclick="editing = true">{{task.name}} </span><a href ng-show="hovering" ng-click="deleteTask(task); delete = true">x</a>
</li>
When I add a new task, the property task.isNew is set to true which sets 'animated fadeInDown' class to the list element. However, when I click on delete link, I would expect the class to be 'animated fadeOutRight' and that the removal is actually animated. This doesn't happen though, the item is removed but no animation is displayed.

Related

Screen reader not reading list values while navigating with arrow keys

I have an input field where a typeahead popup comes on searching for something. The screen reader is unable to read the values of suggestions in the popup.
I am maintaining the focus using $ActiveIndex variable. I am able to navigate the list using only the arrow keys, the screen reader just reads the input text when navigating the popup list and not the actual values in the suggestions
The HTML code is something like this:
<input type="text"
class="search"
title="Search User"
ng-model="vm.SearchText"
ng-model-options="{ debounce: 300 }"
aria-label="{{ placeholder }}"
ng-required="requiredattr" />
<ul class="ui list menu typeahead popup-layer vertical" ng-show="vm.MenuShown" ng-mousedown="vm.RetainFocus()">
<li class="item"
ng-class="{ active: $index == vm.ActiveIndex }"
ng-click="vm.Add(match)"
ng-repeat="match in vm.Matches track by $index">
<div class="header">
<i class="ban icon" ng-if="match.Deleted"></i>
<span ng-bind-html="match.DisplayName"></span> <!-- I want this DisplayName to be read -->
</div>
</li>
</ul>
The UI looks like this
The screen reader is just reading "suh" everytime I navigate the results with arrow keys.
Things I have tried:
Adding aria-label attribute to list item - Didn't work, I guess the element should be tab focusable for the aria label to be read out.
Adding tabindex = -1 to the list item to make it focusable but not navigable. Didn't work either.
You can use aria-active-descendant attribute and set it to the list options IDs and also use aria-owns property from the input box to refer the list items.

Limiting the drag area in angular drag drop list

I'm using the angular drag drop list library for drag/drop of items in a list. Currently I see the item is draggable throughout the body of the page. How can I limit the drag area to only to a particular zone and not everywhere. I checked their API but I don't see any option for that.
In the plunker example you cannot drag and drop every where, only on html element with dnd-draggable
<ul dnd-list="list">
<!-- The dnd-draggable directive makes an element draggable and will
transfer the object that was assigned to it. If an element was
dragged away, you have to remove it from the original list
yourself using the dnd-moved attribute -->
<li ng-repeat="item in list"
dnd-draggable="item"
dnd-moved="list.splice($index, 1)"
dnd-effect-allowed="move"
dnd-selected="models.selected = item"
ng-class="{'selected': models.selected === item}"
>
{{item.label}}
</li>
</ul>

Add class to selected ng-repeat list elements

Hey I'm looping thru an array using ng-repeat in my template. The list spits out 9 list elements and I would like change the background color of the selected list element but I want to do it in a way where multiple ones can be selected and the color of the selected ones with a different background color. Initially I had passed $event to the click function on the list element and added a class to event.target but that put the class on all the list elements rather than the selected one.
<ul>
<li class="info-items"
ng-repeat="card in config.cards"
ng-class="{'error-border': emptyCardsArray}">
<div class="inner-text"
ng-model="userSelection.cards"
ng-click="addCard(card.name, $event)">{{card.name}}{{$index + 1}}</div>
</li>
</ul>
HTML:
$(event.target).addClass('active.cards');
JS:
The list that I'm repeating thru unforunately doesn't have a unique ID or I would have passed in the ID and created a condition to check whether the selected items have one and applied the class.
It's a much better practice to simply use ng-class for this.
<ul>
<li class="info-items"
ng-repeat="card in config.cards"
ng-class="{'error-border': emptyCardsArray}">
<div class="inner-text"
ng-model="userSelection.cards"
ng-class="active.cards">{{card.name}}{{$index + 1}}
</div>
</li>
</ul>

Angular dropped item stay on dropped position

I'm using angular-dragdrop to move images from on div to another div. As each div has its own $scope list, when I drop an element from one to another list, the list which receives the item is updated.
However when I drop an item into the droppable area, it goes to top-left corner. It does not stay where I dropped
this is my html
Draggable
<div class="sand-image" ng-repeat="item in filtered = (products | filter: {cat : config.category.id}:true) |
itemsPerPage: pageSize"
current-page="currentPage"
data-drag="true"
data-jqyoui-options="{revert: 'invalid', helper: 'clone'}"
ng-model="products"
jqyoui-draggable="{index:$index,applyFilter:'{{getIndex(item)}}',
placeholder: 'keep',deepCopy :true}"
></div>
Droppable
<div class="wrap" id="sand-ground"
data-drop="true"
ng-model='box'
jqyoui-droppable="{multiple:true, deepCopy:true ,onOver :'stop',containment :'position'}" >
<!-- item html -->
<div class="draggable" ng-repeat="item in box track by $index" resizable ><img src="{{item.url}}" ></div>
The item in the second list ( dropable ) has a directive ( resizable )to set some info to the item.
How can I make the dropped item stay on dropped position?
$scope.dropAction = function(event, ui) {
console.log('left:', ui.position.left, 'top:', ui.position.top, ui);
// update model
var newItem = {
left:, ui.position.left,
top:, ui.position.top
};
$scope.someList.push(newItem);
};
Since you can capture the position in your drop function, I decided to just update a model that manages the positions of each draggable item. In your drop function:
jqyoui-droppable="{onDrop: 'dropaction($event)'}"
Then in your markup you can repeat through the items and use the stored property to position them with inline ng-style.
ng-repeat="item in someList" ng-style="{'left': item.left, 'top': item.top}"
These are the basics of what I did and you will most likely have to expand it to fit your usage. In my case, this captures pixels and I am converting to percentages in order to get responsive positions. I also launch a $uibModal that takes more information about my item before I place it.

ng-repeat Circular Reference Screen Refresh

I'm a noob to AngularJS. As a learning exercise I am creating a typeahead control.
The typeahead is comprised of a text box for filtering the options, an unordered list for displaying the menu of short-listed options, and a Show/Hide button for manually toggling the list.
The text box filters the li elements using ng-repeat. When selecting an li item from the list, I populate the text box with the selected value, and then hide the list.
<div class="xtab-typeahead" ng-controller="xTabTypeAheadCtrl">
<input type="text" class="xtab-typeahead-search" placeholder="{{type}}" ng-model="query.id" ng-focus="showMenu()" ng-init="query.id = undefined" />
<button ng-click="toggleMenu()">Show/Hide</button>
<ul class="xtab-typeahead-menu" ng-class="{true:'active',false:''}[isActive]">
<li ng-repeat="item in menuItems | filter:query"
ng-click="hideMenu(); query.id = item.id">
{{item.id}}
</li>
</ul>
</div>
My issue is that when the value is assigned to the text box, the list is momentarily filtered to the one option selected (because the text box is also the source of the ng-repeat filter), before hiding the menu. What I want id for the menu to be hidden without being refreshed with the filter first.
It should be noted that this only occurs when using CSS transitions which I am using to fade the menu out.
Here is a plnkr to illustrate.
Here's a working Plnkr. I basically gave your menu time to finish its animation before setting the value. Relevant code is as follows:
$scope.selectItem = function(id){
$scope.isActive = false;
$timeout(function(){
$scope.query.id = id;
}, 250);
}
...and the HTML using the newly created selectItem method:
<div class="xtab-typeahead" ng-controller="xTabTypeAheadCtrl">
<input type="text" class="xtab-typeahead-search" placeholder="{{type}}" ng-model="query.id" ng-focus="showMenu()" ng-init="query.id = undefined" />
<button ng-click="toggleMenu()">Show/Hide</button>
<ul class="xtab-typeahead-menu" ng-class="{true:'active',false:''}[isActive]">
<li ng-repeat="item in menuItems | filter:query"
ng-click="selectItem(item.id)">
{{item.id}}
</li>
</ul>
</div>

Resources