How do I make an entire row clickable except for one cell and its margins in angular? - angularjs

Let's say I have a row that looks like
<tr>
<td>John</td>
<td>Smith</td>
<td>Approved?<input type="checkbox"/></td>
</tr>
Each row shows one employee, and allows you to check to approve/disapprove the employee (e.g. for registration for a course). I want the user to be able to click anywhere on the row to get greater detail about the employee, but if they click on the last column ("Approved?") it should not go to greater detail, since it should just change the checkbox.
Here are the solutions I know of, none is great:
Entire row: <tr class="clickable" ng-click="go()">. Makes all the cells and margins clickable, and only requires one ng-click entry, but then the checkbox causes "go()" to execute, which is bad.
Each cell: <td class="clickable" ng-click="go()">...<td class="clickable" ng-click="go()">. Pro: can restrict to just the cells I want. Con: lots of repetition (not DRY), and misses the margins.
Entire row with special "go" fn: <tr class="clickable" ng-click="go()">, but "go" knows how to differentiate between different cells. Pro: Has exactly the effect. Con: requires lots of view/html knowledge in a specialized controller action.
How can I make the first 2 columns and their margins clickable, but not the 3rd or its margins?

You can use two click handlers, one for a whole tr , second for a last td' checkbox. In the second use Event's stopPropagation method.
Controller:
var TableCtrl = function($scope){
$scope.click1 = function(){
console.log("Click 1 method")
}
$scope.click2 = function(e){
console.log("Click 2 method");
e.stopPropagation();
}
}
Markup:
<table ng-controller="TableCtrl">
<tr ng-click="click1()">
<td>John</td> <td>Smith</td>
<td>Approved?<input type="checkbox" ng-click="click2($event)"/></td>
</tr>
</table>
Working example: http://jsfiddle.net/zDMQB/1/

How about this?
<tr>
<td style="cursor: pointer;" ng-click="alert('hello1')">John</td>
<td style="cursor: pointer;" ng-click="alert('hello2')">Smith</td>
<td>Approved?<input type="checkbox"/></td>
</tr>

Related

React.js, handling onMouseOver event

being a noob in React I'm facing a problem: the component returns a simple nested table, so each cell of the 'big-table-id' contains another small table 'small-table-id'.
Thing is that every time the mouseover event occurs I'm always getting the 'small-cell-*' as target.id, even if the event handler is referenced in the parent (big) table. Is there any way to get the parent table kinda 'non-transparent' so that I could receive 'big-table-cell-1' or 'small-table-id'?
(using Rails with 'react-rails' gem)
var Tables = React.createClass({
handleMouseOver: function(e){
console.log(e.target.id)
},
render: function(){
return (
<table id='big-table-id' onMouseOver={this.handleMouseOver}>
<tr>
<td id='big-table-cell-1'>
<table id='small-table-id'>
<tr>
<td id='small-cell-1>
text 1
</td>
<td id='small-cell-2'>
text 2
</td>
</tr>
</table>
</td>
</tr>
</table>
)
}
});
The DOM lets you select an elements child and parent nodes with methods like firstChild and parentElement. You should look into those.
Edit: also not sure if this would work but you could try wrapping the big table in a div and setting the callback there and seeing what it references.

Hide table rows in angular Js

