simple way of creating dynamic table - arrays

i have creating table with this way:
first i have my child component that act as the whole table warper
<div class="table-responsive hidden-xs">
<table class="table table-striped" :class="tableClass">
<!-- header -->
<thead class="bg-primary">
<tr class="text-nowrap">
<th v-for="item in columnData" v-if="!item.hide && !item.disable">
<div #click="sort(item.key)" v-if="item.sort" class="cursor-pointer">
<span v-html="item.title"></span>
<span v-if="params.column === item.key">
<span v-if="params.direction === 'asc'"><i class="icon-sort-amount-asc"></i></span>
<span v-else><i class="icon-sort-amount-desc"></i></span>
</span>
<span class="icon-sort text-muted" v-else></span>
</div>
<div v-else>
<span v-html="item.title"></span>
</div>
</th>
</tr>
</thead>
<!-- loading body -->
<tbody v-if="itemDataStat === 'loading'">
<tr>
<td :colspan="columnData.length">
<div class="progress">
<div class="progress-bar progress-bar-info progress-bar-striped active" style="width: 100%">
<span class="sr-only">100% Complete</span>
</div>
</div>
</td>
</tr>
</tbody>
<!-- data body -->
<tbody v-for="(items,index) in groupData" v-else-if="itemDataStat === 'success'" #contextmenu.prevent = "$refs.menu.open">
<tr class="active border-double" v-if="group.show">
<td :colspan="columnData.length">
Kelompok {{ group.title }}: <b>{{index}}</b>
</td>
</tr>
<slot name="item-desktop" v-for="(item,index) in items" :item="item" :index="index"></slot>
</tbody>
<!-- error body -->
<tbody v-else-if="itemDataStat === 'fail'">
<tr>
<td :colspan="columnData.length">
Oops.. Terjadi kesalahan, silahkan coba lagi.
</td>
</tr>
</tbody>
</table>
</div>
and from there i just import this table component into my page and just do this
<template slot="item-desktop" slot-scope="props">
<tr :class="{ 'info': selectedItem.id === props.item.id }" class="text-nowrap" #click="selectedRow(props.item)">
<td>
{{ props.index + 1 + (+itemData.current_page-1) * +itemData.per_page + '.'}}
</td>
<td v-if="!columnData[1].hide">
<img :src="'/images/' + kelas + '/' + props.item.picture + 'n.jpg'" class="img-rounded img-responsive img-sm" v-if="props.item.picture">
<img :src="'/images/no_image.jpg'" class="img-rounded img-responsive img-sm" v-else>
</td>
<td v-if="!columnData[2].hide">
<check-value :value="props.item.name"></check-value>
</td>
<td v-if="!columnData[3].hide">
<check-value :value="props.item.price1"></check-value>
</td>
<td v-if="!columnData[4].hide">
<check-value :value="props.item.price2"></check-value>
</td>
<td v-if="!columnData[5].hide">
<check-value :value="props.item.discount"></check-value>
</td>
<td v-if="!columnData[6].hide" v-html="$options.filters.dateTime(props.item.created_at)" class="text-nowrap"></td>
<td v-if="!columnData[7].hide">
<span v-if="props.item.created_at !== props.item.updated_at" v-html="$options.filters.dateTime(props.item.updated_at)"></span>
<span v-else>-</span>
</td>
</tr>
</template>
and what columnData array looked like is
columnData: [
{
title: 'No.',
key: 'No.',
excelType: 'string',
sort: false,
hide: false,
disable: false
},
{
title: 'Image',
key: 'picture',
excelType: 'string',
sort: false,
hide: false,
disable: false
},
{
title: 'Nama',
key: 'name',
excelType: 'string',
sort: true,
hide: false,
disable: false,
filter: true,
filterType: 'string',
},
{
title: 'Seller 1 Price',
key: 'price1',
excelType: 'string',
sort: true,
hide: false,
disable: false
},
{
title: 'Seller 2 Price',
key: 'price2',
excelType: 'string',
sort: true,
hide: false,
disable: false
},
{
title: 'Discount',
key: 'discount',
excelType: 'string',
sort: false,
hide: false,
disable: false
},
{
title: 'Created',
key: 'created_at',
sort: true,
hide: false,
disable: false
},
{
title: 'Updated',
key: 'updated_at',
sort: true,
hide: false,
disable: false
}
],
and i also have methods that use for hiding the column by changing columnData[].hide value to true and it will not show/hide the column header and column body
everything works fine, but when i have more and more column in one table then it will be a repetitive task. so is there any more elegant way? to just do some looping?

