AngularJS access another array with $index under ng-repeat - angularjs

I new to AngularJS and wish to access two arrays under ng-repeat. This is my code:
<tr ng-repreat="find in findOptions">
<td>find.first</td>
<td>find.second</td>
<td>{{ search[{{$index}}].third }}</td>
</tr>
search is another array that I want to access here

You can't have iterpolation inside a intepolation again, basically you could access scope variable directly inside it.
You could simply directly use $index to access array.
search[$index].third

Created JSFiddle Demonstration - https://jsfiddle.net/qtksp1kj/
Hope this will help!
<body ng-app="SampleApp">
<table ng-controller="fcController" border="1px">
<thead>
<tr>
<td>Name</td>
<td>Address</td>
<td>LandMark</td>
</tr>
</thead>
<tbody ng-repeat="element in myArray">
<tr>
<td>{{element.name}}</td>
<td>{{element.address}}</td>
<td>{{myArray1[$index].landMark}}</td>
</tr>
</tbody>
</table>
</body>
var sampleApp = angular.module("SampleApp", []);
sampleApp.controller('fcController', function($scope) {
$scope.myArray = [{
'name': 'Name1',
'address': 'H-1 China Town'
}, {
'name': 'Name2',
'address': 'H-2 China Town'
}];
$scope.myArray1 = [{
'landMark': 'Near Dominos'
}, {
'landMark': 'Near Airport'
}];
});

Related

AngularJS recursive templates using tables

I am trying to work out how to do recursion using table tags with angularjs. I have the following data structure
$scope.report = [{
'Name': 'Moo',
'Value': 'MooV',
'Children': [{
'Name': 'Moo2',
'Value': 'Moo2V',
'Children': [{
'Name': 'Moo3',
'Value': 'Moo3V'
}]
}]
}];
The recursion can have no limit. I am looking to put in a simple table with the format
<table>
<tr>
<td>Moo</td>
<td>MooV</td>
</tr>
<tr>
<td>Moo2</td>
<td>Moo2V</td>
</tr>
<tr>
<td>Moo3</td>
<td>Moo3v</td>
</tr>
<table>
but I am unable to get it working just right. This will allow me to do certain things to the sections while looking flat to the user. Currently I have the code
<div ng-app="app" ng-controller='AppCtrl'>
<script type="text/ng-template" id="rloop">
<td>{{data.Name}}</td>
<td>{{data.Value}}</td>
<tr ng-repeat="data in data.Children" ng-include src="'rloop'"></tr>
</script>
<table class="table table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="data in report" ng-include="'rloop'"></tr>
<tr ng-repeat-end></tr>
</tbody>
</table>
</div>
but this is not going to work due to in repeating it creates a tr tag within a tr tag. I have tried various different methods of moving the repeat to tbody etc etc but I can't seems to get it working due to the restrictions of tables in HTML. Example, is not allowed within tr.
JSFiddle showing issue here: JSfiddle
As you say, this is not going to work within the table. Maybe it would be better to recursively convert the data to an array of Name/Value pairs, then use those in the normal way?
var app = angular.module('app', []);
function includeChildren([first, ...rest]) {
if (!first) return [];
const {Name, Value, Children = []} = first;
return [{Name, Value}, ...includeChildren(Children), ...includeChildren(rest)];
}
app.controller('AppCtrl', function ($scope) {
$scope.report = [{
'Name': 'Moo',
'Value': 'MooV',
'Children': [{
'Name': 'Moo2',
'Value': 'Moo2V',
'Children': [{
'Name': 'Moo3',
'Value': 'Moo3V'
}]
}]
}];
$scope.reportTable = includeChildren($scope.report);
// $scope.reportTable now contains:
// [{Name: 'Moo', Value: 'MooV'}, {Name: 'Moo2', Value: 'Moo2V'}, {Name: 'Moo3', Value: 'Moo3V'}]
});
Now you can use a more unsurprising template:
<div ng-app="app" ng-controller='AppCtrl'>
<table class="table table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="data in reportTable">
<td>{{data.Name}}</td>
<td>{{data.Value}}</td>
</tr>
</tbody>
</table>
</div>
See it working here: https://jsfiddle.net/k6rf9g1p/1/

ng-click, ng-model not working in angularjs datatable

