prime-ng drag/drop in combination with reorder is not working - drag-and-drop

I am trying to work on a prime ng table with both drag/drop and reorder enabled.
I can only have one working at a time, but when I enable both functionalities only reorder works.
Looked at the source and looks like the drop event is consumed at the reorder. I have an working example at
demo
Here if you remove the [pReorderableRow]="index"from "Available" table drag drop works into the "Selected" section.
Is there a way to have both reorder and drag/drop working together.
Thanks

try to bind this events in the table
(onDragStart)="dragStart(product)" (onDragEnd)="dragEnd()"
here's a sample
<tr pDraggable="products" [pReorderableRow]="index" (onDragStart)="dragStart(product)" (onDragEnd)="dragEnd()">
then at the typescript file try adding the function dragStart(product) and dragEnd()
dragStart(data){
//console.log(data);
}
dragEnd(){
this.drop();
}
trigger the drop() method in the dragend() method.
i tested it from the demo link you provide:
[link]https://stackblitz.com/edit/primeng-tablereorder-dragdrop-demo?file=src/app/app.component.html

Related

How to implement drag and drop functionality in Angular Material Table?

I am able to to implement drag and drop functionality using ng2-dragula but the problem I am facing that it drags the header row as well and also unable to get the dragged row values(its row data )and the row above and below from the dragged row.
Can anyone help me this ?
I also found the same issue on github
https://github.com/valor-software/ng2-dragula/issues/831
<mat-table [dataSource]="dataSource"
matSort matSortActive="categoryName" matSortDirection="asc" matSortDisableClear
[dragula]='"seventh-bag"'>
<ng-container matColumnDef="seqNo">
<mat-header-cell *matHeaderCellDef>S.No.</mat-header-cell>
<mat-cell *matCellDef="let row;let i=index;">
{{(paginator.pageSize * (paginator.pageIndex)) + i+1}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef mat-sort-header (mouseenter)="nameIcon=false" (mouseleave)="nameIcon=true">
Category Name
<i *ngIf="nameIcon && sort.active=='join'" class="fa fa-sort"></i>
</mat-header-cell>
<mat-cell
*matCellDef="let catg;">
name
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns"
(click)="selectedRow(row)" [ngClass]="{'highlight': selectedRowIndex == row._id}"
(mouseenter) ="dragRow = row" (mouseleave) ="mouseLeave('div A')"
>
{{row}}
</mat-row>
</mat-table>
When I use the above approach, then I am unable to fetch the dragged row data and its new position
2.) When I implement ng2-dragula
<mat-row *matRowDef="let row; columns: displayedColumns"
(click)="selectedRow(row)" [dragula]='"seventh-bag"'
>
then the drag and drop functionality not works well
Please refer to the picture below
Image Source:- https://user-images.githubusercontent.com/6483007/36256531-4a34b638-124b-11e8-9b13-cd15391886ae.gif
This may not be an exact answer to your question regarding dragula but seeing no-one has had a go yet here is a possible solution that seems to be working for me: I tried getting drag and drop working with mat-table as well. I didn't use ng2-dragula (i used jquery ui-sortable in the past), but i did get somewhere with angulars new CDK drag and drop system. (now in 7.0.0).
https://material.angular.io/cdk/drag-drop/overview
The only issue i had with this is that if you are wanting to do sorting, the cdkDropList directive had to be a direct parent to the cdkDrag elements, not sure if there is a way around this and i couldn't find an option saying otherwise.
seeing that mat-tables don't seem to be constructed in a way that works nicely with d&d I've turned to lists or expansion-panels (if you want the drop down for extended forms on each row) as they seem to behave better when being nested and work well with the drag and drop tools by cdk. (you will probably need to do some custom styling to get it looking like a table)
I realise it wont come with the sorting, filtering features mat-table comes with but if you are prioritising the d&d you may have to find another way around it.
Hope that gives you something to work with!

Waiting for sap.ui.table.Table rendered after bound model has changed

