Getting element id from Kendo UI treeview drag and drop - kendo-ui

On the drop event you get back an object that allows you to get the source and destination elements, however I can't see anything available in these objects that helps me identify them uniquely against the datasource.
When I originally databound all of these objects I set an id for each item, but that id is not available in the drop event source/destination elements.
The documentation on the Kendo UI site only goes as far as explaining that there is source/destination objects, not how to do anything with them.
I want to get the source and destination ids so that I can go to the database, remove the source and add it to the destination.

So by process of some voodoo magic you can get what you need like so:
e.sender.dataItem(e.destinationNode)
_childrenOptions: Object
_events: Object
_loaded: false
children: J.extend.init
dirty: false
enabled: true
hasChildren: true
id: 3
index: 2
items: ct.extend.init[0]
parent: function (){return i}
text: "Sales"
uid: "fedfd9ca-83bf-45ba-a14d-4127f8cc1560"
__proto__: n.extend.r

Related

how to correctly render referenced entities in list when I have objects instead of numberic ids?

right now in order for the list to render properly I need to have this kind of data passed in:
row = {
id: value,
name: value,
height: value,
categories: [1,2,3,4]
}
how can I adapt the code so that a list works with this kind of data?
row = {
id: value,
name: value,
height: value,
categories: [{id: "1"},{id: "2"},{id: "3"},{id: "4"}]
}
when I try to do that it seems that it applies JSON.stringify to the objects so it is trying to find category with id [Object object]
I would to avoid a per case conversion of data as I do now..
it seems that I cannot do anything in my restClient since the stringify was already applied
I have the same issue when I fetch just one data row e.g in Edit or Create.. categories ReferenceArrayInput is not populated when categories contains objects
Have you tried using format?
https://marmelab.com/admin-on-rest/Inputs.html#transforming-input-value-tofrom-record
Might help transform your input value. Then you can use format() to change values back to the format your API expects.
If this does not work then you will have to probably create a custom component out of ReferenceArrayInput.

Ternary Conditional Operator not returning true/false

