How to pass $index as a object key in ng-repeat? - angularjs

I am facing a problem with angular where i have a dynamic generated object in the form below
object:{
0: [],
1: []
}
This is set in the angular controller so in the html side i want to do this
<tr ng-repeat="comapny in companies">
<td ng-repeat="option in object.$index">{{option.name}}</td>
</tr>
$index comes from the tr ng-repeat that wraps the ng-repeat with $index variable.
Is this even possible?

If you really have an object like this you can simply access the array by
option in object[$parent.$index]
You need to use $parent.$index because you want to access the $index of the first ng-repeat.

Objects don't have an index... the correct syntax for ngRepeat with objects is (k, v) in obj - so you can do:
<tr ng-repeat="(id, options) in companies">
<td ng-repeat="option in options">{{option.name}}</td>
</tr>

Related

how to iterate json data using ng-repeat in angularjs

how to iterate json data using ng-repeat in angularjs
{
"CSS Corp":{
"COE":{"win_loss":[6,4]},
"YNOS":{"win_loss":[5,5]},
"ESTEE":{"win_loss":[10,0]},
"ELC":{"win_loss":[8,2]}
},
"SSSPL":{
"PEG":{"win_loss":[0,10]},
"ARUBA":{"win_loss":[2,8]},
"SALES":{"win_loss":[1,9]},
"MARKETING":{"win_loss":[7,3]}
},
}
Your question is very broad. You will first have to attach those JSON data to the scope of your controller and expose it to the template through a variable myData. Assuming you know how to do that, the use of ng-repeat becomes very trivial (add more columns or rows to fit your dataset):
<table>
<thead>
<tr><th>Header 1</th></tr>
</thead>
<tbody>
<tr ng-repeat="item in myData">
<td>{{ item }}</td>
</tr>
</tbody>
</table>
Use ng-repeat
Syntax : <tr ng-repeat="value in container">
Assuming that you have a array of JSON object in your JS as below,
var arrayObject = [
"CSS Corp":{
"COE":{"win_loss":[6,4]},
"YNOS":{"win_loss":[5,5]},
"ESTEE":{"win_loss":[10,0]},
"ELC":{"win_loss":[8,2]}
},
"SSSPL":{
"PEG":{"win_loss":[0,10]},
"ARUBA":{"win_loss":[2,8]},
"SALES":{"win_loss":[1,9]},
"MARKETING":{"win_loss":[7,3]}
}
];
Then your view should iterate as below,
<div ng-repeat="company in arrayObject">
{{company}} // use whatever you want to print
</div>

AngularJS and Laravel Foreach

I do have a problem with using Angular with Laravel's foreach loop, i tried to be as detailed as possible :)
<div style="padding:15px;" id="table-scroll" ng-app>
<table class="table table-responsive tblProducts" id="tblProducts">
<thead>
<tr>
<th>Description</th>
<th>Prices</th>
<th></th>
<th></th>
<th>Action</th>
</tr>
</thead>
<tbody>
//foreach loop here
</tbody>
</table>
</div>
this is my foreach loop
#foreach($products as $product)
{{ $product->product_description }}
product_price }}" ng-model="price">
#{{price*qty}}
#endforeach
Problem:
-When I use "ng-model" the prices/quantity are not displayed, but when i use "ng-bind" the prices/quantity are displayed but the subtotal column displays NaN (i have no idea why).
Flow:
-Each row of that table displays a list of grocery items, when the checkbox is clicked, it means that the item is selected and transferred to another table for calculating the grandtotal.
Reference:
https://ibb.co/hCddLv (snap from list of grocery items)
https://ibb.co/e0jk0v (when that product is transferred, this happens)
*im using "ng-bind" to display the price and quantity...
Thanks for the answer in advance guys...
I have updated this with my controller code in laravel
public function create()
{
$rooms = Room::where('status','=',0)->orderBy('room_length_of_stay')->get();
$products = DB::table('classifications')
->join('products', 'classifications.id', '=', 'products.classification_id')
->select('classifications.*', 'products.*')
->get();
//$scope.products = $products;
return View::make('frontdesk.transactions.create', ['rooms' => $rooms, 'products'=>$products]);
}
ng-model works by using a property on the scope to read/write a value as an input changes so you can't just assign it some value hence the problem. Ideally I only use Angular for the front end and template handling and would do the looping with an ng-repeat over an array that is retrieved in JS from the backend (could be laravel based but would keep it just serving JSON data not doing anything with the view, lumen is good for this). In the short term you can just set the value attribute on the input that would be the most direct way to put your data into the form that may not work with ng-model though (assuming you pointed that at some JS property) since it's expected the ng-model will be used for reading/writing the value.
Instead of using the foreach in blade use a ng-repeat directive. Get the data in the foreach in a json and iterate it in the template.
Before the render of the angular controller make a script:
<script>
var products = "{{ json_encode($products) }}";
</script>
Then in the controller store it as:
$scope.products = products;
Then iterate it:
<p ng-repeat="product in products">
#{{ product.product_description }}
#{{ product.price*product.qty}}
</p>

$index always 0 when using ng-bind-html