I have a table, I am already given it CSS using ng-class if they satisfy a condition. Now I want to show only those rows who satisfy the same condition on a button click. I have wrote a controller which checks if the data received is within 24 hours are not and marks the data cell. Until this it's working.Now I need to add a button and show only the row which has this td marked as not received in time.
<tbody>
<tr ng-repeat ="data in log">
<td>{{data.UniqueId}}</td>
<td>{{data.Name}}</td>
<td ng-class ="{'data-notreceived' : dataNotReceived('data.receivedTime')}">{{data.receivedTime
}}
</tbody>
</table>
I think something like this should work. Basically, clicking the button will toggle between showing all or only the items marked as 'data not received'.
<tbody>
<tr ng-repeat ="data in log" ng-show="showAll || dataNotReceived(data.receivedTime)">
<td>{{data.UniqueId}}</td>
<td>{{data.Name}}</td>
<td ng-class ="{'data-notreceived' : dataNotReceived('data.receivedTime')}">{{data.receivedTime}}
</tr>
</tbody>
// in controller
$scope.showAll = true;
$scope.onButtonClick = function() {
$scope.showAll = !$scope.showAll;
return false;
}
From the information provided in question what I can say is: Use ng-show to show rows based on your condition.
<tr ng-show ="your_condition">
You could also use an ng-if rather than ng-show. See the differences here.
Really depends on how often the hide/show toggle needs to happen.
<tbody>
<tr ng-repeat="data in log" ng-if="showLast24Hrs(data.ReceivedTime)">
<td>{{data.UniqueId}}</td>
<td>{{data.Name}}</td>
<td>{{data.ReceivedTime}}</td>
</tbody>
and then in the controller,
$scope.showLast24Hrs = function(receivedTime){
if($scope.isLast24Hours) {
return receivedTime < 200; // Write your less than 24 hours check here
}
return true;
}
I wrote this demo on Codepen. Hope that helps.

ui.bootstrap.collapse - one collapse for each row in a table column - open only the collapse which has been clicked (not all of them)

