add formatting from scope object when binding element - javascript

I have a table which is build up from a array I create in my controller. When trying to bind I would like to add formatting, for example | number, from my object array.
So, in the td-element inside tbody, I would like to use something like
row[column.rowValue] | column.filter
I've tried using {{}} around, and also tried ng-bind-template and so on..
How should I do this?
JSFIDDLE
html:
<script data-require="angular.js#*" data-semver="1.2.0" src="http://code.angularjs.org/1.2.0/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div ng:controller="MyCtrl">
<table class="table table-striped table-hover table-responsive table-bordered" border="1">
<thead style="font-weight: bold;">
<tr>
<th class="text-right" ng-repeat="column in columns" ng-bind="column.rowHeader"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rows">
<td ng-repeat="column in columns" ng-bind="row[column.rowValue] | column.filter"></td> <--doesnt work
</tr>
</tbody>
</table>
</div>
js:
var app = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.columns = [
{ checked: true, rowValue: 'value1', rowHeader: 'Value1', filter: 'number' },
{ checked: true, rowValue: 'value2', rowHeader: 'Value2', filter: 'number' },
{ checked: true, rowValue: 'ModelName', rowHeader: 'Name' }
];
$scope.rows = [
{ value1: 100, value2: 5, ModelName: "This is a cell value" },
{ value1: 15, value2: 5, ModelName: "This is a cell value2" },
{ value1: 38, value2: 2, ModelName: "This is a cell value3" }
];
}

Use a function in you controller for format the value and if you need use a custom filter, inject the $filter service.
var app = angular.module('myApp',[]);
function MyCtrl($scope, $filter) {
$scope.columns = [
{ checked: true, rowValue: 'value1', rowHeader: 'Value1', filter: 'number' },
{ checked: true, rowValue: 'value2', rowHeader: 'Value2', filter: 'number' },
{ checked: true, rowValue: 'ModelName', rowHeader: 'Name' }
];
$scope.formatRow = function(value, filterName){
return $filter(filterName)(value);
};
$scope.rows = [
{ value1: 100, value2: 5, ModelName: "This is a cell value" },
{ value1: 15, value2: 5, ModelName: "This is a cell value2" },
{ value1: 38, value2: 2, ModelName: "This is a cell value3" }
];
}
HTML
<tbody>
<tr ng-repeat="row in rows">
<td ng-repeat="column in columns" ng-bind="formatRow(row[column.rowValue], column.filter)"></td>
</tr>
</tbody>

Related

Angularjs: How do I ng-repeat through an array of objects with a field that is also an array?

