highlight table row using angularjs - angularjs

how to highlight a table row using angularjs. i tried in the following way but it is highlighting all rows.
I have a table in the following way,
<table>
<tr>
<th>header1</th>
<th>header2</th>
</tr>
<tbody data-ng-repeat="transaction in transactionsgroup">
<tr data-ng-click="rowHighilited($index)" data-ng-repeat="txns in transaction.transactions" data-ng-class='{selected: $index==selectedRow}'>
<td>xxxxxx</td>
<td>xxxxxx</td>
</tr>
</tbody>
</table>
controller,
$scope.rowHighilited = function(row){
$scope.selectedRow = row;
};

Is this what you are looking for ? I had to guess some mock data and also the selection behavior.
Feel free to ask for more details if this solution suites you well.
function TestCtrl($scope){
$scope.rowHighilited = function(group, row){
$scope.selectedGroup= group;
$scope.selectedRow = row;
};
$scope.transactionsGroups=[
{transactions:['test1','test2','test3']},
{transactions:['test1','test2']},
{transactions:['test1','test2']},
]
}
.selected{
background:black;
color:white;
}
/* The following just makes the tbody tags spaced up,
see http://stackoverflow.com/questions/294885/how-to-put-spacing-between-tbody-elements for details */
table {
border-collapse: collapse;
width:100%;
max-width:300px;
}
table tbody {
border-top: 30px solid white;
}
td,th{width:50%; text-align:center;}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="TestCtrl">
<pre ng-bind="{{transactionsgroups}}"></pre>
<table>
<tr>
<th>header1</th>
<th>header2</th>
</tr>
<tbody
ng-repeat="transactionGroup in transactionsGroups"
ng-init="groupIndex=$index"
>
<tr
ng-repeat="transaction in transactionGroup.transactions"
ng-init="transactionIndex=$index"
ng-click="rowHighilited(groupIndex, transactionIndex)"
ng-class="groupIndex==selectedGroup && transactionIndex==selectedRow?'selected':''">
<td>transaction:</td>
<td>{{transaction}}</td>
</tr>
</tbody>
</table>
</div>

<div ng-app="myApp">
<div ng-controller="startCtrl">
<table>
<tr>
<th>header1</th>
<th>header2</th>
</tr>
<tbody data-ng-repeat="transaction in transactionsgroup">
<tr ng-class="{active:$index==selectedRow}" data-ng-click="rowHighilited($index)" data-ng-repeat="txns in transaction.transactions">
<td>{{txns.id}}</td>
<td>{{txns.trasactionName}}</td>
</tr>
</tbody>
</table>
</div>
</div>
Your Controller.
var app=angular.module("myApp",[]);
app.controller("startCtrl",function($scope){
$scope.transactionsgroup=[
{id:1,
transactions:
[{id:1,trasactionName:"a"},
{id:2,trasactionName:"b"},
{id:3,trasactionName:"c"}
]}
];
$scope.rowHighilited=function(row)
{
$scope.selectedRow = row;
}
});
Your .css
.active{
background:yellow;
border:1px solid;
}
Working Fiddle Link
http://jsfiddle.net/Lk4me2xp/1/
This is my custom easy solution.

i tried in the following way but it is highlighting all rows
It's because you are setting common scope property which is shared by all rows. You should set selectedRow in the scope of the individual clicked row. You can refer row child scope with this inside ngClick:
$scope.rowHighilited = function(row) {
this.selectedRow = true;
// or if you also want to unselect on the second click
// this.selectedRow = !this.selectedRow;
};
and then:
data-ng-class='{selected: txns.selectedRow}'

Related

How to highlight table row based on condition in angularJs?