I have a datatable with column filters made with AngularJS.
Here is the HTML:
<body ng-app="myApp" ng-controller="appController as Ctrl">
<table class="table table-bordered table-striped table-hover dataTable js-exportable" datatable="ng" dt-options="Ctrl.dtOptions" dt-columns="Ctrl.dtColumns">
<thead>
<tr>
<th></th>
<th>Name</th>
</tr>
</thead>
<tfoot>
<tr>
<th></th>
<th>Name</th>
</tr>
</tfoot>
<tbody>
<tr ng-repeat="user in userList">
<td>
<input type="checkbox" id="user-{{ $index }}" ng-model="Ctrl.checkboxValue[$index]" ng-click="Ctrl.checkValue(user.id)" ng-true-value="{{user.id}}" />
<label for="user-{{ $index }}"></label>
</td>
<td>
<a href="#">
{{ ::user.name }}
</a>
</td>
</tr>
</tbody>
</table>
Here's the script:
angular.module('myApp', ['ngAnimate', 'ngSanitize', 'datatables', 'datatables.columnfilter'])
.controller('appController', function($scope, $compile, DTOptionsBuilder, DTColumnBuilder){
$scope.userList = [
{
id: '1',
name: 'hello'
},
{
id: '2',
name: 'hi'
}
];
var vm = this;
vm.dtOptions = DTOptionsBuilder.newOptions()
.withPaginationType('full_numbers')
.withOption('createdRow', function (row, data, dataIndex) {
$compile(angular.element(row).contents())($scope);
})
.withColumnFilter({
aoColumns: [{
}, {
type: 'text',
bRegex: true,
bSmart: true
}]
});
vm.dtColumns = [
DTColumnBuilder.newColumn('').withTitle(''),
DTColumnBuilder.newColumn('name').withTitle('Name'),
];
vm.checkboxValue = [];
vm.checkValue = function(id){
console.log(id);
}
});
Issues:
id of the user does not get passed to checkValue function. Hence, the console.log is undefined.
Suppose if the checkbox of 1st user is checked, the value of checkboxValue array is [undefined: '1']. If checkbox of 2nd user is checked the value of checkboxValue array becomes [undefined: '2'].
Only one checkbox gets checked. Why is that?
Demo: https://plnkr.co/edit/A3PJfBuwtpUQFAIz8hW7?p=preview
You kill your code with redundancy. Look at this :
When using the angular way, you CANNOT use the dt-column directive.
Indeed, the module will render the datatable after the promise is
resolved. So for DataTables, it's like rendering a static table.
You are in fact using the "angular way" along with dt-columns. You could switch to use DTColumnDefBuilder but why define the columns when you already have a <thead> section? It would only make sense if you need to use sorting plugins etc on specific columns. And / or not is specifying the header in the markup.
Moreover, when you are rendering with angular it is not necessary to $compile anything, in fact is is very wrong, angular already does that. So
remove your dt-columns or replace it with a dt-column-defs literal
remove your $compile from the createdRow callback
Then it works. I would also remove the ng-true-value="{{user.id}}" attribute. You want an array representing the checkboxes state, why set the state to the user.id and not true or false?
vm.dtOptions = DTOptionsBuilder.newOptions()
.withPaginationType('full_numbers')
.withColumnFilter({
aoColumns: [{
}, {
type: 'text',
bRegex: true,
bSmart: true
}]
});
and
<input type="checkbox" id="user-{{ $index }}" ng-model="Ctrl.checkboxValue[user.id]" ng-click="Ctrl.checkValue(user.id)" />
Is really all you need.
forked plunkr -> https://plnkr.co/edit/Z82oHi0m9Uj37LcdUSEW?p=preview

handling arrays in ng-repeat

