keep footer last in list when dragging new item into the list from another - vuedraggable

I have Vue Draggable working like a Kanban board with multiple columns, and I have made each column at least the height of the viewport so that each item can easily be dragged into the column next to it (for cases where one column is much longer than the next, for example).
I also have a button in the footer slot to add new cards to the column. This works well in that it is generally always at the bottom of the list, is not draggable, etc.
The issue arises when I drag an item from another list in below the footer (but still within the height of the draggable element). When I do this, the footer does not stay below the new item, which looks odd.
Once I drop the element, it snaps into place and the footer is one again at the bottom - it is only when the new card is being moved that it appears below the footer.
Is there any way to make sure that even during the move event and a new card being added to a list that the footer stays as the last element?
This issue seems to be captured in this comment on Github issues - https://github.com/SortableJS/Vue.Draggable/issues/673#issuecomment-554149705 - but no solution is provided in that thread.
Any help greatly appreciated.

So for anyone having the same issue I solved this by doing the following:
Hooking into the onMove event using the :move prop to run a function each time an item is moved... e.g. :move="fixFooter"
Creating a function that checks if the moved item would be the last in the new list (thus by default it would sit below the footer without this fix), and if so on the $nextTick append the footer to the Draggable container so it gets moved below the item coming in to the list... (just learnt that .appendChild will move an existing element to the end)
It then checks if the from/to list is the same to account for the item being dragged back into the list it's coming from during the same drag event (otherwise you get the same undesirable footer behaviour as before if you drag an item out of a list and back below the footer without dropping it).
fixFooter(e) {
if(e.relatedContext.list.length === e.draggedContext.futureIndex) {
var newListDom = e.relatedContext.component.$el;
var newListFooter = e.relatedContext.component.$slots.footer[0].elm;
this.$nextTick(() => {
newListDom.appendChild(newListFooter);
});
} else if(e.from === e.to && (e.from.children.length - 1) === e.draggedContext.futureIndex) {
var currentListDom = e.from;
var currentListFooter = e.from.lastChild;
this.$nextTick(() => {
currentListDom.appendChild(currentListFooter);
});
}
}

Seems like for vue draggable next this is enough:
fixFooter(e) {
if (e.relatedContext.list.length === e.draggedContext.futureIndex) {
var newListDom = e.to
var newListFooter = e.to.lastChild
this.$nextTick(() => {
newListDom.appendChild(newListFooter);
});
}
}

Related

Tabulator GroupBy problems

Good afternoon. Please tell me how to solve the following problems.
I added a menu to the column headers of the table, when clicked, grouping by the selected column should occur. But for some reason, grouping occurs only after re-selecting this menu item. This happens once after the table is created. Then the menu is triggered the first time. Next, the grouping is triggered by the first click of the menu item.
After adding grouping by columns, the table starts working very slowly. Scrolling in the horizontal direction is jerky and has a long delay, while scrolling vertically remains acceptable. If you select grouping by different columns several times, the browser starts to take up a lot of RAM. The code and video example are below. And even if we remove the grouping, the lags remain when scrolling. It is worth using the grouping once and the Tabulator becomes difficult to use.
UPD: This is actual for Chrome. An if table include 'Frozen' columns.
Code of header menus
var headerMenu = [
{
label:"Группировка",
action:function(e, column){
let gField = column.getDefinition().field;
if(table.options.groupBy === gField){
table.setGroupBy();
}
else {
table.setGroupBy(gField);
}
}
},
]
Adding menus example
arrCol.push({
title: 'Работник',
field:"fio",
sorter:"string",
headerFilter:"list",
bottomCalc:"count",
headerMenu: headerMenu,
bottomCalcParams:{precision:0},
headerFilterParams:{valuesLookup:"active",autocomplete:true},
frozen:true,
width: 200
});
Creating Table
table = new Tabulator("#spreadsheet", {
columnDefaults:{
headerHozAlign:"center",
},
height:"65vh",
columns: arrCol,
columnCalcs:"both",
groupClosedShowCalcs:true,
});
Video showcase

Tabulator - get another cell's value on click event

this one should be simple for tabulator experts (but not for me)...
i have a tabulator table. I've made one column, "edit" clickable as shown below. it works fine and returns the value of the cell i clicked. HOWEVER, that's not what i need. I need to get the value of ANOTHER cell in the same row (column "transactionID"). I know how you would do it in other languages, just use x and y values to move over 3 columns and get the value. but how is it done in tabulator? by the cloumn name? I can't find any example code on how to accomplish this.
This is the snippet from my tabulator init :
{title:"edit" , name:"edit", formatter:myformatter, cellClick:function(e, cell){alert("cell clicked - " + cell.getValue())}},
i just need to make it return value for "transactionID" instead of "edit"
and before anyone asks, no, i can't just make "transactionID" clickable. I need the clickable cell to be separate.
thanks for your help!
ok so since i got no answers to this question, i slogged thru and figured it out myself eventually. To save others time who run into this in the future, i am posting how i solved it. code with comments below :
// this goes in your tabulator column definitions. In my example, "edit" is a column
with an image button that on clicking, redirects to another page depending on what cell was clicked
{title:"" , name:"edit", formatter:openIcon, headerSort:false, cellClick:function(e, cell){
var re = cell.getRow(cell); // get the row of the cell that was clicked
var thenum = re.getData().id; // gets the value of column "id" in the same row
var theurl = "editTransaction.php?trans="+thenum; // creates my url
console.log(theurl); // perform whatever action you need to do. replace this.
}},
If you are using react-tabulator and you want to access some column data to perform a specific action ,here is the snippet for your help.
import { reactFormatter } from "react-tabulator";
// your React Component to use in a cell
function CustomFormatter(props: any) {
const rowData = props.cell._cell.row.data;
return <a onClick={() => alert(rowData.customField)}{cellData.customField }</a>;
}
const columns = [{ title: 'Custom', field: 'custom', align: 'center', formatter: reactFormatter(<CustomFormatter />) },
]

