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

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!

Related

Mixing and aligning non-Smart fields in a SAPUI 5 Smartform

The attached screen below works just fine but underneath the covers I have a slight problem ^^
Smartform with both simple and smart fields
Behind the view there's a smartform (no annotations used). Field "Agreement Action Type" and the last two pairs of fields are not smartfields (found no "smartcombo" or something similar to use) they are just pairs of labels and comboboxes and here comes the issue. While the smart fields were all perfectly aligned, comboboxes (aka simple fields I suppose) were not aligned along. In order to solve this for the moment, I used a couple of SAPUI5 formatting classes and...width declaration in pixels in the combo definition within the view. Results works fine, even in different size monitors but, even though I'm currently in the process of learning and understanding the technology, I already know that the latter is a crime against SAPUI5. Is there a way to align smart and simple fields in the same view (or an equivalent dropdown control for smartforms alternatively) or I will have eventually to get rid of my smartform (losing small bonuses like the togglable attribute) and use a simple form instead?
Thanks for taking time to read it.
Regards,
Greg
The GroupElement aggregation manages the SmartLabel for you so try to remove the label inside the GroupElement aggregation like this:
<smartForm:GroupElement label="Label">
<Input type="Text" value="someValue"/>
</smartForm:GroupElement>
On the contrary, if you want to change the appearence of your SmartField, you can use ControlType to configure the internal control.

Add to the beginning of Reactive Forms Array Angular

Please see the relevant plunker
https://plnkr.co/edit/f0BxpinhuqVz8o6IIFaL?p=preview
stack overflow makes you put code if a plunker is linked
but it is too much code to copy paste here it would just
look messy so I a am putting this comment instead.
If you run this and then click the add button a new entry is added to the array, but the form view does not reflect the forms state, instead the first entry is duplicated and the last entry is gone.
If anyone has any ideas or guides as to what I am doing wrong I would be very grateful as I have been pretty stuck on a seemingly easy task.
I tried to follow the official Angular Reactive Forms guide as close as possible to build this example.
Seems like Angular has trouble tracking the index of your objects in your formArray. This can be solved by using trackBy. Add it to your iteration with function:
<div *ngFor="let detail of detailArray.controls; let i=index; trackBy:trackByFn" [formGroupName]="i">
and in component:
trackByFn(index: any, item: any) {
return index;
}
Your PLUNKER

Element Checkbox got its label always to the left and needs a link

How can I change the positions of checkbox and label and how to implement a link into the label?
$acceptGTC = new Element\Checkbox('AGBs');
$acceptGTC->setLabel('I Accept the GTC (show it).');
$this->add($acceptGTC);
regards
n00n
meanwhile:
I tried to overwrite the view helper for checkboxes.
copied
*/vendor/zendframework/zend-form/src/View/Helper/FormCheckbox.php
to
*/module/Application/src/Application/View/Helper/FormCheckbox.php
added to module.config.php
'viewhelpers' => array('checkbox'=>'Application\View\Helper'),
But it still uses the original one...
Do I have to tell zend to use my FormCheckbox?
I don't exactly know the way you are rendering your Zend_Form_Element, but in order to enhance the rendering as you want you should build a custom decorator, and add it to this element.
You should read the Zend documentation on Zend_Form_Decorators, everything is quite well explained and should lead you to a fancy solution.

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

Change reading order of html form elements

I'm designing a form like this, where the bottom of the labels in that row align in straight line and the top of the input fields in that row align in straight line.
Owing to some restriction in CSS (we can't fix the height as it will vary), I've to place the labels of the form elements in first row and then place their respective input fields in the next row (such that the input fields are placed just below their labels).
I tested the keyboard & the tab order with this html structure, it works fine.
I'm wondering that the reading order in JAWS or any other screen reader is not going to be right.
Any recommendations for any method to change the reading order
or
is it ok to go ahead with this html structure since the tab order is anywys working ?
In the HTML structure each input should be preceded by its label, rather than having labels on one row and inputs on the next.
However, you have a very particular display you want, and you are supporting IE7 (without display: table), so I think you are best off actually using a table.
You can do this accessibly, if you take these things into account:
Use a basic layout table for your form, and include an extra attribute on the table tag:
<table role="presentation">
That means the table is not a table from an accessibility point of view. (I only ever recommend this when supporting IE7 layouts!) Do not use <th> tags either.
The main thing for screen readers when filling it in would be an explicit label-input relationship.
<label for="input_id">My label</label>
<input type="text" id="input_id">
You can tell if this works by clicking on the label, it should put the cursor in the input.
However, your reading view needs a different approach. When you've got a row of items at the top that relate to a row of items underneath, that is the definition of a data table. So when the page is saved (or however it converts to the reading view), use a data table e.g:
<table>
<tr>
<th>Customer account number</th>
[other <th>s]
</tr>
<tr>
<tr>
<td>023456353434</td>
...
When read out by a screen reader it will read the 'header' (e.g. customer account number) before the content (023...). So the changes are:
Remove the role
Convert the top row into <th>s
It has to be said this is a hack, it is not particularly robust, and I certainly wouldn't recommend it for a responsive site. It is purely the required layout and browser support that lead to this.
without viewing your markup its impossible to tell exactly, but it sounds like you have a tow of inputs and then a row of labels....that's not ideal for accessibility.
you could nest the form control inside the label element, setting the form control's display to block to achieve the same effect, while also increasing usability and clickability.