How to perform row double click event in kendo ui grid angular 2? - angularjs

How to display orginal cell value in cell template <span> tag in angular 2 kendo ui grid.
Code
<ng-container ngFor="let col of grid.ColModel">
<kendo-grid-column [title]="col.Label" [field]="col.Name" [locked]="col.Locked" width="250px" *ngIf="hiddenColumns.indexOf(col.Name) === -1" >
<template kendoCellTemplate let-dataItem let-rowIndex="rowIndex" >
<span (dblclick)="open(rowIndex)">**{{dataItem}}** </span>
</template>
</kendo-grid-column>
</ng-container>

The example provided by Melanie might have worked in the past, but will not work with the Angular 2/4 Grid (if you click on the plunker, it won't load).
I have to do lots of debugging as I ran into the same issue.
The solution in a simple grid was as follows:
<kendo-grid #myGrid [selectable]="true" (dblclick)="dblClickEvent(myGrid, $event)">
<kendo-grid-column field="User" title="User" width="100">
</kendo-grid-column>
</kendo-grid>
in your .ts file, implement the event as follows:
dblClickEvent(grid, event) {
// debugger;
console.log('the selected row Index is '+ event.path[1].rowIndex);
//use the following line if you want to get the clicked cell content:
console.log('clicked cell content'+ event.path[0].textContent);
}
This would give your the selected row index, from which you can
Hope this helps.

The first argument in your double-click handler needs to be the double-click event (which you can access as $event in your template). You should pass that first and rowIndex second.
In addition, you're probably missing a lot of click events since you're using a span and your content is inside of a padded cell. I'd recommend that you make your entire cell a click target, for example by changing it to a div and getting rid of the padding on the containing td.
So your cell template might look like:
<kendo-grid-column field="MyField">
<template kendoGridCellTemplate let-dataItem let-rowIndex="rowIndex">
<div class="innerCell" (dblclick)="onRowDoubleClick($event, rowIndex)">
{{dataItem.MyField}}
</div>
</template>
</kendo-grid-column>
And your function:
onRowDoubleClick(evt, rowIndex) {
alert('You clicked row ' + rowIndex + '!');
}
And your styling:
td { padding: 0 !important; }
td > .innerCell { padding: 7px; cursor: pointer; }
Example: Plunker

Update:
If you have a sortable grid, you need to implement cellClick and dblClick like here:
https://stackblitz.com/edit/angular-ac3jzd?file=app/app.component.ts
This works for both: sorted and non sorted kendo grids
Orginal answer:
We like to define the dblclick on the grid and not on each column, So the answer from Adam works for us perfectly in chrome, but not in firefox.
Problem is that the path property is non-standard on the mouseevent and not provided in firefox (probably not in safari too)
Based on Adam's solution, we have solved it with:
<kendo-grid [selectable]="true" (dblclick)="dblClickEvent($event)">
<kendo-grid-column field="User" title="User" width="100"></kendo-grid-column>
</kendo-grid>
and:
dblClickEvent(event) {
let rowIndex;
if (event.path) { // works on chrome and all browsers supporting path property in mouseevent
rowIndex = event.path[1].rowIndex;
} else { // should work on all browsers
rowIndex = event.target.parentElement.rowIndex;
}
if (typeof rowIndex === 'number' && rowIndex < this.data.length) {
// do something
}
}
(this aussumes that the user has clicked inside a td-element)
Note: this does not work if the grid was sorted

Related

Radio button deselects itself on clicking anywhere on the page

I am trying to implement segmented control button instead of normal radio button in Angular
Although If i remove CSS class, normal radio button is working fine and remain selected on navigating to another page os clicking anywhere on the same page, but after adding CSS, radio button selection do not remain intact and deselects.
Please help with this
HTML Code :
<div class ="segmented-control">
<div ng-repeat="p in LP">
<a href="#" class="list-group-item">
<label> {{p.label}}
<input type ="radio" ng-model="test" name="test" value="{{p.value}}" ng-click="getElement($event)"></label>
</a>
</div>
</div>
CSS :
.segmented-control input[type="radio"] {
visibility:hidden;
}
.segmented-control .list-group-item {
display: inline-block;
}
In controller.js
calling below function to get the value of radio button
$scope.getElement= function(obj){
$scope.test = obj.target.value;
}
There are 2 issues with your code:
You have nested elements <div><a tag><label><radio></label> but the ng-model will be set only when you click exactly on the label. If you click little outside the label the ng-model will not be updated.
The gray color change that you see when you click on the segmented button does not mean that the radio button is selected. It is applying the following bootstrap class a.list-group-item:focus which means the button is in focus. That is why when you click outside the button the color changes back to white.
To solve this you have to add extra class to highlight the selected button and make sure your ng-model is updated no matter where the user clicks inside the div.
I have created a sample jsfiddle to demonstrate both the issues. Good luck and welcome to Stackoverflow!

Expand and collapse row for ng-grid

I am trying to achieve an expand and collapse row for ng-grid.
Basically what we have to do, if you click on a row it displayed with more detail.
Does anyone know how to achieve this?
Any help appreciated.
Quick and dirty example. This is not specific to ngGrid but I believe the concept should carry over. (IF not please feel free to yell at me :) )
<div class="row" ng-repeat-start="item in items" ng-click="item.expanded = !item.expanded"></div>
<div class="row-details" ng-if="item.expanded"></div>
Currently nggrid doesn't support this feature issue #1111 and its being implemented in UIGrid 3.0 version.
But i have found a workaround and this is how you can try to achieve in nggrid using rowTemplate and a little bit of jquery. hope this helps!
rowTemplate:
<div class="row">
// add column data
// expand or collapse image
<div class=\"col-xs-1 col-md-1\"><img "id='showHide_{{row.rowIndex}}' ng-src='src/img/{{imgArrowRight}}' ng-click=\"rowExpand (row.rowIndex);\"/></div>
</div>
<div id='expRowId_{{row.rowIndex}}' style=\"display:none;\">< div class=\"expData\">< span ng-bind=\"row.entity.Attr\">< /span>
//add whatever you want in the expanded row.< /div>< /div>
//Defined customArray for handling dynamic row Toggle
angular.forEach($scope.gridData, function(row,index) {
$scope.customArray[index] = true;
});
//row expand code
$scope.rowExpand = function(index){
$scope.customArray[index] = $scope.customArray[index] === false ? true : false;
if($scope.customArray[index]){
$('#showHide_'+index).attr('src','src/assets/img/rigthIcon.gif');
$('#expRowId_'+index).hide();
}else{
$('#showHide_'+index).attr('src','src/assets/img/downIcon.gif');
$('#expRowId_'+index).show();
}
}
Also override ngRow styleclass
.ngRow {
position: relative !important;
}