How to trigger editor programmatically

I have set up a producttable (kind of a shopping-cart) with one editable column (product amount) like this :
{
title:"Aantal",
field:"product_amount",
align:"center",
responsive: 3,
validator:["required","numeric"],
editor:amountEditor,
cellEdited:recalcPrices,
validator:["required","numeric","min:1","max:10"]
},
I am using a custom jquery amountEditor because this one looks somewhat nicer than the builtin editor. Rows are added to the shopping cart tabel (copied from another producttable) by a button click. Everything works fine but I would like that the user doesn't have to click on the editable columnfield himself. So the only one editable field should be triggered automatically / programmatically after the row is added to the table.
I think I have to combine these commands somehow in the table definition:
rowAdded:function(row){
var cell = row.getCell("product_amount");
cell.edit();
},
I tried everything but I cannot find the right combination to get this work. I can get var rowElement = row.getElement(), however var cells = row.getCells() or var cell = row.getCell(column) look empty. Any help is much appreciated.
You need to scroll to the row using the scrollTo function on the row component to ensure it is visible before you can trigger an edit on the cell, so your rowAdded callback wants to look like this:
rowAdded:function(row){
row.scrollTo().then(function(){
row.getCell("product_amount").edit();
});
},

Select UI Element by filtering properties in coded ui

I have a web application. And I am using coded ui to write automated tests to test the application.
I have a dropdown with a text box. Which on entering values in the textbox, the values in the dropdown gets filtered based on the text entered.
If I type inside textbox like 'Admin', I will get below options like this:
And I need to capture the two options displayed.
But using IE Developer tool (F12), I am not able to capture the filtered options, because the options that are displayed do not have any unique property (like this below). And the options that are NOT displayed have a class="hidden" property
Any way to capture the elements that are displayed by applying some kind of filter like 'Select ui elements whose class != hidden'
Thanks in advance!!
HI please try below code will it works for you or not.By traversing all those controls that have class ="hidden"
WpfWindow mainWindow = new WpfWindow();
mainWindow.SearchProperties.Add(HtmlControl.PropertyNames.ClassName, "hidden");
UITestControlCollection collection = mainWindow.FindMatchingControls();
foreach (UITestControl links in collection)
{
HtmlHyperlink mylink = (HtmlHyperlink)links;
Console.WriteLine(mylink.InnerText);
}
I'm not sure there is a way to do it by search properties, but there are other approaches.
One way would be to brute force difference the collections. Find all the list items, then find the hidden ones and do a difference.
HtmlControl listControl = /* find the UL somehow */
HtmlControl listItemsSearch = new HtmlControl(listControl);
listItemsSearch.SearchProperties.Add(HtmlControl.PropertyNames.TagName, "li");
HtmlControl hiddenListItemsSearch = new HtmlControl(listControl);
hiddenListItemsSearch.SearchProperties.Add(HtmlControl.PropertyNames.TagName, "li");
hiddenListItemsSearch.SearchProperties.Add(HtmlControl.PropertyNames.ClassName, "hidden");
var listItems = listItemsSearch.FindMatchingControls().Except(hiddenListItemsSearch.FindMatchingControls());
You will only be able to iterate this collection one time so if you need to iterate multiple times, create a function that returns this search.
var listItemsFunc = () => listItemsSearch.FindMatchingControls().Except(hiddenListItemsSearch.FindMatchingControls());
foreach(var listItem in listItemsFunc()){
// iterate 1
}
foreach(var listItem in listItemsFunc()){
// iterate 2
}
The other way I would consider doing it would be to filter based on the controls which have a clickable point and take up space on the screen (ie, not hidden).
listItemsSearch.FindMatchingControls().Where(x => {
try { x.GetClickablePoint(); return x.Width > 0 && x.Height > 0; } catch { return false; }
});

Dojox FloatingPane is growing every time I update the content

I've created a simple mapping widget using Dojo and Google Maps. The map is displayed in a dijit.layout.ContentPane set as the center panel of a dijit.layout.BorderContainer (which has the address field and a BusyButton in its top panel); the BorderContainer is in turn wrapped in a dojox.layout.FloatingPane. The widget has a subscription to a topic that will trigger a refresh of the map display when new address data is provided. The updater function is very simple, and looks like this:
_updateAddress: function(data) {
this.addressMapper.show();
if (data === null || !data.address || data.address === "" ) {
this.address.attr("value", "");
} else {
this.address.attr("value", data.address);
}
this.mapBtn.makeBusy();
this._getMap();
}
Every time I call this function, the FloatingPane's resize() method is invoked when I call show(), and it's increasing the height and width of the BorderContainer by 12 pixels every time the pane is shown (even with doLayout and isLayoutContainer set to false on the FloatingPane). I can't seem to prevent this from happening, or correct it afterwards, no matter what I try.
Anyone have any ideas how to remedy this?
Thanks in advance!
-- Joe M --

Resources