Related

Freez static column in P-table

I have a table with static actions column in first position remaining dynamic columns,
How to freeze only first actions column
For example here Name is static column and remaining are dynamic then how to freeze name column only
You could define frozen and scrollable columns as below
this.scrollableCols = [
{ field: 'year', header: 'Year' },
{ field: 'brand', header: 'Brand' },
{ field: 'color', header: 'Color' },
{ field: 'year', header: 'Year' },
{ field: 'brand', header: 'Brand' },
{ field: 'color', header: 'Color' }
];
this.frozenCols = [
{ field: 'vin', header: 'Vin' },
];
Your html would like below.
<p-table [columns]="scrollableCols" [frozenColumns]="frozenCols" [value]="cars" [scrollable]="true" scrollHeight="200px" frozenWidth="200px">
<ng-template pTemplate="colgroup" let-columns>
<colgroup>
<col *ngFor="let col of columns" style="width:200px">
</colgroup>
</ng-template>
<ng-template pTemplate="header" let-columns>
<tr>
<th *ngFor="let col of columns">
{{col.header}}
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowData let-columns="columns">
<tr>
<td *ngFor="let col of columns">
{{rowData[col.field]}}
</td>
</tr>
</ng-template>
</p-table>
Stackblitz link - https://stackblitz.com/edit/angular-primeng-frozen-columns-nytg8b?file=src/app/table-scroll-demo.component.html

How to change ngTable title colors programmatically?

In this plunk I have an ngTable that is created dynamically, setting progammatically the colors of the rows for each column. How to change the colors of the column titles?
HTML:
<table ng-table-dynamic="tableParams with cols" class="table table-bordered table-hover">
<tr ng-repeat="row in data">
<td ng-repeat="col in cols" ng-style="{ 'color': col.color }">{{row[col.nm]}}</td>
</tr>
</table>
Javascript:
var app = angular.module('app', ['ngTable']);
app.controller('myCtl', function($scope,NgTableParams) {
$scope.cols = [
{nm:'uid', title:'User ID', color: 'blue'},
{nm:'ugr', title: 'Group ID', color: 'red'}
];
$scope.data = [
{ uid: 'aaa',ugr: '222'},
{ uid: 'bbb', ugr: '111'}
];
$scope.tableParams = new NgTableParams({dataset: $scope.data});
});
You can use the class property on each of the objects in your cols array:
$scope.cols = [
{nm:'uid', title:'User ID', class: 'text-blue' },
{nm:'ugr', title: 'Group ID', class: 'text-red'}
];
Then set appropriate css classes in your stylesheet:
.text-blue{
color: #0000ff;
}
.text-red{
color: #ff0000;
}
Demo Plunk
You need to include a thead. Here is an updated Plunker
<table ng-table-dynamic="tableParams with cols" class="table table-bordered table-hover">
<thead>
<tr>
<th ng-repeat="col in cols" ng-style="{ 'color': col.color }">{{col.title}}</th>
</tr>
</thead>
<tr ng-repeat="row in data">
<td ng-repeat="col in cols" ng-style="{ 'color': col.color }">{{row[col.nm]}}</td>
</tr>
</table>
The right way to do it is Matthew Cawley's answer but in case you want to do additional modifications on table headers it's useful to know that you can change template for header:
http://plnkr.co/edit/662FYVbJyz2wxqXV5nNk?p=preview
<table template-header="table-header.html" ng-table-dynamic="tableParams with cols" class="table table-bordered table-hover">
after that add file table-header.html in your project containing this:
<tr>
<th title="{{$column.headerTitle(this)}}"
ng-repeat="$column in $columns"
ng-class="{
'sortable': $column.sortable(this),
'sort-asc': params.sorting()[$column.sortable(this)]=='asc',
'sort-desc': params.sorting()[$column.sortable(this)]=='desc',
}"
ng-click="sortBy($column, $event)"
ng-if="$column.show(this)"
ng-init="template = $column.headerTemplateURL(this)"
class="header {{$column.class(this)}} {{$column.headerClass}}">
<div ng-if="!template" class="ng-table-header" ng-class="{'sort-indicator': params.settings().sortingIndicator == 'div'}">
<span ng-bind="$column.title(this)" ng-class="{'sort-indicator': params.settings().sortingIndicator == 'span'}"></span>
</div>
<div ng-if="template" ng-include="template"></div>
</th>
</tr>
then in your code:
$scope.cols = [
{nm:'uid', title:'User ID', headerClass: 'blue'},
{nm:'ugr', title: 'Group ID', headerClass: 'red'}
];
also don't forget css classes:
.red {
color: red;
}
.blue {
color: blue;
}

