I want to display a dropdown within a table shown using ng-repeat. The dropdown is built using Foundation's dropdown.js stuff.
<tr ng-repeat="lead in leads | filter:filterText>
<td>
<input type="text" data-dropdown="dropdown-{[{lead.id}]}"
autocomplete="off"/>
<ul id="dropdown-{[{lead.id}]}" class='f-dropdown' data-dropdown-content>
<li>Dropdown List</li>
</ul>
</td>
</tr>
When I put the input + ul outside of the ng-repeat (minus the added lead.id to define the ID) it works fine, but when it's inside the ng-repeat Foundation throws this error:
Uncaught TypeError: Cannot read property 'is_hover' of undefined
on line 46 when hovering over, line 53 when hover out, and line 31, when clicking of foundation.dropdown.js.
I'm 100% sure this has to do with the fact that Foundation gets initiated before the Angular.js app gets initiated. I'm temporarily working around this by adding data-dropdown-init manually to the dropdown input, but I don't think that's pretty.
Any direction would be welcome.
Here's a plunkr imitating the problem: http://plnkr.co/edit/fyTcPX17Fkbe8hSlUMtb?p=preview
One pretty easy solution is to use Angular-Foundation though it's fairly opinionated about how you implement things.
This error happens since the foundation dropdown function initiates before the angular app initiates. The one workaround to prevent this error is add the HTML attribute after angular app started. Just modify
data-dropdown-content
to
ng-attr-data-dropdown-content="{{$index}}"
I had the same issue and this one solved it
Related
I got an old angular js application and my mission is to fix accessibilty problems. I have a table that includes radio buttons within the cells and I need to navigate between them using the arrow up and down keys.
I already have a method that deals with this issue and its working fine until i test it using screen reader (NVDA)
What happens is for some reason the SR cause the method to be ignored
and causes the table to lose its focus.
the only way that I managed to make it work is by setting the table with role="application".
but from what I have been reading so far it is wrong to use it in this case
This is a sample of one of the cells :
<td class="scheduleLineCell" style="text-align: center;">
<input type="radio"
class="btnRadio ng-valid ng-not-empty ng-touched ng-dirty"
aria-describedby=""
value="126" data-ng-model="selectedIdList[childSchedule.gridIndex]"
data-ng-key-press="scheduleKeyPress"
data-ng-grid-index="0"
xng-focus="isFocusOnStationButton == false &&
isFocusOnMapButton == false && ScheduleLine.Id ==
selectedIdList[search.currentScheduleGridIndex]" name="2096">
</td>
Can you make a working example on here or on JSfiddler?
Off the top of my head I can say this.
You should not put controls in tables or uses tables for design purposes.
a. If you have an enter data row make it from "div"s
b. Remember screen readers repeat table headers a lot!
JAWS and NVDA does mess with a screens JSEvents and get us a example page to help
(AngularJS) Refactor the control back to a component or directive and see if that helps.
a. e.g.
<custom-radio-button ng-value="val" aria-checked="true"></custom-radio-button>
I am writing a tree control using Angular2 and ng2-dragula (based on dragula). I am currently using something very similar to the example nested repeat example here. I have no problem loading in my list and getting drag and drop to work as expected. What I need to do is click a button, go back to the http service get fresh data, then update data on page. I know that I can use javascript to find the id and update that way but it doesn't seem like the correcy way to handle it.
Here is my component code - All this does is just over write the view data and completey undo any drags changed etc (im sure that is by design). I have tried a bunch of different different ways to use dragulaModel, but no matter what the whole component is re-rendered no matter what happens. I need to be able just to update the child text
I'm new to angular and want to make sure i follow the correct patterns
item.component.ts
loadItems(){
this._itemsService.getIems();
}
reloadIems(){
this._itemsService.getItems();
}
item.component.html
<div *ngIf="items">
<div class="holder">
<div *ngFor="let item of items | async">
<div (click)="checkCollapsed(item.text)" >
<div *ngIf='item.children' [dragula]='"first-bag"'>
<div *ngFor='let child of item.children' class="item">
<span class="handle">+</span><span id='{{child.id}}' [innerHtml]="child.text"> </span>
</div>
</div>
</div>
</div>
</div>
</div>
Edit
If I add a .subscribe to loadItems() then update this.items manually like this.items[0].children[0].text = "1000" in reloadItems() it works as i would like. Should I be manually updating the whole object this way? Seems like a hack
**Edit 2 **
I managed to get it to work by subscribing in the loadItems() then comparing the 2 objects in reloadItems, then making any necessary changes there. I think due to the subscribe it is autoupdating. Can anyone confirm if im doing it wrong/right (working plnkr here, leaving out the angular dependencies)
I have a simple jsfiddle using the Angular Drag and Drop module.
What I want: on the left, a list of cards. Each of them is draggable. On the right, a drop area. Upon drag-drop, the element is cloned and added to the ctrl.program list. So far, so good.
The problem: I must be able to reorder and remove element from the right area (i.e. the program array). I tried multiple solutions, none of them work. Ideally, an element is removed when it is dropped outside of the drop area (i.e. the right column). For now, I simply use a button
<button class="btn" ng-click="remove(ctrl.program, $index)"> remove </button>
$scope.remove = function(array, index){
array.splice(index, 1);
}
But it throws
Error: cannot call methods on draggable prior to initialization; attempted to call method 'destroy'
Any idea how to perform a remove smoothly ?
Ok, if anyone gets the same problem, here is the answer.
From this issue,
inserting the script jquery.ui.js after angular.js cause the issue in 1.3 but not 1.2. Specially if the drag or drop directive is used with ngRepeat. On removing the element by $animate.leave , the drag or drop plugin get destroyed by the 'remove' event before the $destroy event.
I inserted jquery.ui.min.js before all the angular scripts and it works perfectly.
I was trying to achieve something like Quora's read on feature where when expanded more content will be displayed.
I am using ng-bind-html binding an html page into P element.
<p ng-show="viewModel.level==0" ng-bind-html="viewModel.content0 | sanitize">
<p ng-show="viewModel.level==1" ng-bind-html="viewModel.content1 | sanitize">
the expanding works fine, but when collapse from level 1 to 0 (more content to less), the html page went into blank stuck there until you click or drag the page.
how to avoid that ?
I get the answer by accident.
what I need is a notification that the list size has changed:
$scope.$broadcast('scroll.resize');
I am currently learning AngularJS and already started a little project, which is basically an older project of mine, done in jQuery.
Everythings fine so far, but the last hours I wrapped my head around this area. In jQuery back then 5 minutes, but I have no idea what's the best way in AngularJS)
Here is my jQuery: A calendar view. It opens and closes days on click. Once a day is clicked it gets the class opened. Also there is the state locked, where I disable to open the day at all.
$('.mod-item').on('click', function(){
if ($(this).find('.mod-item-day').not('.locked')) {
if($(this).find('.mod-item-day').hasClass('open')){
$(this).find('.mod-item-day').removeClass('open').addClass('opened');
}else{
$(this).find('.mod-item-day').addClass('open');
}
}
});
Here is the markup:
<ul class="mod">
<li class="mod-item">
<div class="mod-item-day opened"><span>1</span></div>
<div class="mod-item-content">
<img src="../images/present1_late.jpeg" alt="">
</div>
</li>
So my question is - what's the most AngularJS way to do it?
You do this basically the way shown in the To Do example on the Angular website.
On the day's div, specify ng-click="callbackInYourScopeCode()". In the To Do example, it's ng-click="archive()"
On the day's div's class, include a property from your model. In the To Do example, for instance, there's <span class="done-{{todo.done}}">{{todo.text}}</span>. Note the property todo.done.
In your scope code, have the function (callbackInYourScopeCode) change your model's property (done in the To Do example).
Angular will call your scope code in response to a click, and then update the element based on changes to your model.