so I got the table where I display certain data which includes dates and other stuff. What I want is to highlight row where the displayed date is the same as the current day. Table is ordered by the dates. Any idea about this use-case?
This is my code:
<table class="table table-striped" style="font-size:14px; margin-left: 5px;">
<head>
<tr>
<th style="text-align: left;"><data-i18n i18n="_m_f_pen_feeding_start_date_">Feeding date</data-i18n></th>
<th style="text-align: left;"><data-i18n i18n="_m_f_pen_frequency_of_feeding_">Frequency of feeding</data-i18n></th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="freq in vm.details.pen_feeding_scheduler_list | orderBy:'-start_feeding_date'">
<td style="min-width: 120px; text-align: left;">{{freq.start_feeding_date | date:'shortDate'}}</td>
<td style="min-width: 120px; text-align: left; display: inline-block;white-space: nowrap">{{freq.feeding_frequency || ('_label_empty_' | i18n)}}</td>
</tr>
</tbody>
</table>
In my controller i set current date as :
vm.current_date = new Date().toISOString().slice(0, 10)
If you need more code, I can provide it. Thanks in advance
Here is fiddle link for a simple example. You can modify it as per your need.
<div ng-class="getClass()">text</div>
Controller:
var myModule = angular.module('app', []);
var current_date = new Date().toISOString().slice(0, 10);
myModule.controller('myCtrl', function ($scope) {
$scope.getClass = function(){
if(current_date == '2020-07-23'){
return 'blue';
}else{
return 'red';
}
}
});
http://jsfiddle.net/5oc3fqzj/

How do I add an icon within a td at the end of each row using ng-repeat?

I have a 2-dimensional array.
I am using it as a source to populate an html table using angularjs ng-repeat.
I want to add an icon at the end of each row.
It works on the first two rows, but then the next several rows contain only the icon.
<div ng-app="myApp" ng-controller="tblCtrl">
<table id="tableToFilter" class="w3-table-all w3-small w3-row" ng-cloak>
<tr class="w3-blue w3-mobile">
<th data-row="0" data-col="{{$index}}" ng-repeat="columns in header">{{columns}}</th>
<th></th>
</tr>
<tr class="w3-mobile" ng-show="{{$index > 0}}" ng-repeat="rows in table">
<td data-row="{{$parent.$index}}" data-col="{{$index}}" ng-repeat="columns in rows">{{ columns }}</td>
<td><i class="material-icons editIcon">edit</i></td>
</tr>
</table>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('tblCtrl', function($scope) {
$scope.table = datags;
$scope.header = datags[0];
});
</script>
'datags' above is a 2-dimensional array in json.stringify format.
It does not have key/value pairs.
It is 94 rows and 9 columns. I am using css to prevent displaying columns 0,4,7,8 so that my table fits on my screen. (I'm sure there's a cleaner way to do this.)
<style>
td[data-col="0"], th[data-col="0"] {
display: none;
}
td[data-col="4"], th[data-col="4"] {
display: none;
}
td[data-col="7"], th[data-col="7"] {
display: none;
}
td[data-col="8"], th[data-col="8"] {
display: none;
}
</style>
screenshot of my table
What am I doing wrong?
I did figure it out. I think ng-repeat was perceiving the blanks as duplicates. I added track by $index and now it works. <tr class="w3-mobile" ng-show="{{$index > 0}}" ng-repeat="rows in table track by $index"> <td data-row="{{$parent.$index}}" data-col="{{$index}}" ng-repeat="columns in rows track by $index">{{ columns }}</td> <td><i class="material-icons editIcon">edit</i></td> </tr>

Angular Js swap columns in table