I have a table and I need to display values in table from my JSON response. But I am unable to fetch the datas inside array.somewhere I am missing something.
JSON:
var jobs = [
{"id":1,"title":"Need comedian","company":"AMS","description":"Need comedian"},
{"id":2,"title":"Need Actor","company":"ERS","description":"Actor for Romantic Movie"}
]
HTML:
<tr ng-repeat ="item in jobs">
<td>{{item.jobs.title}}</td>
<td>{{item.jobs.description}}</td>
</tr>
You need to use $scope:
$scope.jobs = [{"id":1,"title":"Need comedian","company":"AMS","description":"Need comedian"},{"id":2,"title":"Need Actor","company":"ERS","description":"Actor for Romantic Movie"}]
<tr ng-repeat ="item in jobs">
<td>{{item.title}}</td>
<td>{{item.description}}</td>
</tr>
Hope it helps =)
There are two issues,
(i)You need to use $scope variable
(ii)You need to access item.title not item.jobs.title inside ng-repeat
You should access item
<tr ng-repeat="item in jobs">
<td>{{item.title}}</td>
<td>{{item.description}}</td>
</tr>
DEMO
The jobs array needs to be in $scope.
$scope.jobs = [{"id":1,"title":"Need comedian","company":"AMS","description":"Need comedian"},{"id":2,"title":"Need Actor","company":"ERS","description":"Actor for Romantic Movie"}]
<tr ng-repeat ="item in jobs">
<td>{{item.title}}</td>
<td>{{item.description}}</td>
</tr>
Keep these things in mind while playing with ng-repeat :
You have to use $scope.jobs object instead of var jobs as an array declaration in the controller which you are going to pass in ng-repeat for binding.
When you are going to iterate the array inside ng-repeat="item in jobs" no need to use again jobs to access the property of the objects(item) of an array(jobs).
Working Demo :
var app = angular.module('myApp',[]);
app.controller('myCtrl',function($scope) {
$scope.jobs = [
{
"id":1,
"title":"Need comedian",
"company":"AMS",
"description":"Need comedian"
},
{
"id":2,
"title":"Need Actor",
"company":"ERS",
"description":"Actor for Romantic Movie"
}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<table>
<tr ng-repeat ="item in jobs">
<td>{{item.title}}</td>
<td>{{item.description}}</td>
</tr>
</table>
</div>

Sorting only certain arrays in nested ngRepeat

I currently have a nested ngRepeat, where the inner loop iterates over a collection of items from its parent. An excerpt:
<div ng-repeat="person in persons">
(Irrelevant code here.)
<table>
<tr>
<th ng-click="setItemOrder('name')">Item name</th>
<th ng-click="setItemOrder('number')">Item number</th>
</tr>
<tr ng-repeat="item in person.items | orderBy:itemOrder">
<td>{{item.name}}
<td>{{item.number}}
</tr>
</table>
</div>
By clicking the table headers, I set the itemOrder-property in my controller to the name of the property I want orderBy to use:
$scope.setItemOrder = function(order){
$scope.itemOrder = order;
}
This all works fine, except that if I click the headers in one person-div, the item-tables in all person-divs get sorted on that property.
Is there a way to make ngRepeat only apply orderBy to entries that match a certain criteria - for instance a certain index? Or should I use a different approach?
Try setting the property to respective person instance as follows:
angular.module('test', []).controller('testController', function($scope) {
$scope.persons = [{
items: [{
name: 'test',
number: 2
}, {
name: 'test1',
number: 1
}]
}, {
items: [{
name: 'test3',
number: 5
}, {
name: 'test4',
number: 4
}]
}];
$scope.setItemOrder = function(person, order) {
person.itemOrder = order;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<form ng-app="test" ng-controller="testController">
<div ng-repeat="person in persons">
<table>
<tr>
<th ng-click="setItemOrder(person,'name')">Item name</th>
<th ng-click="setItemOrder(person,'number')">Item number</th>
</tr>
<tr ng-repeat="item in person.items | orderBy:person.itemOrder">
<td>{{item.name}}
<td>{{item.number}}
</tr>
</table>
</div>
You could add a ordering variable for each person and extend setItemOrder with the person object. Then you can call:
setItemOrder(person, 'name');
and then use it in the ngRepeat:
orderBy:person.itemOrder
angular.module('test', []).controller('testController', function($scope) {
$scope.ordersort=true;
$scope.orderfield='number';
$scope.persons = {
"items": [{
"name": 'test',
"number": 2
}, {
"name": 'test1',
"number": 1
}],
"item1": [{
"name": 'test3',
"number": 5
}, {
"name": 'test4',
"number": 4
}]
};
$scope.setItemOrder = function(person, order) {
$scope.orderfield=order;
person.itemOrder = order;
$scope.ordersort= !$scope.ordersort;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<form ng-app="test" ng-controller="testController">
<div ng-repeat="person in persons">
<table>
<tr>
<th ng-click="setItemOrder(person,'name')">Item name</th>
<th ng-click="setItemOrder(person,'number')">Item number</th>
</tr>
<tr ng-repeat="item in person | orderBy:orderfield:ordersort">
<td>{{item.name}}
<td>{{item.number}}
</tr>
</table>
</div>
I have modified your example. In this example table sorting is working perfectly. But It is not sorted the particular table when I click on that table header. Anyway to sort columns by specific table?
angular.module('test', []).controller('testController', function($scope) {
$scope.persons = [{
items: [{
name: 'test',
number: 2
}, {
name: 'test1',
number: 1
}]
}, {
items: [{
name: 'test3',
number: 5
}, {
name: 'test4',
number: 4
}]
}];
$scope.setItemOrder = function(person, order) {
person.itemOrder = order;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<form ng-app="test" ng-controller="testController">
<div ng-repeat="person in persons">
<table>
<tr>
<th ng-click="setItemOrder(person,'name')">Item name</th>
<th ng-click="setItemOrder(person,'number')">Item number</th>
</tr>
<tr ng-repeat="item in person.items | orderBy:person.itemOrder">
<td>{{item.name}}
<td>{{item.number}}
</tr>
</table>
</div>

Dynamically setting new ng-model when pushing model to array

Can't figure out how to dynamically add a new model whenever a new row is added to the page. For example, the input select box ng-model= infos.rigBonusInfo.rigName is used for all select box I've added to the page. I would like to have a different model attached to a each select inputs. I tried using ng-model= infos.rigBonusInfo.rigName[rigBonus] but it doesn't work for the rates as the same model gets attachedto each rate field.
Pretty much what I want to do is to bind a new model whenever a new row gets pushed into the array.
Currently, I have a nested table which is the following:
<div class="col-lg-5">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Rig</th>
<th>Rig Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="rig in rigs">
<td>{{ $index + 1 }}</td>
<td>{{ rig.name }}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-lg-2"></div>
<div class="col-lg-5">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Bonus Name</th>
<th>Rate</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="bonus in create.rigBonusRates">
<td>{{ bonus.rateName }}</td>
<td>{{ bonus.rate }}</td>
</tr>
</tbody>
</table>
</div>
<table>
<thead>
<tr>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="rigDate in rigDateList track by $index">
<td><input ui-date="datepickerOptions" ng-model="date" /></td>
<td>
<table>
<thead>
<tr>
<th>Rig</th>
<th>Rate1</th>
<th></th>
<th>Rate2</th>
<th></th>
<th>Rate3</th>
<th></th>
<th>Rate4</th>
<th></th>
<th>Comments</th>
</tr>
</thead>
<tr ng-repeat="rigBonus in rigBonusList track by $index">
<td><select ng-options="rig as rigs.indexOf(rig) + 1 for rig in rigs" ng-model="infos.rigBonusInfo.rigName[rigBonus]" ></select></td>
#for (var i = 1; i < 5; i++)
{
<td><select ng-options="rigBonus.rateName for rigBonus in create.rigBonusRates" ng-model="infos.rigBonusInfo.rate#(#i)"></select></td>
<td><input type="text" ng-disabled="infos.rigBonusInfo.rate#(#i).rateName != 'Special' " ng-model=infos.rigBonusInfo.rate#(#i).rate /></td>
}
<td><input ng-model="info.rigBonusInfo.comments" /></td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
<div>
<button type="button" ng-click="add()">Add</button>
<button type="button" ng-click="addDate()">Add Date</button>
</div>
My current controller has the following:
angular.module('RigBonus').controller('rigCreateController', ['$scope', '$http', 'PayPeriodService', 'RigLegendService',
function ($scope, $http, PayPeriodService, RigLegendService, RigBonusRateService) {
$scope.rigs = RigLegendService.getRigLegend();
$scope.datepickerOptions = {
orientation: 'top',
startDate: PayPeriodService.getStartDate(),
endDate: PayPeriodService.getEndDate()
};
$http({ method: 'GET', url: '/Home/CreateData' }).success(function (data) {
$scope.create = data;
$scope.infos = {
rigBonusInfo: {
rigName: $scope.rigs[0],
rate1: $scope.create.rigBonusRates[0],
rate2: $scope.create.rigBonusRates[0],
rate3: $scope.create.rigBonusRates[0],
rate4: $scope.create.rigBonusRates[0],
comment: ""
}
};
$scope.add = function () {
$scope.rigBonusList.push();
};
$scope.addDate = function(){
$scope.rigDateList.push("");
};
});
$scope.rigBonusList = [$scope.rigBonusInfo];
$scope.rigDateList = [];
$scope.submit = function () {
$http.post('/Home/Create', {model: "testing"} );
};
}]);
I figured out my issue. My problem was that I was not sure how to generate a new object when a new row of controls are added. Think I should have put something on fiddleJS to help people visualize it better. As a static model was used ($scope.infos) as ng-model, the same model was used for two different controls which I don't want. I want all my controls to be unique.
The fix was to create the object I had in mind which is the following:
$scope.rigDateList = [{
date: "",
rigBonusList: [{}]
}];
So it is an array of objects where the object contains a date and another array of objects.
When I want to push new objects to the inside array which I didn't know I could just create objects like this at the time. I was trying to figure out a way to dynamically create new models ng-model could by declaring them in the controller. I use the following function:
$scope.rigDateList[$scope.rigListIndex].rigBonusList.push({
rigName: "",
rate1: "",
rate2: "",
rate3: "",
comments: ""
});
I also didn't know that I could use elements inside the array from ng-repeat. In the following case, it is rigBonus that I could have used as a model instead of infos model.
<tr ng-repeat="rigBonus in rigDate.rigBonusList track by $index">
<td><select ng-options="rig as rigs.indexOf(rig) + 1 for rig in rigs" ng-model="rigBonus.rigName"></select></td>
and when I want to push to the outside array I use the following:
$scope.rigDateList.push({
date: "",
rigBonusList: [""]
});
$scope.rigListIndex = $scope.rigListIndex + 1;
I use an index to keep track of which object I'm in.
A more closest question and answer is that:
Ng-repeat with dynamic ng-model on input not working
please, take a look.

Resources