Having trouble with ellipsis with angularjs - angularjs

I am having issue with ellipsis and angularjs. I want to update max-width dynamically from parent as TD element width. I tried for 2 approach. One is updating dom after printing the table structure. Another is to provide directive. But nothing works.
HTML:
<table class="table data-table cvcTable sort display">
<thead>
<tr>
<th ng-repeat="column in tableOptions.columnDefs"
ng-style="{'width': column.width}"><a href
ng-click="tableEvents.sort('{{column.field}}',$event)">{{column.label}}
<i class="pull-left" ng-class="column.orderType"></i>
</a></th>
</tr>
</thead>
<tbody>
<tr ng-class-odd="'row-odd'" ng-class-even="'row-even'" ng-repeat="item in tableOptions.data">
<td>{{item.key}}</td>
<td><span title="{{item.value}}" ellipsisSpan
class="ellipsis">{{item.value}}</span></td>
<td><span title="{{item.comments}}" ellipsisSpan
class="ellipsis">{{item.comments}}</span></td>
<td>{{item.updated}}</td>
<td>{{item.updatedBy}}</td>
</tr>
</tbody>
Directive: I am not getting alert message.
app.directive('ellipsisSpan', function () {
return {
restrict: 'A',
link: function ($scope, element, attrs, ctrl) {
alert("Im inside call");
// Do calculation
}
};
});
Dynamic Call: I can see following line working perfectly but don't see updated in DOM.
"a.css('max-width', width + 'px');"
angular.element(document).ready(function () {
var element = angular.element(document.querySelector('.ellipsis'));
angular.forEach(element, function(value, key){
var a = angular.element(value);
var width = a.parent()[0].clientWidth;
a.css('max-width', width + 'px');
});
scope.$apply();
});
CSS:
.ellipsis {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
max-width: inherit;
}

Directive names get converted into dash separated case in the HTML so you need to reference your directive like this in the HTML:
<span title="{{item.value}}" ellipsis-span class="ellipsis">

Related

AngularJs direct infinite Scrolling not working

I ve got this view with a ng-repeat :
<div style="overflow: auto; max-height: 550px; min-height:550px;" >
<table class="table table-bordered table-hover " border="1" >
<thead fix-head>
<tr>
<th>Photo</th>
<th>Identifiant</th>
<th>Prénom</th>
<th>Nom</th>
<th>Editer</th>
</tr>
</thead>
<tbody >
<tr ng-repeat="footballeur in footballers| limitTo: limit " >
<td><img ng-src="img/{{footballeur.photo|| 'defaut.png'}}"/></td>
<td>{{footballeur.identifiant}}</td>
<td>{{footballeur.prenom}}</td>
<td>{{footballeur.nom}}</td>
<td><button ng-click="modifier_footballeur(footballeur)" class="btn btn-primary" aria-label="Left Align">Editer</button></td>
</tr>
</tbody>
</table>
<button ng-click="loadMore()">more</div>
And in my controller :
$scope.loadMore = function() {
$scope.limit += 5;
};
The button "more" works very well, so i'm adding 5 footballers to the ng-repeat each time i click on it.
The problem is that i want to detect the end of the div bottom, and start loadMore() each time i reach the bottom.
I've tried 3 directives and full Jquery nothing works and ingnite the loadMore() correctly..
The Jquery detects well the bottom of the div , but refuses to execute loadMore() inside its function even with angular.element syntax...
This next directive detects well the end of the div, but i dont know how to start $scope.loadMore() from it, it doesn't recognize the scope. . Maybe you should have an idea ? thanks a lot :
monApp.directive("scrollable", function() {
return function(scope, element, attrs) {
var container = angular.element(element);
container.bind("scroll", function(evt) {
if (container[0].scrollTop <= 0) {
alert('On the top of the world I\'m singing I\'m dancing.');
}
if (container[0].offsetHeight + container[0].scrollTop >= container[0].scrollHeight) {
alert('On the bottom of the world I\'m waiting.');
$('#liste').scope().loadMore();
}
});
};
})

angular-datatables - ng-repeat does not update datatable with new rows when $onChanges event called in component controller

