I have json array and i want to create table from this and want to give a heading which is an element of array. Here is fiddle showing the scenario.
<div ng-repeat="products in items">
<div>{{products.IDTYPE}}</div>
<div>
<table border=1>
<thead>
<th>primkey</th>
<th>userid</th>
</thead>
<tbody>
<tr>
<td>{{products.PRIMKEY}}</td>
<td>{{products.USERID}}</td>
</tr>
</tbody>
</table>
</div>
This will create simple table with heading from the IDTYPE . But i want to group the rows with unique IDTYPE. So desired table will be as shown in this link.
So i tried adding a ng-show condition ng-show="$index==0 || items[$index-1].IDTYPE!=items[$index].IDTYPE" but it doesn't work properly as tbody and table will be constructed for every row.This is what i have tried.
So how to generate the table as i desired in the above description?
If you do not wish to change your source data structure to fit better to what you need, you may have to write some extra code to change it from the javascript side. Something like:
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.items = [...]; //your original data
// Here the transformation begins...
$scope.newItems = {};
for (var i = 0; i < $scope.items.length; i++) {
// We'll make it look like a map
// Each IDTYPE will have an array associated to it
if (!$scope.newItems[$scope.items[i].IDTYPE]) {
$scope.newItems[$scope.items[i].IDTYPE] = [];
}
$scope.newItems[$scope.items[i].IDTYPE].push($scope.items[i]);
}
}
From the HTML side, you just have to read accordingly to your new data:
<div ng-repeat="products in newItems">
<div>{{products[0].IDTYPE}}</div>
<div>
<table border=1>
<thead>
<th>primkey</th>
<th>userid</th>
</thead>
<tbody>
<tr ng-repeat="productItem in products">
<td>{{productItem.PRIMKEY}}</td>
<td>{{productItem.USERID}}</td>
</tr>
</tbody>
</table>
</div>
</div>
Fiddle: http://jsfiddle.net/5mpgzdem/
Related
I am trying to learn AngularJS 1.6 and I am trying to populate a table with rows depending on the amount of rows selected in a dropdown list. It could be anywhere from 1 to 12. So far I have the following code.
<body ng-controller="myController">
<div>
<p>Blue Corner Boxer: </p> <input type="text" ng-model="nameBlue">
<br>
<p>Red Corner Boxer: </p> <input type="text" ng-model="nameRed">
<br>
<p>Number of Rounds:</p> <select ng-model="selectedRounds"><option ng-repeat="x in rounds">{{x}}</option></select>
</div>
<div>
<table class="table table-striped">
<thead>
<tr>
<th style="text-align:center">{{nameBlue}}</th>
<th style="text-align:center">Round</th>
<th style="text-align:center">{{nameRed}}</th>
</tr>
</thead>
<tbody class="tablerows">
<tr ng-repeat="x in selectedRounds">
<td>Test</td>
<td>Test</td>
<td>Test</td>
</tr>
</tbody>
</table>
<h2 style="text-align: center">Final Score: </h2> {{scoreBlue1 + ScoreBlue2}}
</div>
</body>
Then in the js file
//Create the module
var myApp = angular.module("myModule", []);
//Create the controller and register the module in one line
myApp.controller("myController", function ($scope) {
$scope.message = "AngularJS tutorial";
$scope.score = [1,2,3,4,5,6,7,8,9,10];
$scope.rounds = [1,2,3,4,5,6,7,8,9,10,11,12];
});
So far the table will add 1 row on selection of anything 1 to 9, but 10 to 12 adds 2 rows. So I think I am wondering how to create an array length of size "selectedrounds" that will repeat rows with the repeater.
Thanks
If you need an array only for iterating and you don't worry about data in it. You can do something like this:
In your controller:
$scope.selectedRounds = 0;
$scope.getRoundsArray(){
return new Array($scope.selectedRounds);
}
We just create an array with needed length and with all elements are 'undefined'. If you create an array with 3 lenght you will get: ['undefined', 'undefined', 'undefined'].
In view:
<tr ng-repeat="x in getRoundsArray() track by $index">
You need this track by $index cause your array contains only 'undefined' values so to prevent angular arguing about duplicate keys we need to use track by.
I have a table sorted by properties "age" and "name" but I have a counter of rows (counterR) that shows the numbers of rows in the table.
I want to exclude this item on OrderBy because is ordered too, I need it would be static and always ordered but I canĀ“t.
There's the Plunker link of my problem: http://plnkr.co/edit/MJYayUANphxksbGkyEcj?p=preview
HTML:
<body ng-controller="MainCtrl">
<table border="0">
<thead>
<tr>
<th>#</th>
<th>ID</th>
<th ng-click="sortType = 'name';sortReverse=!sortReverse">NAME</th>
<th ng-click="sortType = 'age';sortReverse=!sortReverse">AGE</th>
</tr>
</thead>
<tbody>
<tr ng-init="counterR=incrementCounter()" ng-repeat="item in items | orderBy:sortType:sortReverse">
<td>{{counterR}}</td>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.age}}</td>
</tr>
</tbody>
</table>
JS:
$scope.items = [
{"name":"Jhon","id":"BB1","age":23},
{"name":"Austin","id":"BB2","age":44},
{"name":"Mark","id":"BB3","age":56},
{"name":"Jenn","id":"BB4","age":15}
];
var counterRow = 0;
$scope.incrementCounter = function(){
counterRow = counterRow + 1;
return counterRow;
}
Instead of storing the row number with the data - which doesn't work because the row numbers are not specific to a data row, but rather to a display position - you need to calculate the value "on the fly". In the scope of an ng-repeat you can do this with the special $index variable. That is, instead of
<td>{{counterR}}</td>
which reads a value from the data row, you would use
<td>{{$index+1}}</td>
(assuming sequential numbers starting from 1)
<table class="table table-bordered">
<tbody>
<tr ng-repeat="playerOrTeam in template.editableTable track by $index">
<td style="text-align: center;" ng-repeat="playerOrTeamCat in playerOrTeam track by $index">
<input ng-model="playerOrTeamCat" type="text" class="form-control input-sm">
</td>
</tr>
</tbody>
</table>
template.editableTable is a multi dimensional array just filled with standard variables. when I change one of the values in the input box and then i look at the output of the template.editable table, i don't see the changes. Am I missing something obvious?
EDIT with more details because i'm getting no responses =\
//Template Class
app.factory('Template', function () {
var Template = function () {
/*
* Public Variables
*/
this.editableTable = someMultiDimensionalTable;
}
/*
* Functions
*/
Template.prototype.SeeEditableTableContents = function () {
console.log(this.editableTable);
}
}
//Main Controller
app.controller('MainController', function () {
$scope.template = new Template();
//etc
}
You cannot perform direct in-line modifications within ng-repeat. You can update your array entry using a function.
You'd want something like:
$scope.saveEntry = function (idx) {
console.log("Saving entry");
$scope.template.editableTable[idx] = angular.copy($scope.model.selected);
$scope.reset();
};
See JSFiddle for sample.
okay i actually got it to work so that i CAN make direct in-line modifications with ng-repeat by making my multidimensional table full of objects rather than soley a value.
so by doing that, i modified the table to look like this
<table class="table table-bordered">
<tbody>
<tr ng-repeat="playerOrTeam in template.editableTable track by $index">
<td style="text-align: center;" ng-repeat="playerOrTeamCat in playerOrTeam track by $index">
<input ng-model="playerOrTeamCat.value" type="text" class="form-control input-sm">
</td>
</tr>
</tbody>
</table>
got the idea looking here
Modifying objects within Angular Scope inside ng-repeat
I'm trying to use Angular.JS to dynamically add columns to an html table.
It starts with a set of data, and I want to make extra data available on a click. I'm new to Angular, and made this plunker to illustrate what I'm trying to do. I'd like to (obviously) just add a new table header and a new table data based on the number of items in the array, matched to the index number of the same row. Thank you
Controller:
function Ctrl($scope) {
$scope.data = [];
$scope.data[3] = [];
$scope.data[0] = [['New York', 1000,2000],['Los Angeles', 200,400],['Nottingham', 800,400]]
$scope.moredata = [1500, 2500, 4500];
temp = []
$scope.getData = function() {
$scope.moduleArray[1] = $scope.moredata;
}
$scope.moduleArray = $scope.data;
}
HTML:
<div ng-controller="Ctrl">
<button ng-click="getData()">Get more data</button>
<table>
<tr>
<th>Location</th>
<th>Current Data</th>
<th ng-repeat="ba in moduleArray[1]">new data</th>
</tr>
<tr data-ng-repeat="item2 in moduleArray[0]">
<td>2[0]{{item2[0]}}</td>
<td>2[1]{{item2[1]}}</td>
<td data-ng-repeat="bat in moduleArray[1]">{{bat[$parent.$index]}}</td>
</tr>
</table>
Plunkr
Here's very simple set up that toggles single columns on right side.
There are 2 sets of arrays, one for column headers and one for row data.
It uses limitTo filter for ng-repeat.
From there it is a simple increment/decrement of a scope variable colCount to add/remove column
View
<button ng-click="increment('up')">Add Column</button>
<button ng-click="increment('down')">Remove Column</button>
<table class="table table-bordered">
<tr>
<th ng-repeat="col in cols | limitTo: colCount">{{col}}</th>
</tr>
<tr ng-repeat="row in data">
<td ng-repeat="item in row | limitTo: colCount">{{item}}</td>
</tr>
</table>
Controller
// used as limit for ng-repeat limitTo
$scope.colCount = 3;
$scope.increment = function(dir) {
(dir === 'up') ? $scope.colCount++: $scope.colCount--;
}
$scope.cols = // array of column names
$scope.data = // row data arrays
Note that for large tables this may not great for performance due to multiple nested repeaters
DEMO
here is my HTML:
...
<table class="tickerTable">
<thead>
<th>Symbol</th>
<th>Accts</th>
</thead>
<tbody ng-repeat="ticker in tickers">
<tr ng-click="showTrades(ticker)">
<td >{{ticker.Ticker}}</td>
<td>{{ticker.TradeCount}}</td>
</tr>
<tr ng-show="currentItem == ticker">
<td colspan="2">{{trades}}</td>
</tr>
</tbody>
</table>
here is the controller:
$scope.showTrades = function(ticker){
$scope.trades = {};
$scope.currentItem = ticker;
$scope.trades = "this is the result of a rest call using the params from $scope.ticker";
};
the table is populated with many rows. for each row i add a blank row that is hidden by default.
when the row is clicked the hidden row displays dynamically generated content that is returned from a rest call made with the params of that particular table row's "ticker" object. the result is injected into $scope.trades and displayed in the now visible TR.
The problem: {{trades}} is being populated in every hidden row along with the revealed row. I only want it to load in the revealed row.
solution
http://plnkr.co/edit/qFZyeuIbt6z5dYEFFHzr?p=preview
In your plnkr you are using ng-if.
There is a bug relatead to ng-if in tables #3104 which will cause problems for you. Maybe you can use ng-show instead as you did in the posted HTML?
Next you may add the trades to the containing ticker. So you display the trades belonging to the current ticker. Then only the selected ticker row will have trades.
<!doctype html>
<html ng-app='portfolio'>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js">
</script>
<script src="script.js"></script>
</head>
<body>
<table ng-controller = "TickerListCtrl">
<thead>
<th>Symbol</th>
</thead>
<tbody ng-repeat="ticker in tickers">
<tr ng-click="showTrades(ticker)">
<td>{{ticker.Ticker}}</td>
</tr>
<tr >
<td ng-show="currentItem == ticker" colspan="2">{{ticker.trades}}</td>
</tr>
</tbody>
</table>
</body>
</html>
$scope.showTrades = function(ticker){
ticker.trades = "this is trades for ticker: " + ticker.Ticker;
$scope.currentItem = ticker;
};
Here is a fork of your plnkr with the described changes.