I would like to swap 2 columns in a table. Finally, I succeeded the change, but only the data. The attributes of the cell (style, id, class) didn't move. I tried to move attributes with jquery (i know, not an elegant method), but it was only symptomatic treatment. After clicking the data reload button, the attributes restored.
How can I change the columns order with all attributes?
my code: https://codepen.io/qwertz_/pen/YxWMBO
<!DOCTYPE html>
<html>
<head>
<title>angT</title>
<script type="text/javascript" src="http://code.angularjs.org/angular-1.0.0rc10.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<style>
th, td{padding: 3px 20px;border: 1px solid red;}
</style>
</head>
<body>
<div ng-controller="MyCtrl" ng-app="myApp">
<button ng-click="swap(0)">first2second</button>
<button ng-click="reload()">reload</button>
<table id="myTable" >
<tr ng-repeat="row in ths">
<th class="oo1">{{col(row, 0)}}</th>
<th class="oo2">{{col(row, 1)}}</th>
<th class="oo3">{{col(row, 2)}}</th>
<th class="oo4">{{col(row, 3)}}</th>
</tr>
<tr ng-repeat="row in rows">
<td class="o1" style="background-color:yellow;">{{col(row, 0)}}</td>
<td class="o2" style="background-color:pink;">{{col(row, 1)}}</td>
<td class="o3" style="background-color:green;">{{col(row, 2)}}</td>
<td class="o4" style="background-color:blue;">{{col(row, 3)}}</td>
</tr>
</table>
</div>
<script type='text/javascript'>
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.mycol = new Array();
$scope.mycol[0] = 'id';
$scope.mycol[1] = 'name';
$scope.mycol[2] = 'db';
$scope.mycol[3] = 'let';
$scope.reload = function()
{
$scope.rows=[{id:parseInt(Math.random()*10000),name:"Liv","db":21,let:"r"},{id:parseInt(Math.random()*10000),name:"Mike",db:30,let:"u"}];
};
$scope.swap = function(i) {
var temp = $scope.mycol[i];
$scope.mycol[i] = $scope.mycol[(i+1)];
$scope.mycol[(i+1)] = temp;
};
$scope.col = function(row, mycol) {
return row[$scope.mycol[mycol]];
};
$scope.reload();
$scope.ths=[{id:"id",name:"name","db":"db",let:"letter"}];
}
</script>
</body>
Thx a lot
Simple way
You can bind colors to header name as:
$scope.styles = {
id: "yellow",
name: "pink"
};
and table will look like:
<tr ng-repeat="row in rows">
<td class="o1" ng-style="{'background-color':styles[mycol[0]]}">{{col(row, 0)}}</td>
<td class="o2" ng-style="{'background-color':styles[mycol[1]]}">{{col(row, 1)}}</td>
<td class="o3" style="background-color:green;">{{col(row, 2)}}</td>
<td class="o4" style="background-color:blue;">{{col(row, 3)}}</td>
</tr>
Once header value changes, colors will change too
Codepen DEMO
More complicated but generic
You can achieve it by replacing all table with directive (headers + data) and by using $compile rebuild all HTML table.

Setting a table onclick using AngularJS ng-repeat

