FileUploadField 'stuck' after submitting form with ExtJS4/DWR - file-upload

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 :)

Related

Enquire.js: Don't get the purpose of "setup" handler

I don't quite get the idea behind enquire.js' "setup" handler.
Case:
I want to load content through ajax once when you're not in a small viewport (lt 600px).
Naturally I would do enquire.register('(min-width: 600px)', { setup: myFunction });.
Problem:
Now I tested this multiple times but the setup handler also gets fired when you're in a small screen, which totally eliminates the benefit of the setup handler imo, because you would want to only load the ajax content once you enter a viewport bigger than 600px, wouldn't you?
See example jsfiddle.
Conclusion:
So actually I wouldn't even need the setup handler because I simply could load the content outside the enquire register and would have the same effect. (Which of course isn't what I want...)
Can someone tell me if I just misunderstood the purpose of setup or is there something I'm missing?
Combine with the deferSetup flag to defer the setup callback until the first match. This example illustrates the feature:
enquire.register(someMediaQuery, {
setup : function() {
console.log("setup");
},
deferSetup : true,
match : function() {
console.log("match");
},
unmatch : function() {
console.log("unmatch");
}
});
You can see a working example here: http://wicky.nillia.ms/enquire.js/examples/defer-setup/

viewConfig for getRowClass broken in rc1/2?

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.

set jqGrid page before url is called

I am looking for a way to set the page of a jqGrid to x...
My use case is someone is using my grid...
They click on a patient to edit that patient (I am not using jqGrids modal edit screen... to many modal windows already)...
When the save what they did to that patient, I want to redirect the browser back to the screen where they clicked on that patient, and back to the SAME PAGE...
The thing to keep in mind.
I am using asp.net MVC4. I call the first page via an action method. The url variable of my grid is another action in the same controller. That action is what I send my page and row variables down to. I am sure that this can be done, However, I have no idea of how to achieve it. So far I have tried to set the page variable and rows variable in my document.ready before I call the jqGrid...
tbl.jqGrid({
loadBeforeSend: function () {
page: pageFromTemp;
rows: rowFromTemp
}
});
basically I have tried different ways to do it. The above is just one of them.
I have tried to reload the grid in the document.ready. But that doesn't make any sense. Why reload the grid when you haven't given it any of the parameters it needs...
I have tried to set the variable in the beforeRequest event. I have a function that I try and set it in...
beforeRequest: function () {
if ((rowFromTemp != "") && (pageFromTemp != "")) {
$(this).trigger('reloadGrid', [{ page: pageFromTemp, rowNum: rowFromTemp, url: '/Encounters/GetAjaxPagedGridData/' }]);
//$.extend($(this).setGridParam({ page: pageFromTemp })),
//$.extend($(this).setGridParam({ rowNum: rowFromTemp })),
//$.extend($(this).setGridParam({ url: '/Encounters/GetAjaxPagedGridData/' }))
//$.trigger('reloadGrid', [{ page: pageFromTemp, rowNum: rowFromTemp, url: '/Encounters/GetAjaxPagedGridData/'}]);
}
},
But that doesn't work either. I am obviously missing something. What am I doing wrong...
Got it to change to the right page using loadComplete and $("frTable").trigger({})
But now I am getting a flashing Loading screen which indicates to me that it is still loading the data...
If I set a breakpoint in my code, I can confirm that it is loading the data. I am not doing something right here.
Load the grid in document ready, have it's datatype set to local, have it's url unassigned, and have it hidden. When you want to have it load, trigger the load after setting the parameters and then show it to the user.

ExtJS How to modify the textfield parameter autocomplete="off"

Some modern (Safari, chrom, firefox) browser records informations and allows you to autocomplete some textfields when you come back.
I want to do it in ExtJS. I have a piece of answer here :
How to get Chrome to remember login on forms?
But in ExtJS, I can not access to the parameter autocomplete. It is always hard coded autocomplete="off". In the doc, I do not found how to modify it : http://docs.sencha.com/ext-js/4-1/#!/api/Ext.form.field.Text
Is someone has a simple answer to modify this parameter ?
You want to add an afterrender listener to the textfield, get a reference to the input element, and set its autocomplete attribute to "on". You probably also want to set its name (as that is how the browser remembers the value).
Example:
http://jsfiddle.net/4TSDu/19/
{
xtype:'textfield',
fieldLabel:'some field',
name:'somefield',
listeners:{
afterrender:function(cmp){
cmp.inputEl.set({
autocomplete:'on'
});
}
}
}
Note that to make LastPass work you might need to remove size attribute from textfields. For some weird reasons Sencha is setting size=1 which is weird (was that because of IE6? maybe even IE5.5?).
Anyway this makes LastPass work. I guess you might want to remove autocomplete attribute as well for other password managers. Tested with ExtJS 6.5.
{
xtype: 'textfield',
name: 'username',
fieldLabel: 'Username',
listeners:{
afterrender:function(cmp){
cmp.inputEl.dom.removeAttribute('size')
}
},
},

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.