viewConfig for getRowClass broken in rc1/2? - rally

I've got an app that I was upgrading to SDK version rc2 from p5. It overrides the getRowClass() function in the viewConfig to change the row color setting the class if there is a tool tip displayed as per the code below...but this code for some reason seems to be broken in rc1 and rc2.
In p5, this function is called once per row (which I can see when it hits the console.log), but does not seeem to be called in rc1/rc2.
Can anybody confirm whether this is a defect is rc2, or a feature that is no longer being supported?
var grid = {
xtype: 'rallygrid',
showPagingToolbar: false,
disableColumnMenus: false,
store: this.gridDataStore,
viewConfig: {
getRowClass: function(record) {
var toolTip = record.get('ToolTip');
console.log('checking tooltip', record);
return toolTip !== null ? 'special-row' : 'normal-row';
},
listeners: { render: this._createToolTip }
},
columnCfgs: this.columnCfgs,
border: 1
};

This is due to a defect in the grid where we are blindly overriding the getRowClass function on the viewConfig w/o checking to make sure there wasn't one there already. Hopefully this defect will be fixed soon. Check out my answer to this other, very similar question: https://stackoverflow.com/a/17891138/728184
You should be able to have your getRowClass function win out by setting it in the beforerender event listener (thereby re-clobbering the one that we put on there, which is really only useful for automated testing anyway and not required in any way for the grid to function correctly).
UPDATE:
I just fixed this in the nightly build, so this should no longer be an issue in public sdk builds beginning with the next public release after 2.0rc2.

Related

dojo1.10 Dynamic update of dijit.form.Select

