How to populate a table with AngularJS - angularjs

I have a table:
<h4>Table of Results</h4>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Value</th>
<th scope="col">Sub-Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="object in results>
<td>{{object.field1}}</td>
<td>{{object.field2}}</td>
<td>{{object.field3}}</td>
</tr>
</tbody>
</table>
And I have a controller:
angular.module('app', [])
.controller("Ctrl",['$scope', function ($scope) {
$scope.BtnIndex;
$scope.results = [];
$scope.selectBtn = function (index, model1, model2) {
if (index == $scope.BtnIndex)
$scope.BtnIndex = -1;
else {
$scope.newItem = {
field1 : model2.name,
field2 : model2.val,
field3 : model1.name
}
$scope.results.push($scope.newItem);
}
};
I can't work out why the table is not populating with the data. I have checked the console and it is showing the data, as I expected, but it just isn't populating the table.
I'm expecting the answer to be right in front of me, but I can't see it.

You are not binding the results variable to the scope
Please change
results = [];
to this
$scope.results = [];
Here's the official information from Angular themselves
Scope is the glue between application controller and the view. During the template linking phase the directives set up $watch expressions on the scope. The $watch allows the directives to be notified of property changes, which allows the directive to render the updated value to the DOM.

This works - Plunker
JS
$scope.results = [];
$scope.selectBtn = function (index, model1, model2) {
if (index == $scope.BtnIndex)
$scope.BtnIndex = -1;
else {
$scope.newItem = {
field1 : index,
field2 : model1,
field3 : model2
}
$scope.results.push($scope.newItem);
}
}
Markup
<body ng-controller="MainCtrl">
<button ng-click='selectBtn("hello", "world", "today")'>Press me</button>
<h4>Table of Results</h4>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Value</th>
<th scope="col">Sub-Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="object in results">
<td>{{object.field1}}</td>
<td>{{object.field2}}</td>
<td>{{object.field3}}</td>
</tr>
</tbody>
</table>
</body>
It's not possible to see how you are calling $scope.selectBtn in your markup so I've created a simple example from your question.

Related

How to display array in table using ng-repeat

Unlike other JSON data , I have simple arrays of two.
$scope.land = [ elephant, tiger, zebra ];
$scope.water = [ fish , octopus, crab];
I want to put up the array in table using ng-repeat. I tried this but data is not showing in proper format.
<table class="table table-dark">
<thead>
<tr>
<th scope="col">LAND</th>
<th scope="col">WATER</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="l in land track by $index">
<td>{{l}}</td>
<td>fish</td>
</tr>
</tbody>
</table>
EDIT:-
err in data showing vertical in table
enter image description here
new data :-
$scope.land = [ 'tiger in zoo', 'tiger in jungle', 'zebra'];
$scope.water = [ 'fish in pond'];
I think you are trying to display elements of two arrays next to each other (correct me if i'm wrong).
Here is a simple way to do that :
angular.module('myApp', [])
.controller('TestCtrl', function ($scope) {
$scope.land = [ 'tiger in zoo', 'tiger in jungle', 'zebra'];
$scope.water = [ 'fish in pond'];
$scope.combined = [];
var maxLength = ($scope.land.length > $scope.water.length) ? $scope.land.length : $scope.water.length;
//length is to be determined
for(var index = 0; index < maxLength ; index++) {
$scope.combined.push({
land: ($scope.land[index]) ? $scope.land[index] : '',
water: ($scope.water[index]) ? $scope.water[index] : ''
});
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="myApp" ng-controller="TestCtrl">
<table class="table table-dark">
<thead>
<tr>
<th scope="col">LAND</th>
<th scope="col">WATER</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in combined">
<td>{{item.land}}</td>
<td>{{item.water}}</td>
</tr>
</tbody>
</table>
</div>

How to collapse and hide in ng-repeat over table?

So I have a table where I need to show parent deals and on ng-show(clicking parent deal) I want to show child deals.
<table class="table table-hover">
<thead class="thead-dark">
<tr>
<th scope="col">Name</th>
<th scope="col">No_Of_Orders</th>
<th scope="col">Size</th>
<th scope="col">Book_Size</th>
<th scope="col">Remarks</th>
<th scope="col">Price_Guidance</th>
<th scope="col">CONTROL</th>
<th scope="col">Status</th>
<th scope="col">Current_Cut_Off</th>
<th scope="col">Tenor</th>
<th scope="col">Book</th>
<th scope="col">ORDCOLUMN</th>
<th scope="col">PKEY</th>
<th scope="col">Save</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="parentDeal in parentDeals track by $index" ng-click="childShow(parentDeal.PKEY)">
<td>{{parentDeal.Name}}</td>
<td>{{parentDeal.No_Of_Orders}}</td>
<td>{{parentDeal.Size}}</td>
<td>{{parentDeal.Book_Size}}</td>
<td>{{parentDeal.Remarks}}</td>
<td>{{parentDeal.Price_Guidance}}</td>
<td>{{parentDeal.CONTROL}}</td>
<td>{{parentDeal.Status}}</td>
<td>{{parentDeal.Current_Cut_Off}}</td>
<td>{{parentDeal.Tenor}}</td>
<td>{{parentDeal.Book}}</td>
<td>{{parentDeal.ORDCOLUMN}}</td>
<td>{{parentDeal.PKEY}}</td>
<td>{{parentDeal.Save}}</td>
<tr ng-repeat="childDeal in childDeals track by $index" ng-show = "childRowShow_{{childDeal.PKEY}}">
<td>{{childDeal.Name}}</td>
<td>{{childDeal.No_Of_Orders}}</td>
<td>{{childDeal.Size}}</td>
<td>{{childDeal.Book_Size}}</td>
<td>{{childDeal.Remarks}}</td>
<td>{{childDeal.Price_Guidance}}</td>
<td>{{childDeal.CONTROL}}</td>
<td>{{childDeal.Status}}</td>
<td>{{childDeal.Current_Cut_Off}}</td>
<td>{{childDeal.Tenor}}</td>
<td>{{childDeal.Book}}</td>
<td>{{childDeal.ORDCOLUMN}}</td>
<td>{{childDeal.PKEY}}</td>
<td>{{childDeal.Save}}</td>
</tr>
</tr>
</tbody>
</table>
This is the basic data:-
$scope.allDeals = [
{
"ORDCOLUMN":"2017-11-17T05:00:00.000000000Z",
"CONTROL":"N",
"PKEY":"UD0000000000720",
"Name":"rajat10 10:19",
"Tenor":"0Y",
"Size":0,
"Price_Guidance":"43%",
"Remarks":"-",
"Book_Size":20,
"Status":"Open",
"No_Of_Orders":2,
"Current_Cut_Off":2.3,
"Book":"Book#ReOffer",
"Save":"Edit"
},
{
"ORDCOLUMN":"2017-11-17T05:00:00.000000000Z",
"CONTROL":"Y",
"PKEY":"UD0000000000720",
"Name":"rajat10 10:19",
"Tenor":"Multi ...",
"Size":0,
"Price_Guidance":"-",
"Remarks":"-",
"Book_Size":20,
"Status":" Open",
"No_Of_Orders":2,
"Current_Cut_Off":2.3,
"Book":"Book#ReOffer",
"Save":"Edit"
},
{
"ORDCOLUMN":"2017-11-17T05:00:00.000000000Z",
"CONTROL":"N",
"PKEY":"UD0000000000720",
"Name":"rajat10 10:19",
"Tenor":"Perp",
"Size":0,
"Price_Guidance":"19%",
"Remarks":"-",
"Book_Size":0,
"Status":"Open",
"No_Of_Orders":2,
"Current_Cut_Off":2.3,
"Book":"Book#ReOffer",
"Save":"Edit"
}
....and so on
]
So, this data can be grouped by PKEY and parent object has control - "Y", child object has control - "N". Note:- There can be objects where there is only parent deal with no child deals.
In my app.js:-
$scope.parentDeals = $scope.allDeals.filter(function (item,index) {
return item.CONTROL == "Y";
});
$scope.childDeals = [];
$scope.childShow = function (PKEY) {
if($scope["childRowShow_"+PKEY]){
$scope["childRowShow_"+PKEY] = false;
}
else{
$scope.childDeals = $scope.allDeals.filter(function (item,index) {
if(item.PKEY == PKEY && item.CONTROL == "N"){
return item;
}
});
$scope["childRowShow_"+PKEY] = true;
}
};
Here, I am making two arrays:- parentDeals and childDeals.
Right now, I am applying ng-repeat on the separate row so, child deals are showing after all parent deals. Is there any way I can show them below the respective parent deals or can apply a different solution?
Yes, with ng-repeat-start and ng-repeat-end, we can explicitly specify the starting and ending for ng-repeat. So, instead of using the ng-repeat directive on one single DOM element, we can specify the ng-repeat-start and ng-repeat-end on any two DOM elements.
For eg.
<div ng-app="app">
<table ng-controller="TestController">
<tr ng-repeat-start="d in data">
<td><strong>{{d.name}}</strong></td>
</tr>
<tr ng-repeat-end>
<td>{{ d.info }}</td>
</tr>
</table>
</div>
<script>
var app = angular.module('app', []);
app.controller('TestController', function ($scope) {
$scope.data = [{
name: 'ABC',
info: 'Bangalore'
}, {
name: 'XYZ',
info: 'Mumbai'
}];
});
</script>

angular angular-table dynamic header name

I use angular and angular-table to display multiple tables on the same page.
I need to create dynamic table with dynamic header and dynamic content.
Plunkr her
This is a working example with non dynamic header but I don't find how to make dynamic
The controller :
angular.module('plunker', ['ui.bootstrap',"angular-table","angular-tabs"]);
function ListCtrl($scope, $dialog) {
$scope.cols= ['index','name','email'];
$scope.list = [
{ index: 1, name: "Kristin Hill", email: "kristin#hill.com" },
{ index: 2, name: "Valerie Francis", email: "valerie#francis.com" },
...
];
$scope.config = {
itemsPerPage: 5,
fillLastPage: true
};
}
HTML
<!-- this work -->
<table class="table table-striped" at-table at-paginated at-list="list" at-config="config">
<thead></thead>
<tbody>
<tr>
<td at-implicit at-sortable at-attribute="name"></td>
<td at-implicit at-sortable at-attribute="name"></td>
<td at-implicit at-sortable at-attribute="email"></td>
</tr>
</tbody>
</table>
<!-- this fail ... -->
<table class="table table-striped" at-table at-paginated at-list="list" at-config="config">
<thead></thead>
<tbody>
<tr>
<td ng-repeat='col in cols' at-implicit at-sortable at-attribute="{{col}}"></td>
</tr>
</tbody>
</table>
I am missing some think or it is not possible with this module ?
Did you know another module where you can have dynamic header and pagination ? ( i try also ngTable but have some bug issu with data not being displayed )
Through the below code, you can generate dynamic header
<table class="table table-hover table-striped">
<tbody>
<tr class="accordion-toggle tblHeader">
<th ng-repeat="(key, val) in columns">{{key}}</th>
</tr>
<tr ng-repeat="row in rows">
<td ng-if="!$last" ng-repeat="col in key(row)" ng-init="val=row[col]">
{{val}}
</td>
</tr>
</tbody>
</table>
Angular Script
var app = angular.module('myApp', []);
app.controller('myControl', function ($scope, $http) {
$http.get('http://jsonplaceholder.typicode.com/todos').success(function (data) {
$scope.columns = data[0];
$scope.rows = data;
}).error(function (data, status) {
});
$scope.key = function (obj) {
if (!obj) return [];
return Object.keys(obj);
}
});

How to use ng-repeat for array in array using single ng-repeat

I got a json of table which has columns and rows as below
$scope.table = {
Columns: [{Header:"22-Jul-15",SubHeaders: ["10:33 AM"]}
, {Header:"21-Jul-15",SubHeaders: ["03:40 AM"]}
, {Header:"17-Jul-15",SubHeaders: ["01:05 PM", "12:06 PM"]}]
, Rows:[{Items:[{Value:1},{Value:5},{Value:8},{Value:""}]}
,{Items:[{Value:2},{Value:6},{Value:9},{Value:""}]}
,{Items:[{Value:3},{Value:7},{Value:10},{Value:15}]}]
} //end of table
I want to display Columns.SubHeaders as Sub header row of a table.
Here what I tried, but did not work
<table class="table table-stripped table-bordered">
<thead>
<tr>
<th ng-repeat="col in table.Columns" colspan="{{col.SubHeaders.length}}">{{col.Header}}</th>
</tr>
<tr>
<td class="center text-black" ng-repeat="head in table.Columns[0].SubHeaders">{{head}}</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in table.Rows">
<td ng-repeat="item in row.Items">
{{item.Value}}
</td>
</tr>
</tbody>
</table>
I used head in table.Columns[0].SubHeaders just to show it is working for hard-coded index value.
How can I achieve this using single ng-repeat? I can use two ng-repeats but it will lead to unnecessary html markup.
Here is the complete fiddle
I created this fiddler (forked from yours):
https://jsfiddle.net/b50hvzef/1/
The idea is to join the subheaders as they are they actual columns:
<td class="center text-black" ng-repeat="head in subHeaders">{{head}}</td>
and the code looks like this:
var app = angular.module("app",[]);
app.controller("MyController", function ($scope, $http) {
$scope.table = {
Columns: [{Header:"22-Jul-15",SubHeaders: ["10:33 AM"]}
, {Header:"21-Jul-15",SubHeaders: ["03:40 AM"]}
, {Header:"17-Jul-15",SubHeaders: ["01:05 PM", "12:06 PM"]}]
,Rows:[{Items:[{Value:1},{Value:5},{Value:8}]}
,{Items:[{Value:2},{Value:6},{Value:9}]}
,{Items:[{Value:3},{Value:7},{Value:10}]}]
};
var subHeaders = [];
$scope.table.Columns.forEach(function(col) {
col.SubHeaders.forEach(function(subHeader) {
subHeaders.push(subHeader);
});
});
$scope.subHeaders = subHeaders;
});
Note that there is still a mismatch between columns and data. But it's up to you how to solve it.
Hope this helps.

Angularjs: Why is $scope.variable in $watch not up-to-date?

I created a Plunker here to illustrate the problem. Here is the main code:
<body ng-controller="MainCtrl">
<table class="table table-bordered table-striped table-condensed table-hover">
<caption class="text-left" style="background-color: lightgray">
Search: <input ng-model="searchString" style="width: 80px" />
Filted count: {{filteredList.length}}
</caption>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Sex</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="emp in filteredList = (data.employees | filter:searchString)">
<td>{{emp.firstName}}</td>
<td>{{emp.lastName}}</td>
<td>{{emp.sex}}</td>
</tr>
</tbody>
</table>
</body>
App.js:
$scope.searchString = '';
$scope.$watch('searchString', function(str) {
console.log($scope.filteredList.length);
});
The problem is that the console.log of filteredList.length is always one loop behind (compared to html which is correct), that is, from previous filter. How can I fix it?
You are logging filteredList.length as soon as searchString changes. But, at at moment, filteredList has not yet been modified by the filter in ngRepeat.
One way to fix this would be to $watch filteredList.length instead:
$scope.$watch(function() {
return ($scope.filteredList || []).length;
...
Update
I really like shaunhusain's comment. His suggestion is probably closer to what you really want to do.
$scope.searchString = '';
// Initialize filteredItems as a copy of data.employees
$scope.filteredItems = angular.copy($scope.data.employees);
// Watch your search string instead and apply filtering using $filter
$scope.$watch(function() {
return $scope.searchString;
},
function(str) {
$scope.filteredItems = $filter('filter')($scope.data.employees, {$: $scope.searchString}, false);
console.log($scope.filteredItems.length);
});
Then, your ngRepeat is simply:
<tr ng-repeat="emp in filteredItems">
<td>{{emp.firstName}}</td>
<td>{{emp.lastName}}</td>
<td>{{emp.sex}}</td>
</tr>

Resources