I'm using ui-bootstrap.collapse inside a table with dynamic data from a JSON API. Two of the multiple columns contain collapsed partials for each of its rows.
When I'm clicking on one of the icons to toggle that particular partial, every partial of the entire column open up.
Same issue when I'm trying to close the partial again - any of the icons work (not only the one of that particular partial).
I'm suspecting that I got to add a unique id or something like this to each of the partials to make one only that particular one pop up. But I'm not able to get this working.
Can any one point me in the right direction please?
Here is some of my code (I replaced the dynamic data with static data to make it simpler:
...
<tbody ng-repeat="url in urls">
<tr>
<td>{{url.url}}<span class="pull-right" ng-click="toggleUrl()">▼</span></td>
<td>{{url.title}}</td>
<td>{{url.traffic}}<span class="pull-right" ng-click="toggleTraffic()">▼</span></td>
</tr>
<!-- urlCollapsed -->
<tr collapse="!urlCollapsed">
<td colspan="4" style="background-color: pink">
</td>
</tr>
...
and a working plunker with the entire code: http://plnkr.co/edit/e4UldAFjjIr26Il73C88?p=preview
You need to pass url or some unique field to toggleUrl() method and then at the method make specific variable for each roe partial nd make them true. Accordingly you'll have to mak specific partial for each nd shoe them accordingly on ng-show.
Something like this
$scope.toggleUrl = function (url) {
if (url === '/1') {
$scope.url1Collapsed = !$scope.url1Collapsed;
} else {
$scope.urlCollapsed = !$scope.urlCollapsed;
}
};
and on page
<tr collapse="!url1Collapsed">
<td colspan="4" style="background-color: pink">partial 1</td>
</tr>
<tr collapse="!urlCollapsed">
<td colspan="4" style="background-color: pink"> partial 0</td>
</tr>

Make a single button active in a group of buttons created by a ng-repeat

I am working on a directive that displays a table using ng-repeat directives. Each cell in the table may contain a button depending on the data. Here is the pertinent snippet of the template.
<tbody>
<tr ng-repeat="row in data.rows">
<td>{{ row.rowName }}</td>
<td ng-repeat="cell in row.cells">
<button id="button-{{ row.id }}-{{ cell.id }}"
class="btn btn-primary"
ng-show="cell.isActive"
ng-click="onClick(row.id, cell.id, $event)">Select</button>
</td>
</tr>
</tbody>
In the controller I have
$scope.onClick = function (rowId, cellId, event) {
$scope.selectedRowId = rowId;
$scope.selectedCellId = cellId;
$scope.selectedButtonId = event.target.id;
};
The goal is to make it such that when a user clicks a button in the table, that button becomes active. When the user clicks on another button, it will become active making the previously active button inactive. This functionality will be used to drive what is displayed on another section of the page.
I have tried a few things, but I think the most angular way of doing things is to use ng-class in the buttons to apply the active and inactive classes based on what button has been clicked. To this end, I am assigning them all unique ids and tracking which button has been clicked based on the event.
The problem is I can not figure out how to make the ng-class work. Is there some way I can get the id of the current button that I am in, or am I going about this completely wrong in the first place.
Thanks.
In your button code set the html ng-class attribute :
ng-class="active : selectedRowId = row.id & selectedCellId = cell.id"

turn off re-sorting in angularJS while editing

I have an AngularJS app that lists a bunch of items in a table. Like this:
<table class='unstyled tmain'>
<tr>
<td ng-click='setSort($event)'>X</td>
<td ng-click='setSort($event)'>Desc</td>
<td ng-click='setSort($event)'>created</td>
<td> </td>
</tr>
<tr ng-repeat="item in items | orderBy:itemNormalizationFunction:sortReverse">
<td><input type='checkbox' ng-model='item.done'
ng-click='onCheckedChanged(item)'/></td>
<td><div edit-in-place="item.text"
on-save="updateItemText(value,previousValue,item)"></div></td>
<td><span class='foo'>{{item.created | dateFormatter}}</span></td>
</tr>
</table>
The table headers are clickable to set the sort order. The cell in the 2nd column in each data row is editable "in place" - if you click on the text it gets replaced with an input textbox, and the user can edit the text. I have a little directive enabling that. This all works.
The problem comes in while editing. Suppose I have it set to sort by "description" (the 2nd column). Then if I edit the description (via the edit-in-place directive), as I am typing in the input box, the sort order changes. If I change the first few characters, then angular re-sorts and the item is no longer under my cursor. Nor is it even focused. I have to go hunting through the list to find out where it got re-sorted to, then I can re-focus, and resume typing.
This is kinda lame.
What I'd like to do is tell angular to (a) stop re-sorting while I am keying in the input box, or (b) sort on a separate (not-displayed) index value that preserves the ordering before the edit began. But I don't know how to do either of those. Can anyone give me a hint?
I know this is sort of complicated so I'll try to put together a plunkr to show what's happening.
This is the plunkr that shows how I solved the problem.
http://embed.plnkr.co/eBbjOqNly2QFKkmz9EIh/preview
You can create custom filter and call that only when necessary. Example when you click on 'Grid header' for sorting or after dynamically adding/removing values to array, or simply click of a button(Refresh Grid)
You need to dependency Inject Angular filter and sort filter
angular
.module('MyModule')
.controller('MyController', ['filterFilter', '$filter', MyContFunc])
function ExpenseSubmitter(funcAngularFilter, funcAngularFilterOrderBy) {
oCont = this;
oCont.ArrayOfData = [{
name: 'RackBar',
age: 24
}, {
name: 'BamaO',
age: 48
}];
oCont.sortOnColumn = 'age';
oCont.orderBy = false;
var SearchObj = {
name: 'Bama'
};
oCont.RefreshGrid = function() {
oCont.ArrayOfData = funcAngularFilter(oCont.ArrayOfData, SearchObj);
oCont.ArrayOfData = funcAngularFilterOrderBy('orderBy')(oCont.ArrayOfData, oCont.sortOnColumn, oCont.orderBy);
}
}
and call in HTML something like:
<table>
<thead>
<tr>
<th ng-click="oCont.sortOnColumn = 'age'; oCont.RefreshGrid()">Age</th>
<th ng-click="oCont.sortOnColumn = 'name'; oCont.RefreshGrid()">Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="val in oCont.ArrayOfData">
<td>{{val.age}}</td>
<td>{{val.name}}</td>
</tr>
</tbody>
</table>

Resources