I have sap.ui.table.Table which rows are bound to an JSONModel.
var oListModel = new sap.ui.model.json.JSONModel();
//oTable created here (sap.ui.table.Table)
oTable.setModel(oListModel);
oTable.bindRows("/");
When the table is rendered, i.e. the DOM is created for this table, i need to reference to the DOM to pass the DOM elements (table rows) to a library which will make them draggable.
My problem is: How do i know when the DOM for the table is created after the model has been changed and the table is rerendered? I didnt find any listener. The view controller's listener onAfterRendering() didn't help me.
The model is filled with data after a XMLHTTPRequest is successful. When i set the model in the success handler of the xht request and try to access the DOM elments directly afterwards they don't exist yet.
Thank you for your help!
You can add an event delegate
var oMyTable = new sap.ui.table.Table();
oMyTable.addEventDelegate({
onAfterRendering: function() {
$table = this.getDomRef() ....
}
});
a better way is to extend the control see Using addDelegate to extend a control to use third party functionality
UPDATE
the example in that blog doesn't work anymore fixed here
I had a similar issue recently where i had to access an element after a smartform (where the element is present) rendered onto the view. I posted my query here as well as my final solution (based on the accepted answer of #Dopedev). I am using XML views - including nested XML views - here however and the onAfterRendering didn't help for me as well.
I guess you could look at this solution - like it's mentioned in the accepted answer, it may not be an optimal solution, but it sure works. In my case there is not much of a performance issue with the binding of the DOMNodeInserted since it is being called in the onAfterRendering of the nested view that consists of only the smartform with an immediate unbinding upon finding.
The condition if (id === "yourtableid") { } should be enough to identify and pass on. Since you have a table and thus several child nodes, unbinding is imperative at this point.
Mutation Observer is the preferred method but i guess you may need to check the browser compatibility table at the end of the page to see if it matches your requirements. There is an example here. I have used Mutation Observer (outside of a SAPUI5/openUI5 environment) earlier and found it very convenient(and performant) to listen to DOM insert events. In fact the sap.ui.dt package consists of MutationObserver.js

Use Template on Invisible Table for inserting into existing bound sap.m.Table

Excuse the confusing language but hopefully this makes sense: (see code for more clear explanation)
I have a requirement to display a list of "spare parts" in an sap.m.Table but there is the ability if one of these "spare parts" has a related "spare part" (e.g. A heavy duty version, a light version, etc) , that you can click a button on the row and display these related "spare parts" by inserting them immediately below the "spare part" in question.
While I can get the sap.m.Table doing what I want to do, I would like to take advantage of templates and binding to create a temporary sap.m.Table; bind it to the relationship that returns these alternate spare parts; and reuse the template for a row to give me an array of ColumnListItems which I can insert into the Table at the right place.
Unfortunately, doing this, a sap.m.Table has a feature that if it is not displayed, it doesn't actually make the Odata call and leverage the template function.
To explain possibly much clearer, refer to this jsbin:
http://jsbin.com/sihofu/4/edit?html,js,output
Any better ideas on how to generate template output for a binding without using a sap.m.Table; or alternative, getting the sap.m.Table to make the call without placing it on the screen visible (temporarily)?
The specific code to look at is as follows:
var oTable2 = new sap.m.Table();
oTable2.attachUpdateFinished(function() {
console.log("But this one doesn't");
// What I'm trying to do here is insert these entries below Key 1
});
oTable2.bindAggregation("items", {
path: "/ExampleSecondaryValues",
template: oTemplate,
});
Thanks,
Matt
Back from Holidays now and solved this problem with a bit of brute force by simply enhancing/extending the sap.m.table control slightly.
The problem was if the control was invisible, nothing was rendered, and some optimisation within UI5 core means that in the case nothing is rendered, the AfterRender event is not called on the control and this event is what fires the UpdateFinished event.
I won't debate whether that optimisation is appropriate or not, but to fix this I simply extended the table control with a new control which looks like as follows:
sap.m.Table.extend("my.InvisibleTable", {
renderer: function(oRm, oControl) {
oRm.write("<span");
oRm.writeControlData(oControl);
oRm.write("></span>");
}
});
e.g. Simply always rendering something in the render function, causes the AfterRender event to be called; which in turns allows the sap.m.Table to fire the UpdateFinished event which allows me to then safely get the rendered template items to insert in my visible table.
Would love to know a much better way of doing this (possibly using the template control or similar), but this works okay to solve the problem.
Cheers,
Matt

Fine Uploader and how to highlight extra drop zone area during drag and drop?

I have successfully added an extra drop zone for Fine Uploader, and that works great.
However I would like to be able to highlight the extra drop zone area in the same way that the default drop zone is highlighted, when a drag and drop operation is started.
I tried adding the qq-upload-drop-area class to my extra drop zone, but of course it colored everything red, whether or not the drag and drop is in progress.
Any pointers as to how to correctly implement this functionality would be appreciated.
You can use the the standalone drag and drop module. Make sure to add a value for the classes.dropActive option that matches the class added to the original drag and drop element when it is active.
$(document).ready(function(){
$('#fineuploader-traditional').fineUploader({
// ...
});
$(document.body).fineUploaderDnd({
classes: {
dropActive: 'qq-upload-drop-area'
}
})
.on('processingDroppedFiles', function(event){
console.log('Processing');
})
.on('processingDroppedFilesComplete', function (event, files, target){
$("#fineuploader-traditional").fineUploader('addFiles', files);
});
});
What I am doing here is instantiating a new fineUploaderDnd instance on the document.body (you may want to change this element to something else). I've given it a dropActive class of 'qq-upload-drop-area' which is the default class for the drop area when using Fine Uploader UI (note that you can put any class in here -- ideally it would match the class applied to to original dropzone when it is active so that both dropzones match). This class represents the style applied to the drop zone while a file or files are dragged over it.
The 'processingDroppedFilesComplete' event allows me to add the received files to an instance of Fine Uploader -- where they will validated and eventually uploaded.
Update
If you want the contents of any drop zone to be invisible until an item enters the drop zone, simply ensure a qq-hide-dropzone attribute is present on the drop zone container.
<div id="extra-dropzone" qq-hide-dropzone></div>
Update 2
Another possible option is to use the dragAndDrop.extraDropzones option which will do a lot automatically.
$(document).ready(function(){
$('#fineuploader-traditional').fineUploader({
// ...
dragAndDrop: {
extraDropzones: [ $("#extra-dropzone") ]
},
});
<div id="extra-dropzone" qq-hide-dropzone>
<h2>Drop files here</h2>
</div>

ASP.net MVC Set Checkboxes to checked Clientside

My situation is: Im making a simple inbox page. The inbox is a listing made from a DevExpress grid. Each row in the grid has a checkbox that the user can check so that they can multi delete records (similar to yahoo mail etc).
When the user clicks the select all link or the clear all link i need to set all the checkboxes within the grid to be checked or unchecked. How do I go about this with client-side scripting? Thanks
The easiest way to do this is to use jQuery. With the right selector it's pretty much a one liner. I don't know how much you know about jQuery so here's a link to the selector docs if you want to read up:
http://api.jquery.com/category/selectors/
The selector will depend on the layout of your page. I've done it before using something like this:
$("#tableId tr td input:checkbox").attr("checked", true);
In this example all checkboxes within a table with an id of "tableId" are checked
Using jquery it should be pretty easy- assuming you can use one of the selectors to select all of the checkboxes (take a look at the different jquery selectors http://api.jquery.com/category/selectors/).
Attach a toggle handler:
$('Selector for the "select all" checkbox>').toggle(function() {
alert('First handler for .toggle() called.');
}, function() {
alert('Second handler for .toggle() called.');
});
Select all checkboxes and when toggled switch the checked state of the other checkboxes:
$('<Selector for the ones you want to toggle>').attr('checked', true);
Provide some sample HTML, or a link to a page, if you need further help.
So putting it together, assuming your "select all" checkbox had an ID of "uxSelectAll" and the ones you want to change have a CSS class of "checkbox-mail-items" it would be something like:
$('#uxSelectAll').toggle(function() {
$('.checkbox-mail-items').attr('checked', true);
}, function() {
$('.checkbox-mail-items').attr('checked', false);
});
you can create a delegate (jquery) for all the checkboxes once you've done the answer above. with something like to perform an action for each check box:
$('div.myGridDivClass tbody').delegate(':checkbox', 'click', function(){
var $checkedRow = $(this), $row = $checkedRow.closest('tr')
// check row is checked
// toggleclass for checked css class and apply to the $row or whatever u want
// do something here
});