I have a user setting for admins that will show a delete button if they're an admin, and hide it if they're not an admin. What I'd like to say is "If the delete button is visible, the heading of this table column will say "View/Delete". If you're not an admin, the heading will say "View."" I'm also using a JS plugin called jQgrid, which is why the code is in the ColModel block. So far, it's returning true (showing "View/Delete") for everyone, even if they aren't an admin. Any suggestions? Please be nice - I'm new at this :)
, colModel: [
{ name: $(".delete:visible") ? 'View/Delete' : 'View',
The text of the header of the column of the table should have no direct relation with the value of name property of colModel. You can't dynamically change name of any column without recreating of the whole grid.
What you probably need is setLabel method which allows to change the text or attributes on any grid column. For example you can have the column {name: "view", ...} and colNames: [..., "View", ...]. To change the text "View" to "View/Delete" you need to execute
$("#gridid").jqGrid("setLabel", "view", "View/Delete");

buffered store with local sorting (client-side)

I have a buffered grid on which I've implemented a local sort function (client side). I would like to remove the sort indication (darker background and little arrow) on the column header when the store reloads.
Does anyone know how to accomplish this in 4.1?
To make this clearer:
I want my columns to be sortable. I do not want them to initialize with sorting disabled. Users should be able to click the header and sort it all they want. But, what I want is to be able to turn off the sort programmatically. I.e., remove any sort classes that were applied from user clicks (things like the darker background and the little sort direction arrow).
The reason I would do this is because I am using a modified buffered store which allows me to do local sorting (client-side) with all of the buffered data (not just the chunk that is displayed). Normally, using a buffered store will make local sorting disabled because it would only sort the data that is displayed in the grid - not all of the data in memory, so the guys at Sencha made any grid that has a buffered store automatically disable local sorting - only remote sorting works. Well, as I said, mine is modified so it will work - but then when this buffered store reloads with new data from the database it does not enjoy the handy sortOnLoad feature normal grids get as a matter of course. In my use-case it is more logical to remove the sort state than it is to override the sortOnLoading functionality and make it apply the same sort to the new data, hence, this question.
I do have it worked out now, I'll post an answer shortly along with my implementation of a buffered store with local sorting, in case anyone is interested and for my own future reference.
I should also point out that I am very aware of the client-side performance penalties that come with local sorting on a store that would need to be buffered (as opposed to just using remote sorting of the data on the server). I am aware that this is probably why Sencha does not support local sorting on their buffered stores. I have assessed all of the pros and cons to this and in my specific use-case it is the most sensible thing for me to do.
Buried deep in the dom there is a setSortState function on the Ext.grid.header.Container class and on the Ext.grid.column.Column class. These don't show up anywhere in the 4.1.0 docs but they're in the code nevertheless.
You can look at these functions yourself to get a complete concept of what they do, but the gist of both them is a switch statement that looks for either a 'DESC', 'ASC' or a null in the first argument, e.g.:
setSortState(`DESC`);
setSortState(`ASC`);
setSortState(null);
Calling either the header version or the column version of this function with a single null argument will remove the sort classes on a column. The only real difference is that the header version looks at the grid's store to find the active sorter in the store's sorters property and then uses that data to determine which column to call this function on - the column version simply runs off the column object that it is called from.
In my use-case I don't add a sorter to the store sorters property so I am using the column version (i.e. calling setSortState from an Ext.grid.column.Column object).
First, here is an example of my implementation of a buffered store that allows local (client-side) sorting:
Ext.define('MyApp.store.TheBufferedStoreWithLocalSorting', {
extend: 'Ext.data.Store',
requires: [
'Ext.ux.data.PagingMemoryProxy',
'Ext.util.MixedCollection'
],
model: 'MyApp.model.SomeModel',
buffered: true,
pageSize: 100,
remoteSort: true, // this just keeps sorting from being disabled
proxy: {
type: 'pagingmemory',
reader: 'json'
},
/*
* Custom sort function that overrides the normal store sort function.
* Basically this pulls all the buffered data into a MixedCollection
* and applies the sort to that, then it puts the SORTED data back
* into the buffered store.
*/
sort: function(sorters) {
var collection = new Ext.util.MixedCollection();
collection.addAll(this.proxy.data);
collection.sort(sorters);
this.pageMap.clear();
this.getProxy().data = collection.getRange();
this.load();
}
});
Now, to answer my question, to remove the sorter classes whenever the store reloads I just need to do this:
Ext.each(myGrid.columns, function(column, index) {
if (column.hasCls('x-column-header-sort-ASC') ||
column.hasCls('x-column-header-sort-DESC')) {
myGrid.columns[index].setSortState(null);
return false;
}
});
When the store is reloaded you could add the following to the store's load event handler:
Ext.create("Ext.data.Store", {
listeners: {
load: {
fn: function () {
grid.addCls("no-sort-icon");
}
}
}
};
Then modify your css to hide the icon when element is child of "no-sort-icon" (this would be on the grid)
.no-sort-icon .x-column-header-text {
background-image: none;
}
.no-sort-icon .x-column-header {
background-color: #C5C5C5;
}
If I understand you correctly, setting this config on the specified column should solve your problem
columns: [
{text: 'First Name', dataIndex:'firstname', sortable: false},
{text: 'Last Name', dataIndex:'lastname'},
]
more details here http://docs.sencha.com/ext-js/4-0/#!/api/Ext.grid.column.Column-cfg-sortable
This is a configuration option, so it would disable the sortability of a column when the grid is first rendered.
Here is a jsfiddle demo
* Note that I use Ext. 4.0.7, you can switch to 4.1.0, but for some reason an unrelated display bug with the dropdown pops out

Flyweight VirtualRepeater containing IntegerPicker

In my Enyo app, I have a VirtualRepeater which produces Controls containing various text displays and an IntegerPicker.
I have two problems with this repeater:
1) If three rows are produced, clicking on the IntegerPicker in rows 1 and 2 brings up the drop-down picker UI over the top of the IntegerPicker in row 0.
2) I initialise each IntegerPicker with a max value using setMax(). However, if three rows are produced, the IntegerPickers in rows 0 and 1 will have the same max value as that in row 2.
It looks as if only one IntegerPicker is being created and is being used on the first row.
I tried replacing my VirtualRepeater with a Repeater, and changed my repeater row creation function to return a new instance of the item containing the IntegerPicker, instead of returning true. However this produces the error:
warning: enyo.Component.addComponent(): Duplicate component name "itemName" violates unique-name-under-owner rule, replacing existing component in the hash and continuing, but this is an error condition and should be fixed.
It seems that Repeaters need their delegates created inline, which seems quite inelegant.
This code sample illustrates the problem:
enyo.kind({
name:"Test",
kind:enyo.Control,
components: [
{
kind: "VirtualRepeater",
onSetupRow: "setupRow",
components: [{
name: "theIP", kind: "IntegerPicker", min:0
}]
}
],
setupRow: function(inSender, inIndex) {
if (inIndex < 3) {
this.$.theIP.setMax(inIndex);
return true;
}
return false;
}
});
How can I create an arbitrary number of IntegerPickers in my app? Any help appreciated!
What you are doing with theIP in your setupRow function is accessing a specific IntegerPicker itself, which is a child component of the Virtual Repeater. To set the max value of a given IntegerPicker corresponding to the row, give your VirtualRepeater a name attribute, like "PickerList":
kind: "VirtualRepeater",
onSetupRow: "setupRow",
name: "PickerList",
components:[//this should be empty to begin with]
Then you can access each row in the repeater like this:
setupRow: function(inSender, pickerMax) {
var newPicker = new IntegerPicker(pickerMax);
this.$.PickerList.push(newPicker);
To get a specific row in the VirtualRepeater you need to do it like this:
this.$.PickerList[1];
Here is an extended Enyo tutorial which makes use of the VirtualRepeater:
https://developer.palm.com/content/resources/develop/extended_enyo_tutorial.html

ExtJS Tree same parentNode

I am rendering a Tree using Jason array that i get from a jsp page. So the tree has root node and 3 nodes and each node has more than 5 children and some of the children has same id and same text. It renders properly and no issues in display.
I am trying to make the user select child nodes of only one type (one of 3 nodes). if the user selects any node which is not the sibling of already existing node then i just need to un check already checked nodes. This sounds pretty simple and i coded it. I basically compared the parent nodes(node.parentNode.id) of the checked node with the already checked nodes(tree.getCheckedNodes())
the problem is when i select children nodes which have same id and text my logic fails and they say that they have same parentNode.id even though they have different parentNode.id. Does the tree panel check for duplicate elements and assign them to same parentnode while loading? what is going here and how to fix this any ideas. thank you.
Ext.onReady(function(){
var tree = new Ext.tree.TreePanel({
id: 'deficiencyTree',
renderTo: 'MyTable',
title: 'Deficiencies',
height: 'auto',
width: 525,
useArrows: true,
autoScroll: true,
animate: true,
enableDD: true,
containerScroll: true,
rootVisible: false,
frame: false,
root:{nodeType: 'async'},
dataUrl: 'jsonFile.jsp',
listeners: {
'checkchange': function (node, checked) {
if (checked) {
selNodes = tree.getChecked();
alert(selNodes);
Ext.each(selNodes, function (nodes) {
alert("id values for node and nodes "+node.parentNode.id+" "+nodes.parentNode.id);
if (nodes.parentNode.id != node.parentNode.id)
{
nodes.getUI().toggleCheck();
}
});
}
list.length = 0;
iii = 0;
selNodess = tree.getChecked();
Ext.each(selNodess, function (nodes) {
list[iii] = nodes.id;
iii++;
});
}
}
});
tree.getRootNode().expand(false);
});
As a semi-aside, ideally you should not be replicating node IDs at all (an ID should never be replicated, otherwise it isnt an ID). If you need the value that you are currently assigning to the ID field, add an additional attribute to the node and place it here- you can refer to this attribute when you need to. ExtJS isnt built to handle duplicate IDs for notes within the same tree very well at all.
I used hierarhical ids to solve this problem:
so if path to element was x->y->z then his id in tree will be x+y+z
you just need to change server-side code:
- Get id in format x+y+z, find last + and get z
- Return elements with ids [x+y+z+childId]
Good news. I got it working. it was pretty simple. As "Xupypr MV" suggested, i shouldn't be using same ID which is against the basic functionality, so i did put a different id for each node and put a new attribute named id2 and assigned it the value i needed and then accessed it using node.attribute["id2"], and it work perfectly well. previously i tried to get the attribute value as node.id2 just like node.id, node.text which did not work. Thanks again for the responses.

Resources