ng-repeat over a div not working - angularjs

I have used ng-repeat numerous times already in the past, but for some reason I cannot yet understand why it is not on the following situation:
I have an array of objects called registers which I am referencing on the ng-repeat but nothing happens.
I know the array is populated because I have seen it on numerous console.log and because it works if I move the ng-repeat over to the <tbody>
<div ng-repeat = "r in registers">
<!-- START HEADER -->
<tbody class="js-table-sections-header">
<tr>
<td class="text-center">
<i class="fa fa-angle-right"></i>
</td>
<td class="font-w600">Denise Watson</td>
</tr>
</tbody> <!-- END HEADER -->
<tbody>
<tr>
<td class="text-center"></td>
<td>
<!-- Summernote Container -->
<div class="js-summernote-air">
<p>End of air-mode area!</p>
</div>
</td>
</tr>
</tbody>
<!-- END TABLE -->
</div>
I was hoping someone could tell me if there is something I may be ignoring.
Thanks in advance.

I think I just ran into this same problem. It stems from <div> not being a valid elment within a <table>.
I'm guessing that since you have <tbody> there, that there is a <table> tag that was left out of your snippet. <div>s aren't allowed in a table, so the browser moves it before the table. In my situation, doing this, causes the angular scope to change so that there was nothing to iterate over. You can verify this by using the developer tools of your browser.
So, my guess is that you probably want to move the ng-repeat onto the <tbody> or <table> tag.

If you want to use ng-repeat in "div" tag means use "span"
inside div tag. instead of using "table" and its sub attributes..
else use your ng-repeat inside "table" or "thead" or "tr" also
it will iterate rows ...
than only ng-repeat will works.

Related

ng-repeat directive doesn't work on <tr> / table row element

I am trying to use the ng-repeat directive to create table rows with a list of campaign names.
However, I am not able to get any results, though I am still able to see one of the children of the array displaying correctly.
Here is my view code:
<div class="modal-body">
<p>{{$ctrl.contact.Campaigns[0].CampaignName}}</p>
<tr ng-repeat="campaign in $ctrl.contact.Campaigns">
<label>
{{campaign.CampaignName}}
</label>
</tr>
</div>
I can successfully see the paragraph element above and it shows the expected data, but not the table row elements.
I don't see any errors in the browser console.
How can I make the ng-repeat directive work in the code above?
The problem was that the <tr> / table row element didn't have a parent <table> element containing it.
This is solved by simply adding in table tags around the orphaned <tr> element:
<div class="modal-body">
<table>
<tr ng-repeat="campaign in $ctrl.contact.Campaigns">
<label>
{{campaign.CampaignName}}
</label>
</tr>
</table>
</div>

Building multiple dynamic tables with ng-repeat in angularjs using template

I am trying to achieve the following in angualrjs:
I have multiple information lines, that each can be clicked regardless of the others.
When I click on a line, a div is opened and a table is shown in regarding that line.
My html now looks like this:
<div ng-app="TModule" ng-cloak>
<div class="myDiv" ng-controller="tController as tCtrl">
<h1>Title</h1>
<ul>
<li ng-repeat="option in tCtrl.availableOptions" ng-click="tCtrl.toggleOpen(option.id)">
<div>
<h2>{{option.name}}</h2>
<div ng-show="isOpen(option.id)">
//Table should go here
</div>
</div>
</li>
</ul>
My table template is the same for all lines and should look like this:
<table>
<thead>
<tr>
<th>Header I</th>
...
</tr>
</thead>
<tbody>
<tr ng-repeat...>...</tr>
....
</tbody>
</table>
What I want to happen with clicking on any li item, that it will call a function on the controller which will make an ajax call, and fill the table using a template, with the results receive.
My problem is that I don't know how to fill each table with the same template and to have different information (without using array that will store each information)
Not sure if it is possible in angular and what will be the best way to achieve this?
Each line can be opened together and each line has a different set of information.

Ng-click does not work outside of my tr tag AngularJS