My static html table has a row click event which hightlights a div.
The static table is working fine, but my ng-repeat table has some issues.
I can now highlight my div with a red border, but how do I remove the border when something else is clicked ?
Here's the static table example :
<script type="text/javascript">
$('.image-clicked').click(function () {
debugger;
$(this).css("border", "2px solid red");
});
$('.clickable_row td div').click(function (e) {
// clear all borders first, highlight clicked image
var imageclicked = $(this).data('url');
$('.propertyTable td div').css("border", "none");
$(this).css("border", "2px solid red");
});
</script>
<table id="gadgets" class="propertyTable clickable_row">
<tr>
<th>Type</th>
</tr>
<tr>
<td data-url="chart_treelist">
<div><img data-draggable id="chart_treelist" src="images2/table.png" title="Tree Grid" alt="Hierarchy Grid" width="64" height="64">Grid</div>
</td>
<td data-url="{chart_pivot}">
<div><img data-draggable id="chart_pivot" src="images2/pivottable.png" title="Pivot Table" alt="Pivot Table" width="64" height="64">Pivot</div>
</td>
</tr>
<tr>
<td>
<div><img data-draggable id="chart_bar" src="images2/bar.png" title="Bar" width="64" height="64">Bar</div>
</td>
<td>
<div><img data-draggable id="chart_line" src="images2/line.fast.png" title="Line" >Line</div>
</td>
</tr>
<tr>
<td>
<img data-draggable id="chart_pie" src="images2/pie.png" title="Pie" alt="Pie" width="64" height="64">Pie
</td>
<td><img data-draggable id="chart_area" src="images2/area.png" title="Area" alt="Area" width="64" height="64">Area</td>
</tr>
<tr>
<td>
<img data-draggable id="chart_scatter" src="images2/point.png" title="Scatter" width="64" height="64">Scatter
</td>
<td>
<img data-draggable id="chart_bubble" src="images2/bubble.png" title="Bubble" width="64" height="64">Bubble
</td>
</tr>
</table>
And here is the AngularJS ng-repeat generated table.
FYI: ng-class assigns the image-border class if the initImage values are equal. ng-click goes into the controller and reassigns the chart based on what was just selected.
PROBLEM: I cannot figure out how to select a NEW chart icon with red border, and simultaneously REMOVE the image-border class on the others.
(function () {
'use strict';
angular.module('rage')
.controller('GadgetIconsCtrl', ['$rootScope', '$scope', icons]);
function icons($rootScope, $scope) {
var gadgets = this;
gadgets.subset = null;
gadgets.chartSelected = null;
gadgets.selectChart = function (chart) {
// the assumption is that user selected a different chart icon from the formatting tab
gadgets.chartSelected = chart;
};
if ($scope.widget.gadgetType == 'chart' && $scope.widget.chartType == 'bar') {
// user is configuring a bar chart type, so we also include 'column' in our subset of icons to display
gadgets.subset = _.filter($scope.widgetDefs, function (item) {
return item.chartType == 'bar' || item.chartType == 'column';
});
}
}; // end of gridSettings()
})();
<style scoped>
.image-clicked {
border: 2px solid red;
}
.image-unclicked {
border: 2px solid red;
}
</style>
<table ng-controller="GadgetIconsCtrl as gadgets" >
<tr ng-repeat="gadget in gadgets.subset" >
<td>
<!-- the image icon for this widget should have a css border, otherwise none -->
<div ng-class="{'image-border': gadget.initImage===widget.initImage}">
<img ng-click="gadgets.selectChart(gadget.name)" ng-src="{{gadget.initImage}}" title="{{gadget.title}}"
width="64" height="64">{{gadget.title}}
</div>
</td>
</tr>
</table>
I'm sure there's a better Angular approach to this, but I'm still trying to figure out the best use of ng-click and ng-class in this use-case.
Help is appreciated.
thanks,
Bob
I started a new plnkr http://plnkr.co/edit/w3Ojy5Eo40QHDtUxJfft
for your question.
You can use ng-clik and inject click event (and affected element) into the handler:
$scope.widgetClick = function($event) {
$event.srcElement.style.border = "2px black solid";
}
Corresponding html:
<div class="image-clicked" ng-click="widgetClick($event)"> ... </div>
For simple dom manipulation, like adding or removing a css class, its better to use angular only instead of mixing things up with jQuery.
Dealing with dom/css changes by yourself is more "jQuery way".
With Angular on the other hand, you will change the data for your model and
let the framework do the dom/css work.
For your example (using my plunkr code):
Define widget for ng-repeat as something like:
{
title : "Foobar ",
initImage : "http://lorempixel.com/10/10/",
clicked: false
}
and change clicked in the handler:
$scope.widgetClick = function(widget) {
widget.clicked = true;
};
Corresponding html:
<div ng-click="widgetClick(widget)" ng-class="{clicked: widget.clicked}">
The css class .clicked will be added by angular if widget.clicked changes to true.
Why this is better? No Css/Dom manipulation in your code. Everything clean and nice.
EDIT:
How to remove the .clicked class from previously selected widget?
We will need to keep a reference to the selected widget in the controller:
var selectedWidget = null;
$scope.widgetClick = function(w) {
if(selectedWidget) selectedWidget.clicked = false;
selectedWidget = w;
w.clicked = true;
};
Now, when another widget is selected (clicked), we only need to update the model data: Set the clicked property on the previously selected widget to false and change it to true on the selected one. And update the reference to the selectedWidget. Angular will take care about the css.
Updated plnkr http://plnkr.co/edit/IqWc1W9N12SH8K72jAun?p=preview
Try this !! cannot run angular now, but I think it should work!
< script type = "text/javascript" >
var lastobj = "";
function clickImage(obj, $event) {
debugger;
if (lastobj != obj) {
$(lastobj).css("border", "0px");
} else {
$($event.target).css("border", "2px solid red");
}
};
function clickRow(obj, $event) {
//obj should be the widget
//There you should do similar..
var imageclicked = $($event.target).data('url');
$('.propertyTable td div').css("border", "none");
$($event.target).css("border", "2px solid red");
}); < /script>
<table ng-controller="GadgetIconsCtrl as gadicons">
<tr ng-repeat="widget in gadicons.widgetSubset">
<td>
<div ng-click="clickRow(widget)" class="image-clicked">
<img data-draggable ng-click="clickImage(widget)" ng-src="{{widget.initImage}}" title="{{widget.title}}" width="64" height="64">{{widget.title}}
</div>
</td>
</tr>
</table>
EDIT
I added the unset border functionality u told, and corrected some spelling and grammar mistakes for angularjs.
Hope it works!!

Dragging a table column using HTML5 and AngularJS