I have a directive that contains this markup
<tr ng-if="isComplete()" ng-repeat="row in paged.page() track by $index" ng-click="rowClick(row, $event)" ng-class="assignRowClass(row)">
<td ng-repeat="header in headers" ng-bind-html="trustAsHtml(header.formatter(row[header.property], row, $index))"></td>
</tr>
The problem is that $index is always 0 when passed to the header.formatter function.
try this
<tr ng-if="isComplete()" ng-repeat="(index,val) in paged.page() track by index" ng-click="rowClick(val, $event)" ng-class="assignRowClass(val)">
<td ng-repeat="header in headers" ng-bind-html="trustAsHtml(header.formatter(val[header.property], val, index))"></td>
As saw in my comment this works
$parent.$index
This is because of the new scope created by ng-if and the limit of inheritance between scope in angular (because of javascript limits).
You can either go for $parent.$index of move the ng-if to the upper DOM Element if possible (<thead> / <tbody).

ng-repeat or ng-options How can I automatically select the last row in a table ?

How I can I automatically select the last row in a table
ng-repeat="unit in selectedOrder.products" using something like select by track by $index == desc or alternatively ng-options
<div class="search" ng-show="selectedOrder">
<table class="table table-bordered">
<tr><th>Item</th><th>Name</th><th>ValueToday</th></tr>
<tr ng-repeat="unit in selectedOrder.products">
<td><img ng- src="http:images/thumbnails/{{unit.shortname}}_tn.jpg" width=40 height=40
alt="{{ unit.shortname | limitTo: 18}} Photo"></td>
<td>{{unit.name | limitTo:18 }}</td>
<td>{{unit.valuetoday| currency:"£"}} </td>
</tr>
</table>
<div class="search" ng-show="selectedOrder">
<table class="table table-bordered">
<tr><th>Item</th><th>Name</th><th>ValueToday</th></tr>
<tr ng-repeat="unit in selectedOrder.products" ng-if="$last">
<td><img ng- src="http:images/thumbnails/{{unit.shortname}}_tn.jpg" width=40 height=40
alt="{{ unit.shortname | limitTo: 18}} Photo"></td>
<td>{{unit.name | limitTo:18 }}</td>
<td>{{unit.valuetoday| currency:"£"}} </td>
</tr>
</table>
will give you only the last row selected
In ng-repeat you can use the $last special variable to apply something only if it's the last element. see: https://docs.angularjs.org/api/ng/directive/ngRepeat
you can use it as a condition for anything you want to do in the tag. like
<img class="{{$last ? 'selected'}}" ng-class="{'selected': $last}" ng-if="$last" ....>
or however you like (these are just examples)
Always keep in mind though that using angular means that you have to edit your model to apply changes to your view, so if you want to have an element selected you have to do something to your model so that the element contains a value that makes it selected and then your view should reflect this.
For example in your controller you can check which element is the last in your ng-repeat array and add a selected variable, then in your view do something to make it look like your element is selected (for example: ng-class="{'selected': element.selected}") otherwise, by working on the view only you can make it look like the element is selected using $last but it won't be really selected in your model
In fact In ng-options (so we are talking about a select) you have to change your model in order to reflect your choice. So for example if your select has an attribute like this: ng-model="selected" then in your controller you set the $scope.selected variable to the last element of the array containing the values for your ng-options
You could use something like ng-if="$index == $last"

How to sort table by value using ng-if?

I'm a novice at AngularJS and trying to get my table to only show the rows that have a 'color' value of true when the user selects the 'Color Only' item from the Sort By drop down menu.
Here's my sort menu code:
<label>Sort By:</label>
<select ng-model="orderProp">
<option value="title">Title</option>
<option value="filename">File Name</option>
<option value="class">Classification</option>
<option value="color">Color Only</option>
</select>
Here is my table code:
<table>
<thead>
<tr>
<th>Classification</th>
<th>Title</th>
<th>File</th>
<th>Color</th>
</tr>
</thead>
<tbody>
<tr ng-animate="'animate'" ng-repeat="item in filtered = (pptData | filter: query | orderBy: orderProp)">
<td>{{item.class | uppercase}}</td>
<td>{{item.title}}</td>
<td>{{item.filename}}</td>
<td>{{item.color}}</td>
</tr>
</tbody>
</table>
I tried adding ng-if="color"to the ng-repeat directive but that did not work. Live link here.
Use
ng-if="orderProp !== 'color' || item.color"
on your ng-repeat element.
As you should know, when you refer to a property in an Angular directive expression, the property is resolved against the current $scope. ng-repeat creates a child scope for every iteration. When you specify ng-repeat="item in collection", you can then reference that child scope via the property item.
The color property is on that item child scope, not on the outer scope. Thus, saying ng-if="color" will result in none of the rows being rendered, because $scope.color is undefined. ng-if="item.color" will resolve against the item scope, and the row will only be rendered if item.color is defined.
However, if you only want to filter out those rows when the user has selected the color filtering option, you need to make sure you check the orderProp. Thus,
ng-if="orderProp !== 'color' || item.color"
gets the behavior you are looking for.
I suspect you will want to continue to do more complex filtering on these rows as you develop the code. In that case, I would recommend instead writing a function in your controller:
$scope.shouldShowRow = function(row, index) {
var show = $scope . orderProp !== 'color" || row.color;
// more logic for determining show/hide here
return show;
}
And then in your template:
<tr ng-repeat="item in (pptData | filter: query | orderBy: orderProp)"
ng-if="shouldShowRow(item, $index)">
<!-- your row markup here -->
</tr>
$index is a handy value that ng-repeat creates. You may not need it, but it might be useful.
As a suggestion, you should look into the controllerAs syntax. It requires you to name all of your controllers' scopes, and will help you keep track of what scope you are using when:
<div ng-controller="MyController as my">
...
<tr ng-repeat="item in (my.pptData | filter: query | orderBy: my.orderProp)"
ng-if="my.shouldShowRow(item, $index)">
...
</tr>
</div>
ControllerAs:
http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/

Resources