Both "clickable" and "draggable" area

I have a list of element inside an ng-repeat for which elements are clickable and draggable : if I click I display, and if I drag ... I drag the element.
When dragging I am displaying a circle with the number of element to drag.
My problem is that when a click, the drag circle is displayed. Whereas I just want to click and not drag.
Is there a way to set like 2s when clicking, like a long press action (with the mouse) to distinguish the click from the drag actions ?
It is similar to this post but now I want to prevent the drag when clicking (in the Angular way).
Here some markup :
<div class="docs-manager-doc box-container" ng-class="{'showActions':doc.showActions}">
<a class="box-square" ng-href ng-click="docsManager.toggleDocumentSelection(doc)">
<span class="flaticon-dark"
ng-class="{ 'flaticon-video-embed':(!doc.selected && doc.ref && doc.targetType==='EMBEDDED_VIDEO'),
'flaticon-{{doc.label | docExtMap}}':!doc.selected && !doc.ref,
'flaticon-tick':doc.selected }" ibp-prevent-drag>
</span>
</a>
<a ng-drag="true" ng-drag-data="doc" ng-drag-success="onDragComplete($data)" ng-drag-begin="onDragStart($data)" ng-drag-stop-move="onDragStop($data, $event)">
<span class="box-drag">
<span class="dragging" ng-show="iamdragging" >
<span class="flaticon-dark flaticon-small">
<p class="flaticon-default-doc">{{docsManager.documents.selected.length}}</p>
</span>
</span>
</span>
</a>
</div>
I am using ngDraggable directive.
Here some code if it helps :
.controller('DocumentsManagerCtrl', ['...',
function(...) {
$scope.iamdragging = false;
$scope.onDragStop = function(data, event){
$scope.iamdragging = false;
};
$scope.onDragStart = function(data){
if(!data.selected){
$scope.docsManager.toggleDocumentSelection(data);
}
$scope.iamdragging = true;
};
$scope.onDragComplete = function(){
// do something
};
May be it could be good to have a directive like ng-click-or-drag, when the click is more than 2s it is interpreted as a drag.
The issue has been solved here partially. https://github.com/fatlinesofcode/ngDraggable/issues/12. Posting in case it is useful to someone else browsing the question.
Setting ng-prevent-drag="true" on any element that you do want to initiate drag action, disables the drag action initiation on that object.
I guess benek who has asked this question is also involved in the discussion in the link above. he has indicated that this breaks on ipad, however I have tested this on laptop where it works.
I have implemented ng-drag-after-timeout="2000" attribute which allows to manage this.
The patch is here https://github.com/advantiss/ngDraggable/commit/51bd0e16b3f363935b249b2ee185968f4999f87d
I fixed this by making my image (which was a problem) a vice .
The DIV had a background-image: url();
Problem solved for me

ng-grid hiding bootstrap styled dropdowns

I am upgrading a table form. Each row in the table has several elements, including two drop downs in specific columns for each row. I have upgraded the table to ng-grid and upgraded the drop-downs from plain select widgets to styled bootstrap drop-down elements to match the others on the site. The essential problem I am having is that the CSS layout of ng-grid causes the actual drop down menu to be put behind the cell below, and so not visible. Examining the elements shows that they are actually being rendered, have proper height, width and content, but are merely displayed behind the content in the other cell. I have tried disabling the CSS overflow: hidden on the desired cells, but it seems this property is also set for the entire grid and turning it off at that level totally breaks the grid layout. I have a working workaround, but it makes me want to take a shower and I am sure there is a more elegant way to do this:
1) put a cell template in for just the visible part, including an ng-click call passing the column (Coffeescript):
{field: "type",
displayName: "Type",
width: 155,
original_width: 155,
pinned: false,
cellClass: "type_col",
headerClass: "type_col",
cellTemplate: """<div ng-click="editor.activeCol(col)" class="btn-group">
<button ng-show="row.entity[col.field]" style="width: 125px"
class="btn dropdown-toggle blk-txt" href="#">
{{row.entity[col.field]}}</button><button class="btn">
<span class="caret"></span></button></div>"""
},
2) Put a select row callback to a different method:
multiSelect: false,
enableRowSelection: true,
afterSelectionChange: angular.bind(#, selectFunc),
3) Have a totally separate angular template of the drop-down options that is classed to always be shown open for bootstrap, but has both a ng-show and ng-style elements to allow my code to change its visibility and exact location:
<div ng-show="editor.utilization" ng-style="editor.dropdown_style">
<div class="btn-group editor-widget open">
<ul class="dropdown-menu">
<li ng-click="editor.selectUtil('heavy')">Heavy</li>
<li ng-click="editor.selectUtil('medium')">Medium</li>
<li ng-click="editor.selectUtil('light')">Light</li>
</ul>
</div>
</div>
When a user clicks on the (apparent) drop down, the following happens:
1) ng-click event delivers the column to the class, this is stored
2) row select (afterSelectionChange) callback triggers with the row and is able to get the column from the previous call, with both the row and column we now know the actual cell
3) The exact screen position of the cell in question is grabbed and the drop-down selections template is made visible directly below the clicked cell, making the illusion of a normal drop-down operation.
This is a long explanation, but wanted to give the background of what I have tried, to show that I am looking for a simpler (hopefully MUCH simpler) way to just include styled bootstrap drop-down widgets in ng-grid cells. The entire thrust of this project is to style and beautify already working forms so solutions that work only by cutting style for pure functionality don't really serve the purpose.
This is how I solved it. I have a cell in the ng-grid and in the cell i have a glyphicon arrow down. When I click it I want the dropdown toggle to show. With the CSS I got what I wanted. However, I have many cells with arrows and thus I had to change the css-style "left" dynamically. I do this with my javascript.
Hope it helps!
Cell Template:
<div class="ngCellText" ng-class="col.colIndex()" class="dropdown">
<span ng-cell-text>{{row.getProperty(col.field)}}</span>
<a class="dropdown-toggle" ng-click="setXchords($event)">
<i class="glyphicon glyphicon-chevron-down"></i>
</a>
<ul class="dropdown-menu">
<li ng-repeat="choice in editableItems">
<a>{{choice}}</a>
</li>
</ul>
</div>
CSS:
.dropdown-menu {
position: fixed;
top: inherit;
left: 85px;
}
JavaScript:
$scope.setXchords = function(e) {
var elem = angular.element(e.currentTarget);
$(elem).next().css('left', e.clientX).css('top', e.clientY);
};
In order to show regular dropdowns, I added this css:
.ngCell { overflow: visible; }
In order to get multiselects to appear, I needed to add a class (I used "field-multiselect") to an editableCellTemplate and then add the following css to the class:
.field-multiselect {
position: relative;
overflow: visible;
z-index: 888; }
This worked for me! (Finally, after quite a bit of trial and error!)