I was trying to asynchronously update a Select field via Memory and ObjectStore. This doesn't work. Setting the data to the Memory object before creating the Select element works fine. Updating the Memory object after creating the Select element doesn't work anymore.
Example code:
require([
"dojo/ready",
"dijit/form/Select",
"dojo/store/Memory",
"dojo/store/Observable",
"dojo/data/ObjectStore",
'dojo/domReady!'
], function(ready, Select, Memory, Observable, ObjectStore, dom){
ready(function() {
var mymem = new Memory();
var myobs = new Observable(mymem);
var mystore = new ObjectStore({ objectStore: myobs });
/* updating memory here works :) */
//mymem.setData([ { id: 2, label: 'qwertz2' }, { id: 3, label: 'qwertz3' } ]);
var s = new Select({
store: mystore
}, 'appsAdminQueueContainer');
s.startup();
/* updating memory here doesn't work :( */
mymem.setData([ { id: 2, label: 'qwertz2' }, { id: 3, label: 'qwertz3' } ]);
});
}
);
Real working example: https://jsfiddle.net/mirQ/ra0dqb63/5/
Is this a bug or is there a solution to be able to update the content of the Select field after creating it - without having to access the Select field directly?
UPDATE
Thank you for your response.
The use of dojo/ready was just a missed leftover while simplifying my code, sorry.
That the use of the ObjectStore is not necessary was not clear to me. Thanks for clearing up.
Okay, the real problem seems to be indeed the last point. I think I have to extend my description.
Updated/extended problem description:
I'm using a grid. At first I was using dojox/grid/DataGrid, but then I switched to dgrid. Everything works well, but I want to use dijit.form.Select as editor for one column. This works also well if the data is static. But in one column I have to read dynamic data from the server. This data comes in JSON format.
First I tried to solve this with the use of dojo/data/ItemFileReadStore - that worked. But it's deprecated and I need to implement a formatter for that column that has to have access to the same JSON data read from the server. I don't have the code for that solution anymore, but it didn't work. I wasn't able to successfully query the data from within the formatter function.
Then I switched to Memory and xhr. The response from the server comes after the Memory object is created (and, as it seems, after creating the Select), so I had to use setData to bring my loaded data in the store. And because the Select is only an editor of a grid, I don't have access to the object itself to be able to re-set the store after updating the data.
I hope my extended description makes my real problem a bit clearer. Thanks in advance for your help!
Mirko
This works for me:
require([
'dijit/form/Select',
'dojo/store/Memory',
'dojo/store/Observable',
], function (Select, Memory, Observable) {
var mymem = new Memory({
data: [{
id: 2,
label: 'qwertz2'
}, {
id: 3,
label: 'qwertz3'
}]
});
var myobs = new Observable(mymem);
var s = new Select({
labelAttr: 'label',
store: myobs
}, 'appsAdminQueueContainer');
s.startup();
myobs.add({ id: 4, label: 'qwerty' });
});
Notable changes:
There's no reason to use dojo/ready in this code. The require callback already waits for modules to load, and as long as this script is at the bottom of the body, there's no need to wait for the DOM to load, either.
There's no need to use a dojo/data store adapter. dijit/form/Select supports dojo/store as well (as of 1.8 if I recall correctly). This might also have been why observation wasn't working. The only difference is labelAttr must be specified on the Select since dojo/store has no concept of a label property.
(Edit) now that I re-read the question, I notice you are calling setData. setData does not fire observers. setData completely resets the store's data, and to reflect that, you would need to actually reset the store on the select entirely (which requires calling setStore, not set('store', ...), if you are using 1.9 or earlier, because Select was never updated properly to support the set API until 1.10).
(Edit #2) Given that the primary reason you are calling setData is due to creating the store before actually having data for it, your case would probably be greatly simplified by using the RequestMemory store implementation from dojo-smore. It basically re-adds the url support that dojo/data/ItemFileReadStore had but dojo/store/Memory didn't.

Rally grid color rows based on model

I have a rallygrid that is configured to display two models: PortfolioItem/Feature and PortfolioItem/Rollup. I want to color them in the grid to differentiate them. I am not garunteed that they will alternate in the grid, or anything like that. I just want to apply a subtle color to the rollups to differentiate them visually.
Can anyone think of an easy way to achieve this?
I have tried:
viewConfig: {
getRowClass: function(record, index, rowParams, store) {
console.log('record',record); // nothing logged in console
console.log('index',index);
return 'colorCodeGrid'; // class never added
}
},
[EDIT]
viewConfig: {
stripeRows: false, // rows are no longer striped
getRowClass: function(record, index, rowParams, store) {
console.log('record',record); // still nothing logged in console
console.log('index',index);
return 'colorCodeGrid'; // class never added
}
},
It is strange to me that the viewConfig does correctly un-stripe the rows, but the getRowClass never gets called. I thought maybe just the viewConfig as a whole was not being used in the case of a rallygrid.
Your approach above with the viewConfig should work- I am going to file a defect on this. The root cause is that the Rally.ui.grid.GridView is blowing away the getRowClass function in its constructor (for internal browser testing purposes- ugghh) rather than checking if there was one supplied and calling that as well.
You can see it the source for the constructor here: https://developer.help.rallydev.com/apps/2.0rc1/doc/source/GridView.html#Rally-ui-grid-GridView
You should be able to work around it by just re-overriding the function before the view is rendered.
[EDIT by asker]
Added the following to the grid, and it worked:
listeners: {
beforerender: function(cmp) {
console.log('beforerender');
console.log('view',cmp);
cmp.view.getRowClass = function(record, index, rowParams, store) {
console.log('record',record); // still nothing logged in console
console.log('index',index);
return 'colorCodeGrid'; // class never added
};
}
},
UPDATE:
I just fixed this in the nightly build, so this should no longer be an issue in public sdk builds beginning with the next public release after 2.0rc2.

Rally rallyaddnew with Portfolio Items

I have been trying to use a rallyaddnew to add Features and Rollups, which will then be rendered in a grid/cardboard. I got it to work and display, but I cannot customize the text to say create a new "Feature" or "Rollup", rather it says create a new "PortfolioItem/Feature" and "PortfolioItem/Rollup"
{
xtype: 'rallyaddnew',
recordTypes: ['PortfolioItem/Feature', 'PortfolioItem/Rollup'],
listeners: {
recordAdd: function() {
//
},
beforeRecordAdd: function() {
//
}
}
I couldn't find anything in the SDK on how to customize this.
This is a defect. It should be using the display name of the type instead of its type path. I'll file a defect for this. FYI there is also an existing defect around PI types and adding with details that has been fixed but has not been released in an SDK version yet.

FileUploadField 'stuck' after submitting form with ExtJS4/DWR

im using extjs4 with dwr3 to upload a file
this is all i have in my form
{xtype: 'fileuploadfield',
name: 'file',
fieldLabel: 'Archivo',
allowBlank: false,
buttonText: 'Seleccionar...'
}, {
xtype: 'button',
text: 'Cargar',
action: 'cargarArchivo'
}
when i click the button (labeled Cargar) it submits the file and stays in the same page, so far so good. Problem is, when i choose another file, the text in the field stays the same instead of showing the new file chosen
this is what i have in my controller:
init: function() {
this.control({
'NciImport button[action=cargarArchivo]': {
click: this.cargaArchivo
}
});
},
cargaArchivo : function (button){
clickedButton = button;
bsNciNiv.cargaArchivoNci(dwr.util.getValue('file'), function(x,y,z){
clickedButton.up('form').down('fileuploadfield').createFileInput(); // funny solution
});
}
The bsNciNiv.cargaArchivoNci part is my DWR service
the line i commented as funny solution kind of works, after adding it the rest works as expected, but i really dont think it is the right solution, just added it as a hint in case its useful
can anyone confirm if this is a bug or if theres a way to fix this? thanks
(btw not sure if this has anything to do with dwr3, but i tagged it anyway)
I just ran into this same problem using Ext-JS 4.1.1 and DWR3. I debugged the DWR javascript and found the cause. When the dwr method parameters include a fileupload field, dwr constructs a multipart post message and a hidden iframe rather than using XmlHttpRequest. As part of this process, it replaces the original fileupload element (this itself is a hidden element, created and managed by the Ext FileUpload component) with a clone (same ID and properties). As a result, the Ext field's fileInputEl property is no longer referring to the replaced element and the component's onFileChange() event handler is not registered for the new element's 'change' event. So, it isn't a bug in Ext-JS.
I worked around it in my callback like this:
var fileInputId = uploadField.fileInputEl.dom.id;
MyDwrService.fileUpload(uploadField.fileInputEl.dom, arg2, function(results) {
uploadField.fileInputEl = Ext.get(document.getElementById(fileInputId));
uploadField.fileInputEl.on({
scope: uploadField,
change: uploadField.onFileChange
});
});
It worked for me in Firefox, Chrome and IE8
My guess is that this component was not designed to upload multiple files (in series).
The issue you are seeing is probably due to this hidden element not getting cleared: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.form.field.File-property-fileInputEl
You can probably file this as a bug with Sencha although they might consider it a feature :)

Using dijit.InlineEditBox with dijit.form.Select

I'm trying to use a dijit.form.Select as the editor for my dijit.InlineEditBox. Two problems / unexpected behavior seem to occur:
Inconsistently, the InLineEditBox doesn't have the initial value set as selected
Consistently, after selecting a choice, the value that should be hidden is shown instead of the label.
The width isn't set to 130px
Here's working code: http://jsfiddle.net/mimercha/Vuet8/7/
The jist
<span dojoType="dijit.InlineEditBox" editor="dijit.form.Select"
editorParams="{
options: [
{label:'None',value:'none'},
{label:'Student',value:'stu'},
{label:'Professor',value:'prof',selected:true},
],
style:'width:1000px;',
}"
editorStyle="width: 1000px;"
>
</span>
Any help is greatly appreciated! Thanks!
Okay, after a few MORE hours struggling with the mess that is dijit.InlineEditBox, I think I have the solution to the remaining issue (#2).
EDIT: My first solution to #2 is still flawed; the implementation at http://jsfiddle.net/kfranqueiro/Vuet8/10/ will never return the actual internal value when get('value') is called.
EDIT #2: I've revamped the solution so that value still retains the real (hidden) value, keeping displayedValue separate. See if this works better:
http://jsfiddle.net/kfranqueiro/Vuet8/13/
First, to recap for those who weren't on IRC:
Issue #1 was happening due to value not being properly set as a top-level property of the InlineEditBox itself; it didn't pick it up properly from the wrapped widget.
Issue #3 was happening due to some pretty crazy logic that InlineEditBox executes to try to resolve styles. Turns out though that InlineEditBox makes setting width particularly easy by also exposing it as a top-level numeric attribute. (Though IINM you can also specify a percentage as a string e.g. "50%")
Now, issue #2...that was the killer. The problem is, while InlineEditBox seems to have some logic to account for widgets that have a displayedValue attribute, that logic is sometimes wrong (it expects a displayedValue property to actually exist on the widget, which isn't necessarily the case), and other times missing entirely (when the InlineEditBox initializes). I've worked around those as best I could in my own dojo.declared extensions to InlineEditBox and the internal widget it uses, _InlineEditor - since generally it's a good idea to leave the original distribution untouched.
It's not pretty (neither is the underlying code I dug through to understand and come up with this), but it seems to be doing its job.
But man, this was rather interesting. And potentially pertinent to my interests as well, as we have used this widget in our UIs as well, and will be using it more in the future.
Let me know if anything backfires.
hm...
<span dojoType="dijit.InlineEditBox" editor="dijit.form.Select"
editorParams="{
options: [
{label:'None',value:'none'},
{label:'Student',value:'stu'},
{label:'Professor',value:'prof',selected:true},**<<<<** and this comma is for?
],
style:'width:1000px;',**<<<<** and this comma is for?
}"
editorStyle="width: 1000px;"
>
</span>
Also, when using dijit.form.Select, selected value is not attr "selected" but value.
And if you enter prof inside <span ...blah > prof </span> than your proper selected option will be selected ;)
Dijit select checks for VALUE, not attr.
This may be fixed in recent Dojo - see http://bugs.dojotoolkit.org/ticket/15141 - but using 1.7.3 I found this worked:
In my app directory, at the same level as dojo, dijit and dojox, I created a file InlineSelectBox.js which extends InlineEditBox with code to set the HTML on the associated domNode from the value of the Dijit, and which wires up that code to the onChange() event:
define(["dijit/InlineEditBox",
"dijit/form/Select",
"dojo/on",
"dojo/_base/declare",
"dojo/_base/array"
],
function(InlineEditBox, Select, on, declare, array){
return declare(InlineEditBox, {
_setLabel: function() {
array.some(this.editorParams.options, function(option, i){
if (option.value == this.value) {
this.domNode.innerHTML = option.label;
return true;
}
return false;
}, this);
},
postMixInProperties: function(){
this.inherited(arguments);
this.connect(this, "onChange", "_setLabel");
},
postCreate: function(){
this.inherited(arguments);
this._setLabel();
}
});
});
Then, in my view script:
require(["dojo/ready",
"app/InlineSelectBox",
"dijit/form/Select"
],
function(ready, InlineSelectBox, Select){
ready(function(){
// Add code to set the options array
var options = [];
// Add code to set the initial value
var initialValue = '';
var inlineSelect = new InlineSelectBox({
editor: Select,
editorParams: {options: options},
autoSave: true,
value: initialValue
}, "domNodeToAttachTo");
});
});
I was dealing with this situation a few months ago, and not finding a resolution i made my own algorithm.
I put a div with an event on Onclick that build programatically a Filtering Select on that div with the store i want to use.
function create(id,value){
var name = dojo.byId(id).innerHTML;
dojo.byId(id).parentNode.innerHTML = '<div id="select"></div>';
new dijit.form.FilteringSelect({
store: store,
autoComplete: true,
invalidMessage:"Invalid Selection",
style: "width: 80px;",
onBlur: function(){ },
onChange: function(){ },
required: true,
value: value,
disabled: false,
searchAttr: "name",
id: "status"+id,
name: "status"
},"select");
dijit.byId('status'+id).focus();
}
I used the onBlur event to destroy the widget and the onchange to save by xhr the new value.
The focus is below because the onBlur was not working properly.
note: the function is not complete.