changing the text area value for selected checkboxes when click on applyAll button using angular js

I need to display a block comments of selected check boxes with respective comments fields only(i.e if we select 1,3 check boxes and typing a comments and when we clicking on apply all button it should replace the comments fields of 1,3 after if we select 2,4 again when we change the text of comments and clicks on apply all button it should replace the comments fields of 2,4 only it shouldn't replace the 1,2,3,4 with new comments) can any one help me?
var app = angular.module('demo', []);
app.controller("profileController", function($scope) {
$scope.personalDetails = [
{
'fname':'Muhammed',
'lname':'Shanid',
'email':'shanid#shanid.com',
'check' : 'Y',
'checkxDrpn' : [
{ key: 'Y',selectVal: "Yes"},
{ key: 'N',selectVal: "No"}
],
'indivalCmts' : ''
},
{
'fname':'John',
'lname':'Abraham',
'email':'john#gmail.com',
'check' : 'N',
'checkxDrpn' : [
{ key: 'Y',selectVal: "Yes"},
{ key: 'N',selectVal: "No"}
],
'indivalCmts' : ''
},
{
'fname':'raj',
'lname':'komali',
'email':'raj#gmail.com',
'check' : 'N',
'checkxDrpn' : [
{ key: 'Y',selectVal: "Yes"},
{ key: 'N',selectVal: "No"}
],
'indivalCmts' : ''
},
{
'fname':'Roy',
'lname':'Mathew',
'email':'roy#roy.com',
'check' : 'N',
'checkxDrpn' : [
{ key: 'Y',selectVal: "Yes"},
{ key: 'N',selectVal: "No"}
],
'indivalCmts' : ''
}];
$scope.applyCmtsAll = function(personBlckCmts) {
angular.forEach($scope.personalDetails, function(value) {
if (value.selected == true) {
console.log("value " + value);
value.selectedDpn.selectVal = "Yes";
value.indivalCmts = personBlckCmts;
//$scope.indivalCmts==personBlckCmts;
return;
}
});
}
});
.selected {
text-decoration: line-through;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="demo" ng-controller="profileController">
<div class="">
<textarea ng-model="personBlckCmts"></textarea>
<button class="btn btn-default btn-sm" ng-click="applyCmtsAll(personBlckCmts)">Apply All</button>
</div>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th></th>
<th><input type="checkbox" ng-model="selectedAll" ng-click="checkAll()" /></th>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
<th>Yes/No</th>
<th>Comment</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="personalDetail in personalDetails" ng-class="{'selected':personalDetail.selected}">
<td>{{$index}}</td>
<td>
<input type="checkbox" ng-click="setClickedRow($index)" ng-model="personalDetail.selected" ng-disabled="personalDetail.selected"/>
</td>
<td>
<span>{{personalDetail.fname}}</span>
</td>
<td>
<span>{{personalDetail.lname}}</span>
</td>
<td>
<span>{{personalDetail.email}}</span>
</td>
<td>
<select ng-init="personalDetail.selectedDpn= personalDetail.checkxDrpn[1]" ng-options="value as value.selectVal for value in personalDetail.checkxDrpn track by value.key"
ng-model="personalDetail.selectedDpn" ></select>
</td>
<td>
<textarea ng-model="indivalCmts" ng-disabled="personalDetail.selected">
</textarea>
</td>
</tr>
</tbody>
</table>
</body>
</html>
I have updated your source code here. May be it will help to solve your issue.
var app = angular.module('demo', []);
app.controller("profileController", function($scope) {
$scope.personalDetails = [
{
'fname':'Muhammed',
'lname':'Shanid',
'email':'shanid#shanid.com',
'check' : 'Y',
'checkxDrpn' : [
{ key: 'Y',selectVal: "Yes"},
{ key: 'N',selectVal: "No"}
],
'indivalCmts' : ''
},
{
'fname':'John',
'lname':'Abraham',
'email':'john#gmail.com',
'check' : 'N',
'checkxDrpn' : [
{ key: 'Y',selectVal: "Yes"},
{ key: 'N',selectVal: "No"}
],
'indivalCmts' : ''
},
{
'fname':'raj',
'lname':'komali',
'email':'raj#gmail.com',
'check' : 'N',
'checkxDrpn' : [
{ key: 'Y',selectVal: "Yes"},
{ key: 'N',selectVal: "No"}
],
'indivalCmts' : ''
},
{
'fname':'Roy',
'lname':'Mathew',
'email':'roy#roy.com',
'check' : 'N',
'checkxDrpn' : [
{ key: 'Y',selectVal: "Yes"},
{ key: 'N',selectVal: "No"}
],
'indivalCmts' : ''
}];
$scope.applyCmtsAll = function(personBlckCmts) {
angular.forEach($scope.personalDetails, function(value) {
if (value.selected == true) {
value.selectedDpn.selectVal = "Yes";
value.indivalCmts = personBlckCmts;
value.selected = false;
}
});
$scope.personBlckCmts='';
}
});
.selected {
text-decoration: line-through;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="demo" ng-controller="profileController">
<div class="">
<textarea ng-model="personBlckCmts"></textarea>
<button class="btn btn-default btn-sm" ng-click="applyCmtsAll(personBlckCmts)">Apply All</button>
</div>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th></th>
<th><input type="checkbox" ng-model="selectedAll" ng-click="checkAll()" /></th>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
<th>Yes/No</th>
<th>Comment</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="personalDetail in personalDetails" ng-class="{'selected':personalDetail.selected}">
<td>{{$index}}</td>
<td>
<input type="checkbox" ng-click="setClickedRow($index)" ng-model="personalDetail.selected" ng-disabled="personalDetail.selected"/>
</td>
<td>
<span>{{personalDetail.fname}}</span>
</td>
<td>
<span>{{personalDetail.lname}}</span>
</td>
<td>
<span>{{personalDetail.email}}</span>
</td>
<td>
<select ng-init="personalDetail.selectedDpn= personalDetail.checkxDrpn[1]" ng-options="value as value.selectVal for value in personalDetail.checkxDrpn track by value.key"
ng-model="personalDetail.selectedDpn" ></select>
</td>
<td>
<textarea ng-model="personalDetail.indivalCmts" ng-disabled="personalDetail.selected">
</textarea>
</td>
</tr>
</tbody>
</table>
</body>
</html>

Highlight text in grid using AngularJS filter + ng-repeat in table data

I want to highlight search text under ng-repeat which is creating table.
I found one filter as my solution but it's not working on tables.
Can anyone points me where I am wrong to make it work.
<body ng-app="Demo">
<h1>Hello Plunker!</h1>
<div class="container" ng-controller="Demo">
<input type="text" placeholder="Search" ng-model="search">
<table>
<thead>
<th>Some</th>
<th>MyName</th>
</thead>
<tbody>
<tr ng-repeat="item in data | filter:search"
>
<td>
<td>{{item.title}}</td>
<td>{{item.name}}</td>
</td>
</tr>
</tbody>
<!-- with filter -->
</table>
</div>
<script>
angular.module('Demo', [])
.controller('Demo', function($scope) {
$scope.data = [
{ title: "Bad",name:'kaushik' },
{ title: "Good",name:'1kaushik' },
{ title: "Great",name:'2kaushik' },
{ title: "Cool" ,name:'3kaushik'},
{ title: "Excellent",name:'4kaushik' },
{ title: "Awesome",name:'5kaushik' },
{ title: "Horrible",name:'6kaushik' },
]
})
.filter('highlight', function($sce) {
return function(text, phrase) {
if (phrase) text = text.replace(new RegExp('('+phrase+')', 'gi'),
'<span class="highlighted">$1</span>')
return $sce.trustAsHtml(text)
}
})
</script>
</body>
This is working copy of the & demo the same thing I wants is with table.
You're not applying the highlight filter and you also have nested <td> elements. Try this:
<tr ng-repeat="item in data | filter:search">
<td ng-bind-html="item.title | highlight:search></td>
<td ng-bind-html="item.name | highlight:search"></td>
</tr>
angular.module('Demo', [])
.controller('Demo', function($scope) {
$scope.data = [{
title: "Bad",
name: 'kaushik'
},
{
title: "Good",
name: '1kaushik'
},
{
title: "Great",
name: '2kaushik'
},
{
title: "Cool",
name: '3kaushik'
},
{
title: "Excellent",
name: '4kaushik'
},
{
title: "Awesome",
name: '5kaushik'
},
{
title: "Horrible",
name: '6kaushik'
},
]
})
.filter('highlight', function($sce) {
return function(text, phrase) {
if (phrase) {
text = text.replace(new RegExp('(' + phrase + ')', 'gi'),
'<span class="highlighted">$1</span>');
}
return $sce.trustAsHtml(text)
}
});
.highlighted {
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<body ng-app="Demo">
<h1>Hello Plunker!</h1>
<div class="container" ng-controller="Demo">
<input type="text" placeholder="Search" ng-model="search">
<table>
<thead>
<th>Some</th>
<th>MyName</th>
</thead>
<tbody>
<tr ng-repeat="item in data | filter:search">
<td>
<td ng-bind-html="item.title | highlight:search"></td>
<td ng-bind-html="item.name | highlight:search"></td>
</td>
</tr>
</tbody>
<!-- with filter -->
</table>
</div>
<script>
</script>
</body>

How to use different data inside two ng-repeat directives?

I'm trying to make an editable table directive. I have two configs:
1) Table config:
table = [
{name: 'id',title: '#'},
{name: 'name',title: 'Name'},
{name: 'phone',title: 'Phone'},
{
name: 'action',
title: 'Edit',
button_name: 'Edit me',
type: 'button',
}
];
2) Data config:
data = [
{id: 1, name: 'Rikki', phone: 02},
{id: 2, name: 'Pikki', phone: 03},
{id: 3, name: 'Mikki', phone: 03}
];
I'm wondering, how to put buttons in the cell when it's 'action' row:
3) HTML:
<thead>
<tr>
<h2>head</h2>
<td ng-repeat="(key, value) in table">{{value.title}}</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="(tkey, dataValue) in data">
<td ng-repeat="(dkey, value) in dataValue">
{{value}} // and if it's 'Action' column, I want to push data from Table config to show buttons
Is it possible? Who can help me?
<thead>
<tr>
<th ng-repeat="column in table">{{ column.title }}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in data">
<td ng-repeat="column in table">
<span ng-if="column.name !== 'action'">
{{ row[column.name] }}
</span>
<span ng-if="column.name === 'action'">
<button>{{ column.button_name }}</button>
</span>
</td>
</tr>
</tbody>

Resources