I am working on an app and I cant seem to figure out why my ng-click only works inside of my (single) tr tag but as soon as I put it into another tr tag it stop working. Keep in mind it was working before I used the ng-repeat within the first tr tag. Here is what my code looks like, any advice would greatly help!
<table>
<tbody>
<tr>
<td ng-click="commentOpen = !commentOpen">
<div class="iconsize">Comment Closed</div>
</td>
<td ng-click="switchOpen = !switchOpen">
<div class="iconsize">Switch Closed</div>
</td>
</tr>
<tr>
<td>
<div ng-show="commentOpen == true">
<textarea>Comment Open</textarea>
</div>
<div ng-show="switchOpen == true">
<p>Switch On</p>
</div>
</td>
</tr>
</tbody>
</table>
I had the ng-repeat on the tag which was causing my ng-click to not fire. I ended up moving my ng-repeat to the tbody and the ng-click and ng-show started working again.
ngRepeat creates new scopes for its children, it just usually seems like it's accessing the same scope because this new scope inherits from its parent.
Meaning, commentOpen is actually referring to a property on the wrong scope.
Below are three potential ways for you to fix this:
1) controller as, and always refer to the controller you're after by name
2) $parent.commentOpen (Don't do this! It becomes very confusing as you nest)
3) Instead of commentOpen and switchOpen, you can use an Object (e.g. $scope.openControls = { comment: false, switch: false }, and then in the td tags you would write something like ng-click='openControls.comment = !openControls.comment'). This way it's passed inherited by reference (where as a boolean would be by value), and keeps synced.

AngularJS: How to call function on last iteration of ng-repeat?

I am trying to figure out how to call a function on the last iteration of an ng-repeat? I am using nested ng-repeats to display results in table format and would like to call a function after all the table cells are loaded.
I was trying to do something like this:
<tr ng-repeat="(rowIndex, rowResults) in chunkedResults">
<td ng-repeat="result in rowResults">
<canvas id="item{{rowIndex}}{{$index}}"></canvas>
<div>Canvas{{rowIndex}}{$index}}</div>
</td>
<div ng-if="$last" ng-init="loadCanvases()"></div>
</tr>
But with nested ng-repeats this does not seem to work. When there is only one ng-repeat present like so:
<tr>
<td ng-repeat="result in rowResults">
<canvas id="item{{$index}}"></canvas>
<div>Canvas{$index}}</div>
<div ng-if="$last" ng-init="loadCanvases()"></div>
</td>
</tr>
Then the function gets called on the last iteration as it should.
Any ideas why?
Add condition in your ng-init
<td ng-repeat="result in rowResults">
<canvas id="item{{$index}}"></canvas>
<div>Canvas{{$index}}</div>
<div ng-if="$last" ng-init="$last?loadCanvases():null"></div>
</td>
You can create a directive and place it in your "last" div :
<td ng-repeat="result in rowResults">
<canvas id="item{{$index}}"></canvas>
<div>Canvas{{$index}}</div>
<div ng-if="$last" data-onlast></div>
</td>
and then execute your own logic in your custom "onlast" directive.
(ng-init is only supposed to be used at the same level as ng-repeat, though you could make it work)
You're probably not approaching your problem the right way.
If you want to execute code once the DOM contains all the list elements (for instance you want to get the pixel height of your element), you can simply do it after a $timeout. This will ensure the previous angular digestion is done and everything is on place in the DOM.
$timeout(function() {
// Here execute anything you want after the list is loaded
});

How to get Angular to update the Ui from within the controller

I have the following html.
<div ng-controller="CustCtrl">
<table class="table table-condensed">
<thead>
etc.
</thead>
<tbody>
<tr ng-repeat="customer in customers" data-cust-id="{{customer.Id}}">
<td>
<button ng-model="Id" tracking-{{customer.Tracking}} ng-click="startTrackingCustById(customer.Id)">
</button>
</td>
etc.
</tr>
</tbody>
</table>
So the button has a class that is databound to the customer.Tracking value which is either true or false. When the button is clicked the startTrackingCustById() method is successfully called and the customer object in the customers object is successfully changed like customer.Tracking = true.
But the buttons class is not updated. What am I missing?
Look at using ng-class . For a boolean value in scope you would use:
ng-class="{'classNameToAddIfTrue':customer.Tracking}"
In the CustCtrl I wrapped the call that updated the customers array like this
$scope.$apply($scope.customers[i].Tracking = true);
Based on the suggestion in an answer I will link to when I find it that basically said "If you are having trouble updating the view you most likely need to use $scope.$apply
So that get's it to work. Now I need to figure out why and how.

Resources