I have an array that looks like this:
0: {ID: null,
name: "test",
city: "Austin",
UserColors: [{color: "blue"},{hobby:"beach"} ... ]}
}...
I am trying to ng-repeat through the initial array but once I try to loop through the list, i see nothing, heres the html/angular
<tr ng-repeat="c in vm.people">
<td>{{c.name}}</td>
<td>{{c.city}}</td>
<td ng-repeat="uc in c.UserColors">
<td>{{uc.color}}</td>
</td>
</tr>
I am not sure what is wrong, and I would appreciate your help, I thank you in advance.
I would process the field with a custom filter:
<td ng-repeat-start="(key, value) in c.UserColors | reduce">
<b>{{key}}</b>
</td>
<td ng-repeat-end>
{{value}}
</td>
The filter:
app.filter("reduce",function() {
return function(items) {
var x = items.map(o => Object.entries(o));
var x2 = x.reduce(((a,x) => (a.concat(x))), []);
var x3 = x2.reduce(((o,x) => (o[x[0]]=x[1],o)), {});
return x3;
}
})
The DEMO
angular.module("app",[])
.controller("ctrl",function(){
var vm = this;
vm.people = {
0: {ID: null,
name: "test",
city: "Austin",
UserColors: [{color: "blue"},{hobby:"beach"}]
},
1: {ID: null,
name: "best",
city: "Boston",
UserColors: [{colorx: "red"},{shirt:"black"}]
},
2: {ID: null,
name: "rest",
city: "Paris",
UserColors: [{colory: "yel"},{fruit:"peach"}]
},
}
})
.filter("reduce",function() {
return function(items) {
var x = items.map(o => Object.entries(o));
var x2 = x.reduce(((a,x) => (a.concat(x))), []);
var x3 = x2.reduce(((o,x) => (o[x[0]]=x[1],o)), {});
return x3;//items;
}
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="ctrl as vm">
<h3>Table</h3>
<table>
<tr ng-repeat="c in vm.people">
<td>{{c.name}}</td>
<td>{{c.city}}</td>
<td ng-repeat-start="(key, value) in c.UserColors | reduce">
<b>{{key}}</b>
</td>
<td ng-repeat-end>
{{value}}
</td>
</tr>
</table>
</body>

How to remove default order of ng-repeat

How do I stop default sorting inside the ng-repeat for dynamic table data ?
Currently I am getting below order:
Addr | CustomerId | Name
but what I want is below ordering:
CustomerId | Name | Addr
Any Help would me much appreciated.
JS:
app.controller('MyController', function ($scope) {
$scope.Customers = [
{ CustomerId: 1, Name: "John Hammond", Addr:'India'
},
{
CustomerId: 2, Name: "Mudassar Khan", Addr:'India'
},
{
CustomerId: 3, Name: "Suzanne Mathews", Addr:'India'
},
{
CustomerId: 4, Name: "Robert Schidner", Addr: 'India'
}
];
});
HTML:
<table>
<tr >
<th ng-repeat="(key,value) in Customers[0]">{{key}}</th>
</tr>
<tbody ng-repeat="c in Customers">
<tr>
</tr>
</tbody>
</table>
Try this below way. I hope this below snippet result is showing what you want.
angular.module("aaa",[]).controller('MyController', function ($scope) {
$scope.Customers = [
{ CustomerId: 1, Name: "John Hammond", Addr:'India'
},
{
CustomerId: 2, Name: "Mudassar Khan", Addr:'India'
},
{
CustomerId: 3, Name: "Suzanne Mathews", Addr:'India'
},
{
CustomerId: 4, Name: "Robert Schidner", Addr: 'India'
}
];
$scope.keys = Object.keys($scope.Customers[0]);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="aaa" ng-controller="MyController">
<table>
<tr>
<th ng-repeat="key in keys">
{{key}}
</th>
</tr>
<tbody ng-repeat="c in Customers">
<tr>
<td ng-repeat="key in keys">{{c[key]}}</td>
</tr>
</tbody>
</table>
</div>
So objects in JS are inherently unordered. What you can do is just hard code the keys in the header if that will be fixed for that particular table and then print the values in the respective order.
Something like this:
<table>
<tr >
<th>CustomerId</th>
<th>Name</th>
<th>Addr</th>
</tr>
<tbody>
<tr ng-repeat="c in Customers">
<td>{{CustomerId}}</td>
<td>{{Name}}</td>
<td>{{c.Addr}}</td>
</tr>
</tbody>
</table>
Note: I put the ng-repeat on the tr which is probably what you need. I dont think you should put it on the tbody.
Do you mean the sort order of the data or the display order of the columns?
The accepted answer displays the data by the order of the columns as specified, but if you want the data itself sorted then just add a filter to the data like this:
<tbody ng-repeat="c in Customers|orderBy:['CustomerId','Name','Addr']">
This sorts the actual data in the list by the fields specified.

AngularJS: ng-repeat without similar key

I have list of objs:
[{
key:test1
name: name1
},
{
key:test1
name: name2
},
{
key:test2
name: name3
}]
And i use ng-repeat to display it:
<tr ng-repeat=item in list>
<td>{{item.key}}</td>
<td>{{item.name}}</td>
</tr>
Is it possible to combine values with similar keys without changing the structure? not to be displayed twice test1 in my case
now:
test1 : name1
test1 : name2
test2 : name3
desired result:
test1 : name1
_____ name2
test2 : name3
You can use groupBy filter:
angular.module('app', ['angular.filter']).controller('ctrl', function($scope){
$scope.list = [{
key:'test1',
name: 'name1'
}, {
key:'test1',
name: 'name2'
},{
key:'test1',
name: 'name3'
},{
key:'test2',
name: 'name4'
}];
})
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.16/angular-filter.js"></script>
<table ng-app='app' ng-controller='ctrl'>
<tbody>
<tr ng-repeat-start="(key, value) in list | groupBy: 'key'">
<td>{{key}}</td>
<td>{{value[0].name}}</td>
</tr>
<tr ng-repeat-end ng-repeat='item in value.splice(1)'>
<td></td>
<td>{{item.name}}</td>
</tr>
</tbody>
</table>
ng-repeat="item in list | unique:'key'"
Here is how you can achieve the common key value in a same place using angular-filter:
angular.module('app',['angular.filter']).controller('mainCtrl', function($scope){$scope.list = [{
key:'test1',
name: 'name1'
},
{
key:'test1',
name: 'name2'
},
{
key:'test2',
name: 'name3'
}]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.16/angular-filter.min.js"></script>
<div ng-app='app' ng-controller='mainCtrl'>
<div ng-repeat="(key, value) in list | groupBy: 'key'">
<span ng-repeat='val in value'>{{val.name}} </span>
</div>
</div>
Before using ng-repeat update the list.
function rd(o, k, v) {
var n = [];
var l = {};
for(var i in o) {
if (l.hasOwnProperty(o[i][k])){
o[i][v] = l[o[i][k]][v]+ " " + o[i][k]
l[o[i][k]] = o[i]
} else{
l[o[i][k]] = o[i];
}
}
for(i in l) {
n.push(l[i]);
}
return n;
}
var list = rd(arr, "key", "name");
You can try this:
var app = angular.module('myApp', ['angular.filter']);
app.controller('myCtrl', function($scope) {
$scope.items = [{
"key":"test1",
"name": "name1"
},
{
"key":"test1",
"name": "name2"
},
{
"key":"test2",
"name": "name3"
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.16/angular-filter.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="item in items | groupBy: 'key'">
<h3>Key : {{item[0].key}}</h3>
<p>Names : <span ng-repeat='i in item'>{{i.name}} </span></p>
</div>
</div>

bind multidimensional array with vuejs

I am building a dynamic table on my front end side, and at the end i need to know what was inserted on each cell of my table since it is editable, so i did this on my html:
<table class="table table-responsive">
<tbody>
<tr v-for="(row,idx1) in tableRows" :class="{headerRowDefault: checkHeader(idx1)}">
<td class="table-success" v-for="(col,idx2) in tableCols"><input v-model="items[idx1][idx2]" type="text" class="borderTbl" value="HEY"/></td>
</tr>
</tbody>
</table>
as you guys can see. i set inside the input a v-model with items[idx1][idx2] so i can pass the value to that line and columns, it is not working like this, i don't know how to set it.
This is my javascript:
export default {
name: 'app',
data () {
return {
table: {
rows: 1,
cols: 1,
key: 'Table',
tableStyle: 1,
caption: '',
colx: []
},
hasHeader: true,
hasCaption: true,
insert: 1,
idx2: 1,
items: []
}
},
computed: {
tableStyles () {
return this.$store.getters.getTableStyles
},
tableRows () {
return parseInt(this.table.rows)
},
tableCols () {
return parseInt(this.table.cols)
}
expected items array:
items:[
["john","Micheal"]
["john","Micheal"]
["john","Micheal"]
["john","Micheal"]
]
So, I think you're not pointing your models correctly.
Template:
<tr v-for="(row, idx1) in items">
<td class="table-success" v-for="(col, idx2) in row">
<input v-model="items[idx1][idx2]" type="text" />
</td>
</tr>
Script:
data () {
return {
items:[
["john","Micheal"],
["john","Micheal"],
["john","Micheal"],
["john","Micheal"]
];
};
}
Here's a working fiddle of it

Applying a filter on each column of the dynamic table in AngularJS

I am trying to create a general table using element type custom directive that takes collection of data and generates the table header and create all the rows and columns of the table, then i tried to sort all the columns. The part of this code is working fine. But my next goal is to apply the filter on all the columns of the table, as the data is dynamic so we cannot decide about the field to filter at run time. The problem I diagnosed is that I am using ng-repeat="row in customers|filter:{$scope.searchkey:$scope.search}". Here seems to be the problem because in then expression the first thing should be object but $scope returns object.
Following is my code.
Index.html
<body>
<div>
<my-table input="Customers"></my-table>
<br />
<br />
<br />
<my-table input="Users"></my-table>
</div>
</body>
script.js
angular.module('DirectiveDemo', [])
.controller('Controller', ['$scope', function ($scope) {
$scope.Customers = [{ Name: "2Touqeer", Code: "2" },
{ Name: "3Nadeem", Code: "3" },
{ Name: "1Talha", Code: "1" },
{ Name: "4Muslim Khan", Code: "4" }
];
$scope.Users = [{ Name: "Touqeer", Code: "2", ID: "2Touqeer", CID: "CID1" },
{ Name: "Nadeem", Code: "3", ID: "3Muslim", CID: "CID3" },
{ Name: "Talha", Code: "1", ID: "1Nadeem", CID: "CID2" },
{ Name: "Muslim Khan", Code: "4", ID: "1Talha", CID: "CID5" },
{ Name: "Khan", Code: "4", ID: "1Khan", CID: "CID78" }
];
}])
.directive('myTable', function () {
return {
restrict: 'E',
transclude: true,
scope: {
customerInfo: '=input'
},
templateUrl: 'my-table-info.html',
controller: function ($scope) {
$scope.searchKey = 'CID';
alert($scope.searchKey)
$scope.reverseSort = false;
$scope.search = '';
$scope.List = [];
$scope.order = function (item) {
$scope.orderByField = item;
alert($scope.search)
}
$scope.filterValue = function (itemKey,valueKey) {
$scope.searchKey = itemKey;
if (valueKey != 'undefined') {
$scope.search = valueKey;
alert($scope.search)
}
}
}
};
})
my-table-info.html
<table ng-transclude>
<thead class="GridHeaderItem ControlBorder">
<tr>
<th ng-repeat="(key, value) in customerInfo[0]"> <a href="#" ng-click="order(key); reverseSort = !reverseSort">
{{key}}
<span ng-show="orderByField==key">
<span ng-show="!reverseSort">
<i class="glyphicon-circle-arrow-up glyphicon"></i>
</span>
<span ng-show="reverseSort">
<i class="glyphicon-circle-arrow-down glyphicon"></i>
</span></span>
</a></th>
</tr>
<tr class="ControlBorderRight ControlBorderTop ControlBorderBottom">
<td class=" ControlBorderLeft ControlBorderBottom" ng-repeat="(key, value) in customerInfo[0]" >
<input type="text" style="width:100%;" ng-model="searchfilter" ng-change="filterValue(key,searchfilter);" />
<!--ng-change="filter(key);"-->
</td>
</tr>
</thead>
<tr ng-repeat="row in customerInfo|filter:{co[row]:2}|orderBy:orderByField:reverseSort" class="ControlBorderRight ControlBorderTop ControlBorderBottom ">
<td ng-repeat="col in row" class=" ControlBorderBottom ControlBorderLeft Control LabelControl">{{col}}</td>
</tr>
</table>
You should build a custom filter function angular.module('myMod',[]).filter('myFilter',function(){ return function(input){...} }) then your repeat should look like this: ng-repeat="row in customers | myFilter" - the row object will be fed to the filter function as the input parameter.

Categories