http://jsfiddle.net/asutosh/82qum/
<div ng-app='myApp'>
<div ng-controller="myCtrl">
<table border="4">
<thead>
<th ng-repeat="hd in heads">
<div draganddrop drag="handleDrag()">{{hd}}</div>
</th>
</thead>
<tr ng-repeat="row in myData">
<td ng-repeat="hd in heads">
{{row[hd]}}
</td>
</tr>
</table>
</div>
Here is the JS:
var myApp=angular.module('myApp',[]);
myApp.controller('myCtrl',function($scope){
$scope.handleDrag=function()
{
}
$scope.heads=['name','age','company','tech'];
$scope.myData=[{name:'Jay',age:27,company:'XYZ',tech:'Js'},
{ name:'Rayn',age:30,company:'XYZ',tech:'.net'}]
});
myApp.directive('draganddrop',function(){
return{
scope:{
drag:'&'
},
link: function(scope, element) {
// this gives us the native JS object
var el = element[0];
el.draggable=true;
el.addEventListener(
'dragstart',
function(e) {
e.dataTransfer.effectAllowed = 'move';
// this.classList.add('drag');
return false;
},
false
);
el.addEventListener(
'dragend',
function(e) {
this.classList.remove('drag');
return false;
},
false
);
}
};
});
In the above fiddle I want to create a table having column reordering, I am able to set the column header to draggable however while dragging only the header's image is getting dragged, I want the the image of the whole column should come as the dragging image, any suggestion on that will be helpful.
The following solution works with Chrome's latest version, and this solution is implemented using AngularJS 1.4 version:
The change in the code is:
var headerElem=e.target.closest('th');
var textOfHeader=angular.element(headerElem).find("a");
scope.$apply(function() {
scope[dropfn](data, textOfHeader[0]);
});
http://plnkr.co/VDygHR
If you want to use a plugin instead of implementing it yourself you can choose from:
http://ng-table.com/
http://ui-grid.info/
http://lorenzofox3.github.io/smart-table-website/
http://ekokotov.github.io/object-table/
They all support column reorder and a lot of other features, I believe there are a lot of other solutions around.
http://jsfiddle.net/asutosh/82qum/142/
Following is HTML Code:
<div ng-app='myApp'>
<div ng-controller="myCtrl">
<table ng-hide={{dragStart}} id="hidtable" border="4" >
<thead>
<th>{{dragHead}}</th>
</thead>
<tr ng-repeat="row in myData">
<td>{{row[dragHead]}}</td>
</tr>
</table>
<div class='dragstyle' id="coverup"></div>
<table border="4">
<thead>
<th ng-repeat="hd in heads">
<div draganddrop drag="handleDrag">{{hd}}</div>
</th>
</thead>
<tr ng-repeat="row in myData">
<td ng-repeat="hd in heads">
{{row[hd]}}
</td>
</tr>
</table>
</div>
</div>
Following is the CSS:
.dragstyle{
background: white;
width:200px;
color:white;
height: 100px;
position: absolute;
top: 0;
right: 0;
z-index: 2;
}
#hidtable{
height: 100px;
position: absolute;
top: 0;
right: 0;
z-index: 2;
}
Following is the JS:
var myApp=angular.module('myApp',[]);
myApp.controller('myCtrl',function($scope){
$scope.handleDrag=function(columnName)
{
$scope.dragHead=columnName;
};
$scope.dragHead='name';
$scope.heads=['name','age','company','tech'];
$scope.myData=[{name:'Jay',age:27,company:'XYZ',tech:'Js'},
{name:'Rayn',age:30,company:'XYZ',tech:'.net'}]
});
myApp.directive('draganddrop',function(){
return{
scope:{
drag:'='
},
link: function(scope, element,attrs) {
var el = element[0];
el.draggable=true;
el.addEventListener(
'dragstart',
function(e) {
e.dataTransfer.effectAllowed = 'move';
var columnName=e.target.innerHTML;
scope.$apply(function(self){
console.log(self);
scope.drag(columnName);
});
e.dataTransfer.setDragImage(document.getElementById('hidtable'), 0, 0);
;
return false;
},
false
);
el.addEventListener(
'dragend',
function(e) {
this.classList.remove('drag');
return false;
},
false
);
}
};
});
So this way I have created a box with width of 200px and having background color as white, under that the 'hidetable' element is present, so it's visible to the browser but not to the user.
When the drag event occurs at any column head element, the 'hidetable' element is set as the drag image.
This drag'n'drop library will do it for you:
https://github.com/lorenzofox3/lrDragNDrop
Just include it in your app, and make your <th> say this:
<th lr-drag-src="headers" lr-drop-target="headers" ng-repeat="hd in heads" >

Resources