I created a Custom ListItem, which has some ChildWidgets. One of these is a Combobox Widget.
I want to set the Model by a Controller, for this I used qx.data.controller.List.
With the bindItem and controller.bindProperty("", "model", null, item, index); I bind my Model to the List.
My Problem is, that I have one Property in my Model (text) which should be binded to the Combobox Value Property.
I tried controller.bindProperty("text", "value", null, item.getChildControl("combobox"), index); but I didn't get it to work.
What am I doing wrong?
Here's the final answer to your question, including the ability to delete items:
qx.Class.define("CustomListItem", {
extend: qx.ui.core.Widget,
include: [qx.ui.form.MModelProperty],
properties: {
isDistribution: {
init: true,
check: "Boolean",
event: "distributionChange"
},
isFilter: {
init: false,
check: "Boolean",
event: "symbolEvent"
},
isColumn: {
init: false,
check: "Boolean",
event: "symbolEvent"
},
isRow: {
init: false,
check: "Boolean",
event: "changeRow"
},
isFilterPatientCases: {
init: true,
check: "Boolean",
event: "symbolEvent"
},
isShow: {
init: true,
check: "Boolean",
event: "symbolEvent"
},
isUnkownFilter: {
init: true,
check: "Boolean",
event: "symbolEvent"
},
value: {
init: "",
event: "changeValue"
}
},
members: {
_createChildControlImpl: function(id) {
var control;
switch (id) {
case "alertimage":
control = new qx.ui.basic.Image();
control.setWidth(16);
this._add(control);
break;
case "suchecombobox":
control = new qx.ui.form.ComboBox();
this._add(control, {
flex: 1
});
break;
case "deletebutton":
control = new qx.ui.form.Button("Del");
control.setMaxWidth(40);
this._add(control);
break;
case "imagecomposite":
control = new qx.ui.container.Composite(new qx.ui.layout.HBox(0));
this._add(control);
break;
}
return control || this.base(arguments, id);
}
},
construct: function() {
this.base(arguments);
this._setLayout(new qx.ui.layout.HBox(0));
this._showImage = new qx.ui.basic.Image();
this._showImage.setMaxHeight(25);
this._showImage.setMaxWidth(25);
this._showImage.setScale(true);
this._filterImage = new qx.ui.basic.Image();
this._filterImage.setMaxHeight(25);
this._filterImage.setMaxWidth(25);
this._filterImage.setScale(true);
this._createChildControl("alertimage");
this._createChildControl("suchecombobox");
this._createChildControl("imagecomposite");
this._createChildControl("deletebutton");
this.getChildControl("deletebutton").addListener("execute", function(e) {
var itemModel = this.getModel();
data.remove(itemModel);
}, this);
}
});
var dataRaw = {
isColumn: false,
isFilter: false,
isFilterPatientCases: true,
isRow: true,
isShow: true,
isUnkownFilter: true,
position: "row",
queryText: "Dia:I50_:_Herzinsuffizienz",
textType: ""
};
var data = qx.data.marshal.Json.createModel([dataRaw]);
var list = new qx.ui.form.List();
list.setWidth(200);
var listController = new qx.data.controller.List(null, list);
listController.setDelegate({
bindItem: function(controller, item, index) {
controller.bindProperty("", "model", null, item, index);
controller.bindProperty("queryText", "value", null, item.getChildControl("suchecombobox"), index);
controller.bindProperty("isFilter", "isFilter", null, item, index);
controller.bindProperty("isColumn", "isColumn", null, item, index);
controller.bindProperty("isRow", "isRow", null, item, index);
controller.bindProperty("isFilterPatientCases", "isFilterPatientCases", null, item, index);
controller.bindProperty("isShow", "isShow", null, item, index);
controller.bindProperty("isUnkownFilter", "isUnkownFilter", null, item, index);
controller.bindProperty("queryText", "value", null, item, index);
},
createItem: function() {
return new CustomListItem();
}
});
listController.setModel(data);
listController.addListener("changeSelection", function(e) {
console.log(e.getData().toArray());
}, this);
var doc = this.getRoot();
var button = new qx.ui.form.Button("AddItem");
var newIndex = 1;
button.addListener("execute", function(e) {
dataRaw.queryText = "New (" + (newIndex++) + ")";
data.append(qx.data.marshal.Json.createModel([dataRaw]));
}, this);
doc.add(list, {
left: 0,
top: 0
});
doc.add(button, {
left: 200,
top: 0
});
Related
Code mirror is not bind in extjs 6.
I already tried to subcribe the get and set methods, only the set works, when the component is opened the value is set, but when it changes the value of the codemirror, it does not bind with the value
My component:
Ext.define('Ext.form.field.CodeMirror', {
extend: 'Ext.form.field.TextArea',
alias: 'widget.codemirror',
getValue: function () {
var me = this;
if (me.codeEditor) {
return me.codeEditor.getValue();
}
},
setValue: function (value) {
this.codeEditor.setValue(value);
},
listeners: {
afterrender: function (textarea) {
var me = this;
me.codeEditor = CodeMirror.fromTextArea(textarea.inputEl.dom, {
mode: "xml",
htmlMode: true,
theme: "default",
lineNumbers: true,
lineWrapping: true,
matchTags: {
bothTags: true
},
autoCloseTags: true,
extraKeys: {
"F11": function (cm) {
cm.setOption("fullScreen", !cm.getOption("fullScreen"));
},
"Esc": function (cm) {
if (cm.getOption("fullScreen")) {
cm.setOption("fullScreen", false);
}
}
},
foldGutter: {
rangeFinder: new CodeMirror.fold.combine(CodeMirror.fold.indent)
},
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
});
}
}
});
Use the component (Default bind is value on Extjs):
xtype: 'codemirror',
name: 'xml',
bind: '{model.arquivoNfceWrapper.xml}',
listeners: {
afterrender: function (textarea) {
var me = this;
me.codeEditor = CodeMirror.fromTextArea(textarea.inputEl.dom, {
mode: "xml",
htmlMode: true,
theme: "default",
lineNumbers: true,
lineWrapping: true,
matchTags: {
bothTags: true
},
autoCloseTags: true,
extraKeys: {
"F11": function (cm) {
cm.setOption("fullScreen", !cm.getOption("fullScreen"));
},
"Esc": function (cm) {
if (cm.getOption("fullScreen")) {
cm.setOption("fullScreen", false);
}
}
},
foldGutter: {
rangeFinder: new CodeMirror.fold.combine(CodeMirror.fold.indent)
},
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
});
me.codeEditor.on('change', function (cMirror) {
me.updateBindValue(cMirror.getValue());
});
me.codeEditor.setValue(me.getBindValue());
}
},
getBindValue: function () {
return this.bind.value.getValue();
},
updateBindValue: function (value) {
this.bind.value.setValue(value)
}
I am trying to find length of kendo grid dataSource, but I am always getting 0 in return. How can I get the total length of dataSource? I have added Control service that is dataSource for the grid.
ctrl.js
$scope.alignedProcessesToControlGridOptions.dataSource = ControlRatingGridDataService.getAlignedProcessesToControlGrid($stateParams.controlId);
var data = $scope.alignedProcessesToControlGridOptions.dataSource.data().length;
console.log('GRID DATA', data);
DataService.js
getAlignedProcessesToControlGrid: function(controlKey) {
var countNew = 0;
return new kendo.data.DataSource({
type: 'json',
serverPaging: true,
serverSorting: true,
serverFiltering: true,
transport: {
read: function(options) {
var gridSearchObject = {
skip: options.data.skip,
take: options.data.take,
pageSize: options.data.pageSize,
page: options.data.page,
sorting: options.data.sort,
filter: options.data.filter
};
return $http.post(
'app/control/rest/allAlignedProcessesToControl/' + controlKey, gridSearchObject).success(
function(data) {
countNew = data.totalCount;
options.success(data.resultDTOList);
});
}
},
pageSize: 5,
schema: {
model: {
id: 'riskInProcessKey',
fields: {
processName: {
editable: false
},
epcfName: {
editable: false
},
erhName: {
editable: false
},
ctlGeolocationsText: {
editable: false
},
ctlPerformanceRatingText: {
editable: false
},
ctlEffectivenessRatingText: {
editable: false
}
}
},
total: function() {
return countNew;
}
}
});
},
Assuming your HTML for the grid looks something like...
$("#grid").kendoGrid({
dataSource: {
// your datasource
},
dataBound: onDataBound
});
Create a function for the dataBound event...
function onDataBound(e) {
console.log(e.sender.dataSource.view().length);
}
I do not know the right way of creating a treepanel pickerfield. Now I do it like so:
{
xtype:'pickerfield',
width:'34%',
emptyText: 'Choose layer',
createPicker: function(){
return Ext.create('Ext.tree.Panel',{
hidden: true,
floating: true,
minHeight: 300,
pickerField: this,
root: {
text: 'Root',
expanded: true,
children:[{
text: 'Standard',
expanded: true,
children: [{
text: 'Open Street Map',
checked: true,
leaf: true,
itemId: 'OMS'
},{
text: 'MapQuest',
leaf: false,
children:[{
text: 'Road',
leaf:true,
checked: false,
itemId: 'MapQuest',
val: 'osm'
},{
text: 'Satellite',
leaf:true,
checked: false,
itemId: 'MapQuest',
val: 'sat'
},{
text: 'Hybride',
leaf:true,
checked: false,
itemId: 'MapQuest',
val: 'hyb'
}]
}]
}]
}
});
}
}
It works partially. When I first hit the picker, it shows me a treepanel, but when I expand some nodes (leaf=false), then it gets closed. The same happens, when I check a tree leaf - I do not want that, because, the user is allowed to check multiple nodes. Beside, even when I check some leaves, the value of the picker stays unchanged (it keeps showing emptyText value). So, how to fix all this?
You can use following sample:
Ext.define('Ext.ux.TreeCombo',
{
extend: 'Ext.form.field.Picker',
alias: 'widget.treecombo',
tree: false,
constructor: function(config)
{
this.addEvents(
{
"itemclick" : true
});
this.listeners = config.listeners;
this.callParent(arguments);
},
records: [],
recursiveRecords: [],
ids: [],
selectChildren: true,
canSelectFolders: true,
multiselect: false,
displayField: 'text',
valueField: 'id',
treeWidth: 300,
matchFieldWidth: false,
treeHeight: 400,
masN: 0,
recursivePush: function(node, setIds)
{
var me = this;
me.addRecRecord(node);
if(setIds) me.addIds(node);
node.eachChild(function(nodesingle)
{
if(nodesingle.hasChildNodes() == true)
{
me.recursivePush(nodesingle, setIds);
}
else
{
me.addRecRecord(nodesingle);
if(setIds) me.addIds(nodesingle);
}
});
},
recursiveUnPush: function(node)
{
var me = this;
me.removeIds(node);
node.eachChild(function(nodesingle)
{
if(nodesingle.hasChildNodes() == true)
{
me.recursiveUnPush(nodesingle);
}
else me.removeIds(nodesingle);
});
},
addRecRecord: function(record)
{
var me = this;
for(var i=0,j=me.recursiveRecords.length;i<j;i++)
{
var item = me.recursiveRecords[i];
if(item)
{
if(item.getId() == record.getId()) return;
}
}
me.recursiveRecords.push(record);
},
afterLoadSetValue: false,
setValue: function(valueInit)
{
if(typeof valueInit == 'undefined') return;
var me = this,
tree = this.tree,
values = (valueInit == '') ? [] : valueInit.split(','),
valueFin = [];
inputEl = me.inputEl;
if(tree.store.isLoading())
{
me.afterLoadSetValue = valueInit;
}
if(inputEl && me.emptyText && !Ext.isEmpty(values))
{
inputEl.removeCls(me.emptyCls);
}
if(tree == false) return false;
var node = tree.getRootNode();
if(node == null) return false;
me.recursiveRecords = [];
me.recursivePush(node, false);
me.records = [];
Ext.each(me.recursiveRecords, function(record)
{
var id = record.get(me.valueField),
index = values.indexOf(''+id);
if(me.multiselect == true) record.set('checked', false);
if(index != -1)
{
valueFin.push(record.get(me.displayField));
if(me.multiselect == true) record.set('checked', true);
me.addRecord(record);
}
});
me.value = valueInit;
me.setRawValue(valueFin.join(', '));
me.checkChange();
me.applyEmptyText();
return me;
},
getValue: function()
{
return this.value;
},
getSubmitValue: function()
{
return this.value;
},
checkParentNodes: function(node)
{
if(node == null) return;
var me = this,
checkedAll = true;
node.eachChild(function(nodesingle)
{
var id = nodesingle.getId(),
index = me.ids.indexOf(''+id);
if(index == -1) checkedAll = false;
});
if(checkedAll == true)
{
me.addIds(node);
me.checkParentNodes(node.parentNode);
}
else
{
me.removeIds(node);
me.checkParentNodes(node.parentNode);
}
},
initComponent: function()
{
var me = this;
me.tree = Ext.create('Ext.tree.Panel',
{
alias: 'widget.assetstree',
hidden: true,
minHeight: 300,
rootVisible: (typeof me.rootVisible != 'undefined') ? me.rootVisible : true,
floating: true,
useArrows: true,
width: me.treeWidth,
autoScroll: true,
height: me.treeHeight,
store: me.store,
listeners:
{
load: function(store, records)
{
if(me.afterLoadSetValue != false)
{
me.setValue(me.afterLoadSetValue);
}
},
itemclick: function(view, record, item, index, e, eOpts)
{
me.itemTreeClick(view, record, item, index, e, eOpts, me)
}
}
});
if(me.tree.getRootNode().get('checked') != null) me.multiselect = true;
this.createPicker = function()
{
var me = this;
return me.tree;
};
this.callParent(arguments);
},
addIds: function(record)
{
var me = this;
if(me.ids.indexOf(''+record.getId()) == -1) me.ids.push(''+record.get(me.valueField));
},
removeIds: function(record)
{
var me = this,
index = me.ids.indexOf(''+record.getId());
if(index != -1)
{
me.ids.splice(index, 1);
}
},
addRecord: function(record)
{
var me = this;
for(var i=0,j=me.records.length;i<j;i++)
{
var item = me.records[i];
if(item)
{
if(item.getId() == record.getId()) return;
}
}
me.records.push(record);
},
removeRecord: function(record)
{
var me = this;
for(var i=0,j=me.records.length;i<j;i++)
{
var item = me.records[i];
if(item && item.getId() == record.getId()) delete(me.records[i]);
}
},
itemTreeClick: function(view, record, item, index, e, eOpts, treeCombo)
{
var me = treeCombo,
checked = !record.get('checked');//it is still not checked if will be checked in this event
if(me.multiselect == true) record.set('checked', checked);//check record
var node = me.tree.getRootNode().findChild(me.valueField, record.get(me.valueField), true);
if(node == null)
{
if(me.tree.getRootNode().get(me.valueField) == record.get(me.valueField)) node = me.tree.getRootNode();
else return false;
}
if(me.multiselect == false) me.ids = [];
//if it can't select folders and it is a folder check existing values and return false
if(me.canSelectFolders == false && record.get('leaf') == false)
{
me.setRecordsValue(view, record, item, index, e, eOpts, treeCombo);
return false;
}
//if record is leaf
if(record.get('leaf') == true)
{
if(checked == true)
{
me.addIds(record);
}
else
{
me.removeIds(record);
}
}
else //it's a directory
{
me.recursiveRecords = [];
if(checked == true)
{
if(me.multiselect == false)
{
if(me.canSelectFolders == true) me.addIds(record);
}
else
{
if(me.canSelectFolders == true)
{
me.recursivePush(node, true);
}
}
}
else
{
if(me.multiselect == false)
{
if(me.canSelectFolders == true) me.recursiveUnPush(node);
else me.removeIds(record);
}
else me.recursiveUnPush(node);
}
}
//this will check every parent node that has his all children selected
if(me.canSelectFolders == true && me.multiselect == true) me.checkParentNodes(node.parentNode);
me.setRecordsValue(view, record, item, index, e, eOpts, treeCombo);
},
fixIds: function()
{
var me = this;
for(var i=0,j=me.ids.length;i<j;i++)
{
if(me.ids[i] == 'NaN') me.ids.splice(i, 1);
}
},
setRecordsValue: function(view, record, item, index, e, eOpts, treeCombo)
{
var me = treeCombo;
me.fixIds();
me.setValue(me.ids.join(','));
me.fireEvent('itemclick', me, record, item, index, e, eOpts, me.records, me.ids);
if(me.multiselect == false) me.onTriggerClick();
}
});
var storeMenu = Ext.create('Ext.data.TreeStore',
{
root:
{
text: 'Root',
id: '0',
expanded: true,
children:
[
{id: '1', text: 'First node', leaf: false, children:
[
{id: '3', text: 'First child node', leaf: true},
{id: '4', text: 'Second child node', leaf: true}
]
},
{id: '2', text: 'Second node', leaf: true}
]
},
folderSort: false
});
Ext.onReady(function() {
Ext.create('Ext.ux.TreeCombo', {
margin:10,
width:120,
height: 10,
treeHeight: 10,
treeWidth: 240,
renderTo: 'treecombo3',
store: storeMenu,
selectChildren: false,
canSelectFolders: true
,itemTreeClick: function(view, record, item, index, e, eOpts, treeCombo)
{
var id = record.data.id;
}
});
});
I wrote CardBoard Rally sdk 2 app to which I added filter which apply to Backlog and Releases too. But I want to add two different filters, one for releases and one for backlog
See in image attached, u can see one column for Backlog and other for releases
So I should be able to say Now filter Backlog features, and Now filter Releases features
Below is my some of code snippet
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
autoScroll: true,
all_releases: [],
items:[{ xtype: 'container', itemId: 'filter_box', padding: 5},{xtype:'container',itemId:'button_box', padding: 5}],
logger: new Rally.technicalservices.logger(),
launch: function() {
//var allReleases = this._getReleases();
this._drawCardBoard(this, filters= null);
this.down('#button_box').add({
xtype: 'rallybutton',
text: 'Filter Criteria',
itemId: 'run-button',
scope: this,
handler: this._run,
margin: '0 0 0 10'
});
this.down('#button_box').add({
xtype: 'rallybutton',
text: 'Prev',
itemId: 'prev-button',
scope: this,
handler: this._setPrevReleaseDate,
margin: '0 0 0 100'
});
this.down('#button_box').add({
xtype: 'rallybutton',
text: 'Next',
itemId: 'next-button',
scope: this,
handler: this._setNextReleaseDate,
margin: '0 0 0 650'
});
},
_setPrevReleaseDate: function() {
if (this.globalVar == undefined) {
this.globalVar = new Date();
} else {
this.globalVar = new Date(this.globalVar);
};
this.globalVar = Rally.util.DateTime.formatWithDefault(Ext.Date.subtract(this.globalVar, Ext.Date.DAY, 224));
this._drawCardBoard(this, filters= null);
},
_setNextReleaseDate: function() {
if (this.globalVar == undefined) {
this.globalVar = new Date();
} else {
this.globalVar = new Date(this.globalVar);
};
this.globalVar = Rally.util.DateTime.formatWithDefault(Ext.Date.add(this.globalVar, Ext.Date.DAY, 224));
this._drawCardBoard(this, filters= null);
},
_getFilters: function(records) {
var filters = null;
if (records.length >= 1) {
if (records[0].data.PortfolioItemTypeName == "MMF") {
filters = Ext.create('Rally.data.QueryFilter',{
property: 'Parent',
operator: '=',
value: records[0].get("_ref")
});
} else if (records[0].data.PortfolioItemTypeName == "Epic") {
filters = Ext.create('Rally.data.QueryFilter',{
property: 'Parent.Parent',
operator: '=',
value: records[0].get("_ref")
});
} else if (records[0].data.PortfolioItemTypeName == "Program") {
filters = Ext.create('Rally.data.QueryFilter',{
property: 'Parent.Parent.Parent',
operator: '=',
value: records[0].get("_ref")
});
}
for ( var i=1;i<records.length;i++ ) {
if (records[i].data.PortfolioItemTypeName == "MMF") {
filters = filters.or(Ext.create('Rally.data.QueryFilter',{
property: 'Parent',
operator: '=',
value: records[i].get("_ref")
}));
} else if (records[i].data.PortfolioItemTypeName == "Epic") {
filters = filters.or(Ext.create('Rally.data.QueryFilter',{
property: 'Parent.Parent',
operator: '=',
value: records[i].get("_ref")
}));
} else if (records[i].data.PortfolioItemTypeName == "Program") {
filters = filters.or(Ext.create('Rally.data.QueryFilter',{
property: 'Parent.Parent.Parent',
operator: '=',
value: records[i].get("_ref")
}));
}
}
}
return filters;
},
_drawCardBoard: function(that, filters){
if (that.cardboard) {
that.cardboard.destroy();
};
var me = that;
if (filters == null) {
filters = [];
}
me.cardboard = Ext.create('Rally.ui.cardboard.CardBoard',{
types: ['PortfolioItem/Feature'],
attribute: 'Release',
config: {globalVar: this.globalVar},
columnConfig: {
xtype: 'rallycardboardcolumn',
displayField: 'Name',
valueField: '_ref',
plugins: [
{ptype:'rallycolumndropcontroller'},
{ptype:'rallycardboardcardrecordprocessor'},
{ptype:'tscolumnheaderupdater'} /*,
{ptype:'tscolumnheaderupdater', field_to_aggregate: 'LeafStoryPlanEstimateTotal'}*/
],
storeConfig: {
filters: filters,
context: this.getContext().getDataContext()
}
},
addColumn: function (columnConfig, index) {
console.log(columnConfig, index,"columnConfig, index");
var column = this._createColumnDefinition(columnConfig);
Ext.Array.insert(this.columnDefinitions, Ext.isNumber(index) ? index : this.columnDefinitions.length, [column]);
return column;
},
cardConfig: {
editable: true,
showIconsAndHighlightBorder: false,
showReadyIcon: true,
showBlockedIcon: true,
showColorIcon: true,
showPlusIcon: true,
showGearIcon: true,
fields: [
'FormattedID',
'Name',
'Parent',
'ReleaseDate',
'ReleaseStartDate',
{ name: 'Project', renderer: me._renderProject },
{ name: 'PercentDoneByStoryPlanEstimate' },
{ name: 'PreliminaryEstimate', fetch: ['PreliminaryEstimate', 'Name'], renderTpl: Ext.create('Ext.XTemplate', '{PreliminaryEstimate.Name}')},
{ name: 'LeafStoryPlanEstimateTotal', fetch: ['LeafStoryPlanEstimateTotal'], renderTpl: Ext.create('Ext.XTemplate', 'Plan Estimate Total: {LeafStoryPlanEstimateTotal}')}
],
},
listeners: {
beforeShow: this._onTeamMembersLoaded,
added: function(card,container){
//card.set('DisplayColor', "blue");
me.logger.log(this,card,container);
},
fieldClick: function(eOpts) {
me.logger.log(this,eOpts);
if ( eOpts == "PercentDoneByStoryPlanEstimate" ) {
me._showDoneTooltip(eOpts,this);
}
},
scope: this
}
});
_getLocalReleases: function(retrievedColumns, today_iso) {
var me = this;
if (today_iso == undefined) {
today_iso = Rally.util.DateTime.toIsoString(new Date(),false);
}
var filters = [{property:'ReleaseDate',operator:'>',value:today_iso}];
var iteration_names = [];
Ext.create('Rally.data.WsapiDataStore',{
model:me.attribute,
autoLoad: true,
filters: filters,
context: { projectScopeUp: false, projectScopeDown: false },
sorters: [
{
property: 'ReleaseDate',
direction: 'ASC'
}
],
//limit: Infinity,
pageSize: 4,
//buffered: true,
//purgePageCount: 4,
fetch: ['Name','ReleaseStartDate','ReleaseDate','PlannedVelocity'],
listeners: {
load: function(store,records) {
Ext.Array.each(records, function(record){
var start_date = Rally.util.DateTime.formatWithNoYearWithDefault(record.get('ReleaseStartDate'));
var end_date = Rally.util.DateTime.formatWithNoYearWithDefault(record.get('ReleaseDate'));
iteration_names.push(record.get('Name'));
//iteration_names.push(record.get('ReleaseDate'));
retrievedColumns.push({
value: record,
_planned_velocity: 0,
_missing_estimate: false,
columnHeaderConfig: {
headerTpl: "{name}<br/>{start_date} - {end_date}",
headerData: {
name: record.get('Name'),
start_date: start_date,
end_date: end_date,
planned_velocity: 0,
missing_estimate: false
}
}
});
});
this._getAllReleases(retrievedColumns,iteration_names);
},
scope: this
}
});
},
applyLocalFilters: function() {
this.applyFilters(this.localFilters);
},
_getAllReleases: function(retrievedColumns,iteration_names, today_iso) {
var me = this;
if (today_iso == undefined) {
today_iso = Rally.util.DateTime.toIsoString(new Date(),false);
}
var filters = [{property:'ReleaseDate',operator:'>',value:today_iso}];
Ext.create('Rally.data.WsapiDataStore',{
model:me.attribute,
autoLoad: true,
filters: filters,
sorters: [
{
property: 'ReleaseDate',
direction: 'ASC'
}
],
fetch: ['Name','Project','PlannedVelocity'],
listeners: {
load: function(store,records) {
Ext.Array.each(records, function(record){
var planned_velocity = record.get('PlannedVelocity') || 0;
var index = Ext.Array.indexOf(iteration_names[0],record.get('Name'));
if (planned_velocity == 0 ) {
retrievedColumns[index+1]._missing_estimate = true;
}
retrievedColumns[index+1]._planned_velocity += planned_velocity;
});
this.fireEvent('columnsretrieved',this,retrievedColumns);
this.columnDefinitions = [];
_.map(retrievedColumns,this.addColumn,this);
this._renderColumns();
},
scope: this
}
});
},
_createColumnDefinition: function (columnConfig) {
var config = Ext.merge({
enableCrossColumnRanking: this.enableCrossColumnRanking
}, this.columnConfig, columnConfig);
var enableRanking = this.enableRanking;
if (this.context) {
var workspace = this.context.getWorkspace();
if (workspace) {
enableRanking = enableRanking && workspace.WorkspaceConfiguration.DragDropRankingEnabled;
}
}
var listenersConfig = {
ready: this._onColumnReady,
select: this._onCardSelect,
deselect: this._onCardDeselect,
cardinvalid: this._onCardInvalid,
cardready: this._onCardReady,
scope: this
};
if (!this.serverSideFiltering) {
listenersConfig.filter = this.applyLocalFilters;
}
Ext.merge(config, {
cardConfig: Ext.clone(this.cardConfig),
columnHeaderConfig: Ext.clone(this.columnHeaderConfig),
model: this.models,
attribute: this.attribute,
storeConfig: Ext.clone(this.storeConfig),
enableRanking: enableRanking,
filterCollection: this.filterCollection ? this.filterCollection.clone() : undefined,
ownerCardboard: this,
listeners: listenersConfig,
ddGroup: this.ddGroup
});
if (this.readOnly) {
config.dropControllerConfig = false;
}
//merge configs, unioning collections
var cardConfig = config.cardConfig;
if (columnConfig.cardConfig) {
Ext.Object.merge(cardConfig, columnConfig.cardConfig);
cardConfig.fields = Ext.Array.merge(columnConfig.cardConfig.fields || [], this.cardConfig.fields || []);
}
var storeConfig = config.storeConfig;
if (columnConfig.storeConfig) {
Ext.Object.merge(storeConfig, columnConfig.storeConfig);
storeConfig.filters = Ext.Array.merge(columnConfig.storeConfig.filters || [], this.storeConfig.filters || []);
}
console.log("columnConfig", Ext.clone(columnConfig));
console.log("storeConfig", Ext.clone(storeConfig));
return Ext.widget(config.xtype, config);
},
});
Ext.override(Rally.ui.cardboard.Card,{
_setupPlugins: function() {
var cardContentRightPlugin = {ptype: 'rallycardcontentright'};
this.plugins.push(cardContentRightPlugin);
this.plugins.push({ptype: 'rallycardcontentleft'});
if (this.record.get('updatable')) {
if (this.editable) {
this.addCls('editable');
this.plugins.push({ptype: 'rallycardediting'});
var predicateFn = Rally.predicate.RecordPredicates.hasField('PlanEstimate');
if (predicateFn(this.record) && Ext.Array.contains(this.getFields(), 'PlanEstimate')) {
cardContentRightPlugin.showPlanEstimate = true;
}
if (this.enableValidationUi) {
this.plugins.push({ptype: 'rallycardvalidation'});
this.plugins.push({ptype: 'rallycardvalidationui', notificationFieldNames: ['PlanEstimate']});
}
}
if (this.showIconsAndHighlightBorder) {
this.plugins.push({
ptype: 'rallycardicons',
showMenus: this.showIconMenus,
showColorPopover: this.showColorPopover
});
}
}
if (this.showAge > -1) {
this.plugins.push({ptype: 'rallycardage'});
}
this.plugins.push({ptype:'tscardreleasealignment'});
}
}),
Ext.override(Rally.ui.cardboard.Column,{
getStoreFilter: function(model) {
var property = this.attribute;
var value = this.getValue();
if ( this.attribute == "Release" ) {
property = "Release.Name";
if ( value ) {
value = value.get('Name');
}
}
return {
property:property,
operator: '=',
value: value
};
},
isMatchingRecord: function(record) {
var recordValue = record.get(this.attribute);
if (recordValue) {
recordValue = recordValue.Name;
}
var columnValue = this.getValue();
if ( columnValue ) {
columnValue = columnValue.get('Name');
}
return (columnValue === recordValue );
},
addCard: function(card, index, highlight) {
var record = card.getRecord();
var target_value = this.getValue();
if ( target_value && typeof(target_value.get) === "function" ) {
target_value = this.getValue().get('_ref');
}
record.set(this.attribute,target_value);
if (target_value) {
record.set("PlannedStartDate",this.getValue().get('ReleaseStartDate'));
record.set("PlannedEndDate",this.getValue().get('ReleaseDate'));
} else {
record.set("PlannedStartDate",null);
record.set("PlannedEndDate",null);
}
if (!Ext.isNumber(index)) {
//find where it should go
var records = Ext.clone(this.getRecords());
records.push(record);
this._sortRecords(records);
var recordIndex = 0;
for (var iIndex = 0, l = records.length; iIndex < l; iIndex++) {
var i = records[iIndex];
if (i.get("ObjectID") === record.get("ObjectID")) {
recordIndex = iIndex;
break;
}
}
index = recordIndex;
}
this._renderCard(card, index);
if (highlight) {
card.highlight();
}
this.fireEvent('addcard');
card.fireEvent('ready', card);
},
I am trying to implement some drag and drop functionallity from a Tree Panel to a View but I have not been able to do this. I am new using ExtJs and maybe I am doing something wrong.
I have my tree defined like this:
var treeMeasures = Ext.create('Ext.tree.Panel', {
id: 'treeMeasuresPanel',
title: 'Measures',
region: 'north',
store: dsMeasures,
rootVisible: true,
width: '100%',
height: '50%',
useArrows: true,
enableDD: true,
allowDrop: false,
collapsible: true,
border: 0,
style: 'border-right:1px solid #99BCE8;border-top:none;border-left:none;border-bottom: none;',
viewConfig: {
listeners: {
render: initializeFieldsDragZone
},
plugins: {
ptype: 'treeviewdragdrop',
ddGroup: 'fieldsToAreas',
enableDrag: true,
enableDrop: false,
containerScroll: true
}
}
});
The initializeFieldsDragZone function:
function initializeFieldsDragZone(v, record, item, index, evt, eOpts) {
v.dragZone = Ext.create('Ext.dd.DragZone', v.getEl(), {
getDragData: function (e) {
var sourceEl = e.getTarget(v.itemSelector, 10), d;
if (sourceEl) {
d = sourceEl.cloneNode(true);
d.id = Ext.id();
return v.dragData = {
sourceEl: sourceEl,
repairXY: Ext.fly(sourceEl).getXY(),
ddel: d,
controlData: v.getRecord(sourceEl).data
};
}
},
// Provide coordinates for the proxy to slide back to on failed drag.
// This is the original XY coordinates of the draggable element.
getRepairXY: function () {
return this.dragData.repairXY;
}
});
}
The View:
var filterAreaView = Ext.create('Ext.view.View', {
store: dsFilterArea,
tpl: "",
ddGroup: 'fieldsToAreas',
bodyStyle: {
background: 'ffffff'
},
listeners: {
render: initializeAreasDropZone
}
});
And the initializeAreasDropZone function is:
function initializeAreasDropZone(area) {
var view = area.getEl();
view.dropZone = Ext.create('Ext.dd.DropZone', area.el, {
getTargetFromEvent: function (e) {
return e.getTarget('.x-grid-row');
},
onNodeEnter: function (target, dd, e, data) {
},
onNodeOut: function (target, dd, e, data) {
},
onNodeOver: function (target, dd, e, data) {
return true;
},
onNodeDrop: function (target, dd, e, data) {
// My Code
return true;
}
});
}
And the problem is that when I drag the node from the tree and try to drop into the view nothing happens.
Does anyone knows if I am doing something wrong?
Thanks,
Alberto
I think you may be overthinking this. I created a working model of DD between two panels (Ext.tree.Panel) each containing a root, with multiple folders, and multiple leaves in each folder. Simply by adding the plugin to each tree enabled DD:
viewConfig: {
plugins: {
ptype: 'treeviewdragdrop',
ddGroup: 'myDDGroup',
appendOnly: true,
sortOnDrop: true,
containerScroll: true
}
},
After doing this, when I click and drag a leaf from one tree to the other, it dutifully adds the leaf to the target folder upon release of the mouse button. I didn't have to do anything else as far as monitoring events.
if you use TreePanel for Drag Zone, i think we don't need to create function initializeFieldsDragZone, just use plugin "treeviewdragdrop".
The problem from your code is initializeAreasDropZone must have ddgroup same as the plugin:
function initializeAreasDropZone(area) {
var view = area.getEl();
view.dropZone = Ext.create('Ext.dd.DropZone', area.el, {
getTargetFromEvent: function (e) {
return e.getTarget('.x-grid-row');
},
onNodeEnter: function (target, dd, e, data) {
},
onNodeOut: function (target, dd, e, data) {
},
onNodeOver: function (target, dd, e, data) {
return true;
},
onNodeDrop: function (target, dd, e, data) {
console.log(data);
},
ddGroup: 'fieldsToAreas'
});
}
cheers