I have made an angular-datatable component to be used in my project (using angular 1.5) and have bound the data it is populated with (the angular way) to an array of objects that gets updated in the parent scope. Upon changing the parent scope value, the $onChanges event is called and the bound data is updated, but the rows in the table do not change via ng-repeat to reflect the update -- after the table is initially drawn, no changes can be seen with subsequent data changes. Here is my code:
JS:
angular.module('datatable').
component('datatable', {
bindings: {
graphData: '<',
tableId: '=',
divId: '='
},
templateUrl: 'components/graphs/datatable.template.html',
controller: function datatableController (DTOptionsBuilder, DTColumnBuilder) {
let self = this;
self.tableKeys = Object.keys(self.graphData[0])
self.$onChanges = function () {
self.dtOptions = {
paginationType: 'full_numbers',
displayLength: 30,
dom: 'Bfrtip',
buttons: [
{extend: 'excelHtml5'},
'copy'
],
scrollY: 450,
scrollX: '100%',
scrollCollapse: true,
};
};
}
})
HTML (Component):
<datatable graph-data="$ctrl.submittedResults" table-id="'allDataTableResults'" div-id="'allDataTable'"></datatable>
HTML (Template):
<div class="col-md-10 col-md-offset-1">
<div class="well well-lg" style="background: white">
<div id="{{$ctrl.divId}}" style="width: 100%; height: 700px; display: block; margin: 0 auto">
<table datatable="ng" dt-options="$ctrl.dtOptions"
class="table table-striped table-bordered" cellspacing="0">
<thead>
<tr>
<th ng-repeat="key in $ctrl.tableKeys">{{key}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in $ctrl.graphData">
<td ng-repeat="val in row">{{val}}</td>
</tr>
</tbody>
</table>
</div>
</div>
I have tried just about everything I have seen in related questions on Stack Overflow to no avail, and I had no luck with rerendering the table completely with dtInstance. Any help would be greatly appreciated.
v0.5.5 doesn't allow '$' char in controller variable name which unfortunately is the default value in Angular Component. Override it as a workaround e.g. controllerAs: ctrl
https://github.com/l-lin/angular-datatables/blob/v0.5.5/dist/angular-datatables.js#L892
Reported this issue: https://github.com/l-lin/angular-datatables/issues/916

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" >

setting ng-href in <tr> elements

The following code makes the client.name an anchor on each client in clients. I am interested in having the entire <tr> element be that link however. ng-href does not work on the <tr> element.. what can I do so that the entire row is a single link instantiated by ng-href?
<tr ng-repeat="client in clients">
<td><a ng-href="#/user/{{client.tagid}}">{{client.firstname}}</a></td>
<td>{{client.lastname}}</td>
<td>{{client.inumber}}</td>
</tr>
What I am looking to do is something like this.. which of course does not work..
<a ng-href="#/user/{{client.tagid}}">
<tr ng-repeat="client in clients">
<td>{{client.firstname}}</td>
<td>{{client.lastname}}</td>
<td>{{client.inumber}}</td>
</tr>
</a>
OR
<tr ng-repeat="client in clients" ng-href="#/user/{{client.tagid}}">
<td>{{client.firstname}}</td>
<td>{{client.lastname}}</td>
<td>{{client.inumber}}</td>
</tr>
You can use an ng-click (instead of onClick) as Jason suggests as well.
Something like:
HTML
<tr ng-repeat="client in clients" ng-click="showClient(client)">
<td><a ng-href="#/user/{{client.tagid}}">{{client.firstname}}</a></td>
<td>{{client.lastname}}</td>
<td>{{client.inumber}}</td>
</tr>
Controller
$scope.showClient = function(client) {
$location.path('#/user/' + client.tagid);
};
And styling to make it show as an clickable element (wont work in IE7)
CSS
tr {
cursor: pointer;
}
// or
[ng-click] {
cursor: pointer;
}
I wrote a directive so that you can simply write:
<tr ng-repeat="client in clients" such-href="#/user/{{client.tagid}}">
The source:
app.directive('suchHref', ['$location', function ($location) {
return{
restrict: 'A',
link: function (scope, element, attr) {
element.attr('style', 'cursor:pointer');
element.on('click', function(){
$location.url(attr.suchHref)
scope.$apply();
});
}
}
}]);
I use my own Angular directive that automatically wraps every cell in the row with a link.
The advantages are:
You don't duplicate code.
There is a regular link in every cell so things like "Open in new tab" (middle button or CTRL+click) works as expected (in opposite of the ng-click version).
HTML usage:
<tr row-href="#/user/{{client.tagid}}">
<td>...</td>
<td>...</td>
</tr>
Directive code (in TypeSript):
export class RowHrefDirective implements ng.IDirective {
constructor(private $compile: ng.ICompileService) {
}
restrict = "A";
scope = {
rowHref: "#rowHref"
};
link = (scope: Scope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes): void => {
const cells = element.children("td[skip-href!='yes'],th[skip-href!='yes']");
cells.addClass("cell-link");
for (const cell of cells.toArray()) {
const link = jQuery(`<a ng-href="{{ rowHref }}"></a>`);
this.$compile(link)(scope);
jQuery(cell).prepend(link);
}
}
}
Required CSS code (to fill the whole cell with the link):
td.cell-link,
th.cell-link {
position: relative;
}
td.cell-link a,
th.cell-link a {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
}
This is a CSS and HTML issue, not specific to AngularJS. The only allowed child of a <tr> is a <td>, and so you need to wrap the content of each cell in an anchor. You also need to make the anchor a block element to make it the full height/width of its container:
<tr ng-repeat="client in clients">
<td>
<a style="display: block;" ng-href="#/user/{{client.tagid}}">
{{client.firstname}}
</a>
</td>
<td>
<a style="display: block;" ng-href="#/user/{{client.tagid}}">
{{client.lastname}}
</a>
</td>
<td>
<a style="display: block;" ng-href="#/user/{{client.tagid}}">
{{client.inumber}}
</a>
</td>
</tr>
<tr ng-repeat="client in clients" ng-href="#/user/{{client.tagid}}">
<td>{{client.firstname}}</td>
<td>{{client.lastname}}</td>
<td>{{client.inumber}}</td>
</tr>
This is with the referrence to the options provided which may work.
I think this binds the entire row with the each field in the row. but is not clickable. how to do that. i mean we should be able to click so that another view/module can be open.
As requested by #sfs, here’s the solution which we’re using for ui-sref (Angular 1.5; TypeScript code, apologies for any inconvenience).
Credits: The code is based on the awesome answer by Martin Volek:
import { IDirective, IDirectiveFactory, ICompileService, forEach, element } from 'angular';
export default class RowUiSrefDirective implements IDirective {
restrict = 'A';
scope = { rowUiSref: '#rowUiSref' };
constructor(private $compile: ICompileService) { }
link = (scope, elm, attrs) => {
if (elm[0].tagName !== 'TR') {
throw new Error('This directive should only be used in <tr> elements.');
}
forEach(elm.children(), (cell) => {
if (cell.attributes['skip-href'] && cell.attributes['skip-href'].value !== 'false') {
return;
}
cell.className += ' cell-link';
let link = element('<a ui-sref="{{rowUiSref}}"></a>');
this.$compile(link)(scope);
element(cell).prepend(link);
});
};
static factory(): IDirectiveFactory {
let directive = ($compile: ICompileService) => new RowUiSrefDirective($compile);
directive.$inject = ['$compile'];
return directive;
};
}
Directive initialization:
import { module } from 'angular';
import RowUiSrefDirective from './rowUiSref';
module('app').directive('rowUiSref', RowUiSrefDirective.factory());
Example usage:
<table>
<tr ng-repeat="item in itemController.items"
row-ui-sref="state.item({itemId: '{{item.id}}'})">
<td>{{item.name}}</td>
<td>{{item.label}}</td>
</tr>
</table>
An ugly solution would be to just have 1 table cell which contains the link, then within that add another table with a table row and the other cells. So it would look like;
<tr ng-repeat="client in clients">
<a ng-href="#/user/{{client.tagid}}">
<table>
<tr>
<td>{{client.firstname}}</td>
<td>{{client.lastname}}</td>
<td>{{client.inumber}}</td>
</tr>
</table>
</a>
</tr>
I do not agree with using tables for layout!
However, you are using JavaScript and angularjs, so you would be just as good adding a click event to the table row which sends the user to the url via window.location e.g.
<tr ng-repeat="client in clients" ng-click="ChangeLocation([yoururl])">
<td>{{client.firstname}}</td>
<td>{{client.lastname}}</td>
<td>{{client.inumber}}</td>
</tr>
Then have a function within your $scope to handle this;
$scope.ChangeLocation = function(url){
window.location = url;
}
Try for this...
HTML --->
<ul ng-repeat ="item in itemList ">
<li><a data-ng-href="{{getUrl(item)}}">{{item.Name}}</a></li>
</ul>
JS --->
$scope.getUrl = function (item) {
return '/<give your path here>/' + item.ID;
};
I adapted Martin Volek's Typescript code to make an AngularJS 1.x directive:
app.directive('rowHref', function ($compile)
{
return {
restrict: 'A',
link: function (scope, element, attr)
{
scope.rowHref=attr.rowHref;
var cells = element.children("td");
angular.forEach(cells, function (cell)
{
$(cell).addClass("cell-link");
var newElem = angular.element('<a ng-href="{{ rowHref }}"></a>');
$compile(newElem)(scope);
$(cell).append(newElem);
});
}
}
});
Add his same HTML and CSS

What is angular way to transform a table cell

The problem is as follows. I have a directive which builds some table, and i use ng-repeat to construct table rows dynamicly. Each row has two buttons for editing and deleting accordingly. I look for action with ng-click, but how then transform a cell with static text into a cell with an input field in angular way? I know how to do it with jquery. I look around with ng-switch, but i can't get it works inside ng-repeat on a table cell as expected. My code:
JS
order.directive('orderLines',function($http,calculateTotalQtyService,$compile){
return {
restrict: 'A',
link: function($scope,element, attrs){
$scope.editLine = function(line,order_id){
// alert ('Edit'+line.id);
some code here to perform transformation
}
$scope.deleteLine = function(idx){
var line_to_delete = $scope.order.lines[idx]
$http.post('/delete/line?id='+line_to_delete.id +'&order_id='+$scope.order.id).success(function(data){
$scope.order.lines.splice(idx,1);
$scope.order = data.ord;
$scope.order.customer = data.customer;
$scope.order.lines = data.lines;
var res = calculateTotalQtyService.set(data.lines);
$scope.total_kg = res[0];
$scope.total_piece = res[1];
});
}
},
templateUrl:'/assets/fragments/order/order_lines.html',
replace: true
}
});
and HTML
<div class="span12 fiche" id="lines">
<table class="table table-bordered" id="order_lines">
<thead class="header_lines">
<th>S.N.</th>
<th>Ref.</th>
<th>Label</th>
<th>Tva</th>
<th>Qty</th>
<th>Unite</th>
<th>Prix HT</th>
<th>Total HT</th>
<th></th>
</thead>
<tbody ng-switch="lines.length">
<tr id="no_record" ng-switch-when="0"><th colspan="9" style="text-align: center" >No records</th></tr>
<tr ng-repeat="line in order.lines">
<td>{{$index+1}}</td>
<td class='line-ref'>{{line.product_ref}}</td>
<td>{{line.label}}</td>
<td class='line-tva'>{{line.tva}}</td>
<td class='line-qty'>{{line.qty}}</td>
<td class='line-unity'>{{line.unity}}</td>
<td class='line-prix_ht'>{{line.prix_ht}}</td>
<td>{{line.prix_ht*line.qty}}</td>
<th class='control-buttons'>
<button class='btn editline' ng-click="editLine(line,order.id)"><i class='icon-edit'></i></button>
<button class='btn deleteline' ng-click="deleteLine($index)"><i class='icon-trash'></i> </button>
</th>
</tr>
</tbody>
</table>
</div>
So html is a template, that i use in directive. How perform transformation ? with ng-switch? but how, or there are other solutions ? I want to avoid jquery if it's possible. Any help would be appreciated.
So I got it with a custom directive, inspired by #laut3rry. For those who would be interested this is my solution:
Directive:
order.directive('editable', function(){
return {
restrict : 'E',
replace : true,
template: '<div><span ng-hide="editMode">{{line.qty}</span><input class="span1" ng-show="editMode" type="text" ng-model="line.qty"/></div>',
link : function(scope, element, attrs){
}
}
});
And in HTML, in my example it's for a qty cell only, that I need to change, but we can use it with any cell and with a little bit of modification, for example by passing cell value in the attribute of the directive and it can be universal:
<td class='line-qty'><editable></editable></td>
In my controller I initialize $scope.editMode = false the cell isn't editable by default and then in the ng-click="editLine()" handler we change $scope.editMode = true and the cell transforms in to the input field. So directives and directives and once more directives.... :)
For those who is interested, here the link to the plunk plunk

Resources