Angularjs: custom grid component, dynamically add <br> elements

Ok, I have made a really simple grid component. I fetch a column count attribute and add a <br> tag after the end of a row. I do that within the link function.
Her is the directive: http://pastebin.com/U4ckuKJw
grid.html just looks like this: <div class="grid" data-ng-transclude=""></div>
In my first example I have 7 <div> tags inside the grid component and want to have 3 columns. So after every third <div> I want a <br> to be added.
It looks like this and is working:
<div data-grid="" data-cols="5">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
</div>
This one is not working: http://pastebin.com/wtcgM2Hv
I think it is because of the directive ng-repeat and that the content of the grid component isn't rendered at the time the link function ist executed.
Any thoughts on how to solve this problem or how to optimise the component?
An easier approach may be to solve the problem with standard angular directives and css. For instance, if you float your cells and clear: left on those cells that start a new row, you can use ng-repeat and ng-class to accomplish this.
I created an example at: http://jsbin.com/idukaz/1
The html looks like this. Note I'm using ng-class to apply the class that formats the cell that needs to start a new row depending on the result of calling the custom columnEnd function. columnBreak is a scope variable for the number of columns you want. $index is a variable generated by ng-repeat:
<div class="table">
<div class="label"
ng-class="{'new-row': startNewRow($index, columnBreak) }"
ng-repeat="item in items">{{ item.name }} ({{ $index + 1 }})</div>
</div>
In your controller:
app.controller('Controller', ['$scope', function (scope) {
// list of grid data
scope.items = [];
// controls the number of columns
scope.columnBreak = 5;
// calculates if current cell is start of new row
scope.startNewRow = function (index, count) {
return ((index) % count) === 0;
};
}]);
In your css if you float your cells and clear left, you'll get your columns to dynamically
reformat when you change the columnBreak value.
.label {
float: left;
}
.new-row {
clear: left;
}
Ok, now I found the solution:
use angular directive to change classes of ng-repeat elements
I mixed it with Marks idea and manipulate the css classes now.
Thanks

Resources