I am using ExtJS version 4.1.1.
I try to create upload file form using filefield as follow:
{
xtype: 'filefield',
itemId : 'my-file',
name: 'my file',
emptyText : 'No file chosen',
fieldLabel: 'Upload File',
submitValue: true,
allowBlank : false,
buttonText: 'Browse',
listeners: {
change: function(fld, value) {
var newValue = value.replace(/C:\\fakepath\\/g, '');
fld.setRawValue(newValue);
}
}
}
When the form is submitted, the filefield is reset.
As I see in
http://www.sencha.com/forum/showthread.php?135109-File-upload-field-is-empty-by-re-submitting-of-the-form
I try to override the filefield to :
Ext.override(Ext.form.field.File, {
extractFileInput: function() {
var me = this,
fileInput = me.fileInputEl.dom,
clone = fileInput.cloneNode(true);
fileInput.parentNode.replaceChild(clone, fileInput);
me.fileInputEl = Ext.get(clone);
me.fileInputEl.on({
scope: me,
change: me.onFileChange
});
return fileInput;
}
It look OK when I submit the form.
The value that I see in the textfield is not reset to empty.
However, when I submit the form again without re-choose file, the data that be sent to the server is null.
The data that be sent to the server should be retained.
Additional Info:
This problem occur when I use Chrome and IE, It seem work fine on Firefox.
Is it related with C:\\fakepath that I see on textfield when choose file?
How can I fix this problem?
set clearOnSubmit to false on your filefield
Related
I am doing form validations in Sencha Touch 2.3. My model looks like following.
Ext.define('net.omobio.dialog.dialogcc.model.StockTransferDetails', {
extend: 'Ext.data.Model',
config: {
fields: ['to_msisdn','to_profile_id','transfer_lob','transfer_item_status','transfer_product','transfer_qty','transfer_req_type','transfer_item_type','transfer_pack_type'],
validations: [
{ type: 'presence', field: 'to_msisdn' },
{ type: 'presence', field: 'to_profile_id' },
{ type: 'exclusion', field: 'transfer_lob', list: ['null'] },
{ type: 'exclusion', field: 'transfer_req_type', list: ['null'] },
{ type: 'exclusion', field: 'transfer_item_type', list: ['null'] },
{ type: 'exclusion', field: 'transfer_pack_type', list: ['null'] }
]
}
});
Following is a code segment that I use in my controller to remove validations from hidden form fields but no luck.
var form1 = me.getStockTransferRequestPage();
var model = Ext.create("net.omobio.dialog.dialogcc.model.StockTransferDetails", form1.getValues());
// validate form fields
var errors = model.validate();
if (!errors.isValid()) {
// loop through validation errors and generate a message to the user
errors.each(function (errorObj){
//errorString += errorObj.getField() + " " + errorObj.getMessage();
console.log('7777777777777777777 '+errorObj.getField());
if (!Ext.getCmp(errorObj.getField().toString()).isHidden()) {
var s = Ext.String.format('field[name={0}]',errorObj.getField());
form1.down(s).addCls('invalidField');
}
});
Ext.Msg.alert('','stock_transfer.errors.required_fields_empty');
}
I would be much appreciated if anyone could help me to solve this.
Thank you
so there are multiple ways to achieve this, my preference even though some folks won't like it, but it will always work.
I did the following override to solve this problem, tried my best not to affect the normal flow of validation.the first two overrides have to be added somewhere to your overrides folder, you only have to add them once for the whole app.
Ext.Define('Ext.form.field.BaseOverride', {
override: 'Ext.form.field,Base',
/* traverse up and look for a hidden Parent/Ancestor */
isParentHidden: function () {
return this.up('[hidden=true]');
}
/* override isValid basic method to consider skipValidateWhenHidden property, when skipValidateWhenHidden is set to true code should check if the elementor it's Parent/Ancestors is hidden */
isValid: function () {
var me = this,
disabled = me.disabled,
isHidden = me.isHidden(),
skipValidateWhenHidden = !!me.skipValidateWhenHidden,
validate = me.forceValidation || !disabled,
isValid = validate ? me.validateValue(me.processRawValue(me.getRawValue())) : disabled;
if (isValid || !skipValidateWhenHidden) {
return isValid;
}
if (skipValidateWhenHidden) {
isHidden = isHidden ? true : me.isParentHidden();
if (isHidden) {
return skipValidateWhenHidden;
}
}
return isValid;
}
});
and eventually you'll be able to do the following, which is set the property to true on any field so if its not visible for the user, it will survive validation
{
itemId: 'City',
cls: 'AddressCity',
xtype: 'textfield',
emptyText: emptyCityText,
skipValidateWhenHidden: true,
},
another approach is to add a show()/Hide() listener on the fields container to enable/disable the children, disabling the fields would make them skip validation, but i'm not a big fan of managing button states and wiring listeners.
Note
Ext.getCmp() takes component id
errorObj.getField().toString() returns model field name, It won't
return id of the component (hidden) field.
So if model field name matches with hidden field id, It will work. Otherwise it won't work.
I have an ExtJS Formpanel and I have written a listener on a click for the form ( not on any fields of a form ) which is working fine.
Even after setting the Ext.FocusManager.Enable() to true, I am not able to get the even 'blur' working. What am I missing?
I am not able to access form fields from the event handlers for formpanel click event. When I do - this.up.('form').get.(fielname).value [which works fine in the event handlers on the form fields.] It says the element is undefined. How can I access the form elements here?
Adding the code snippet -
// Call it Object A
Ext.create.('Ext.form.Panel', {
id : xyz,
items: [
{
xtype : 'textfield',
name : 'test',
fieldLabel : 'Name'
}
listeners : { // listener on the formPanel; not on any of its element
click : {
console.log("this works" );
},
focus : {
console.log('this does not work');
}
}
]
}
I am doing this so that I can access a value of another object, say B.field.
Onload I am able to fetch the value of B.field. But when the user changes the value of B.field which is on a different tab, I am not able to fetch the changed value of B.field in A. I am just finding ways to avoid an Ajax call to the database, if possible.
Thanks in advance for your time.
Without any sample from your code to reference, it's hard to determine what you are trying to do.
It could be that you just need to fix how you are querying for the form elements. For example, elements in a toolbar are not children of the form, so up/down doesn't work.
I don't think you can listen for the events focus, blur, or click on a form. Even if you could, I am not sure you would want to do. Instead, it's more common to listen for focus on a field or click on a button.
Example 1 form with field using focus and button using click
http://codepen.io/anon/pen/qEPRge?editors=001
;(function(Ext) {
Ext.onReady(function() {
console.log("Ext.onReady")
var form = new Ext.create("Ext.form.Panel", {
title: "person"
,items: [
{itemId: "fld-id", fieldLabel: "id", name: "id", value: "1", xtype: "textfield", labelAlign: "top", labelSeparator: ""}
,{itemId: "fld-name", fieldLabel: "name", name: "name", value: "Emily", xtype: "textfield", labelAlign: "top", labelSeparator: ""}
,{itemId: "btn-submit", text: "submit", xtype: "button"}
]
})
form.on("afterrender", function(component) {
console.log("form.afterrender")
})
form.render(Ext.getBody())
form.queryById("fld-id").on("focus", function(component) {
console.log("fld-id.focus")
})
form.queryById("fld-name").on("focus", function(component) {
console.log("fld-name.focus")
})
form.queryById("btn-submit").on("click", function(component) {
console.log("btn-submit.click")
console.log("fld-id.value:")
console.log(component.up("form").queryById("fld-id").getValue())
console.log("fld-name.value:")
console.log(component.up("form").queryById("fld-name").getValue())
})
})
})(Ext)
I have in my ExtJS 4.2.1 Application a grid with the following editable column:
text: 'Location',
dataIndex: 'LocationId',
width: 140,
renderer: function(value) {
var record = me.store.findRecord('LocationId', value);
return record.get('Description');
},
editor: {
xtype: 'combobox',
typeAhead: true,
triggerAction: 'all',
store: Ext.create('App.store.catalog.Location', {
autoLoad: true
}),
displayField: 'Description',
valueField: 'LocationId',
listConfig: {
width: 250,
loadingText: 'Searching...',
// Custom rendering template for each item
getInnerTpl: function() {
return '<b>{Code}</b><br/>(<span style="font-size:0.8em;">{Description}</span>)';
}
}
}
The combo has a renderer to display the Description of the LocationId selected.
Then, my grid has the feature 'Ext.grid.plugin.CellEditing' so I can edit just that column cell.
The problem that I have is when I press the "Update" button, the combo display value returns to the original it used to have, even if the LocationId in the record has the right value.
This is my code that gets fired when the user press the "Update" button.
me.rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 1,
autoCancel: false,
listeners: {
edit: function(editor, e) {
var record = e.record;
me.setLoading('Updating...');
App.util.Ajax.request({
noMask: true,
url: '/api/catalog/UpdateEmployeeLocation',
jsonData: record.getData(),
success: function(response, opts) {
var obj = Ext.decode(response.responseText);
if (obj.success) {
// commit changes (no save just clear the dirty icon)
me.getStore().commitChanges();
}
},
callback: function() {
me.setLoading(false);
}
});
}
}
});
The record is saved correctly in my database but the combo display value is not updated with the description that corresponds to the LocationId. If I reload the store from server again then It shows correctly.
So, there is something wrong with the renderer in my column that is not updating the value after I update my record.
Any clue on how to get around this?
Thanks.
You are setting dataIndex as 'LocationId' but no where you are changing the 'LocationId', you are just changing description and updating it in rendered method. Since there no change in 'LocationId', store doesn't consider it as dirty field and hence rendered function is not getting called. One quick and dirty way could be instead of using 'LocationId', create another field in the model say 'LocationIdchangeTraker'. Use 'LocationIdchangeTraker' instead of 'LocationId' in data index. It doesn't not effect your view because you are changing the value in reneerer function. Now whenever you update the function change the value of 'LocationIdchangeTraker' as shown below.
record.set('LocationIdchangeTraker',Ext.getId());
My problem is: I need to support select local image files and also preview server side images, I am using an plugin FileUploadField. It has a
button for select from local files, how to add another button near it ?
perhaps this is the same question :
How to find a buttons's parent component, and append another child (button)?
thanks a lot.
you can add your custom button after field is rendered like this
Ext.onReady(function(){
var fp = new Ext.ux.form.FileUploadField({
renderTo : Ext.getBody(),
emptyText: 'Select an image',
listeners : {
afterrender : function(fupload) {
this.customButton = new Ext.Button({
renderTo : Ext.getBody(),
cls: 'x-form-file-btn',
text : 'some button'
});
this.customButton.el.insertAfter(fupload.fileInput);
}
}
});
});
Example:
JSFiddle Link
I am using Ext.direct.RemotingProvider . At the server side I make some validation checks. The Respond is send back in JSON format.
If i find any errors when making validation checks, the field success = false, and errors will contain the error.
I am trying to figure out, how do i reflect errors i found in the server side in the form (client side).
In the link below there is an example of what i want to achieve. When the client press on "submit" an error message will occur in the form, how does it work ?
Example
In the code i post in the bottom the following happens:
in the browser there are 2 fields (Name,Email) and 2 buttons.
the fields are irrelevant for now. they are used as dummies.
Each time the user press on "Add" button, a new action is added into callBuffer of Ext.direct.RemotingProvider
When the user press on "Apply" button, all the actions are being sent to the router (MVC model) and from there to a specific controller. (the function sfw.Direct.getProvider('sfwProvider').combineAndSend() is triggered).
As for now, i intentionally fails the respond and create an error field, just like the example link i added in the beginning of the Thread.
i put in the errors field {email="Already exists"}.
but i see not effect in the form..
what am i doing wrong ?
Code:
appWiki.main_panel = new Ext.FormPanel({
renderTo: 'extjs_panels_container'
, id: 'appWiki_main_panel'
, name: 'appWiki_main_panel'
, defaultType: 'textfield'
, items: [
{
fieldLabel: 'Name',
name: 'name'
}
,{
fieldLabel: 'Email',
msgTarget: 'side',
name: 'email'
}]
,buttons:[
{xtype: 'sfw.Button'
, text: 'Add'
, handler: function(){sfw.rule.store.api.readByRowId({data: {_ROWID_: 1}});}
}
,{text: 'Submit'
, handler: function(){
appWiki.main_panel.getForm().submit({
});
}
}]
,api: {
// The server-side must mark the submit handler as a 'formHandler'
submit: sumbitAllRequests
}
, load: function()
{
setTimeout("hide_loading_mask()",2000);
}
});
In the JSON response you need the following structure
{ "result" : { "success": false, "errors": { "name of field" : "validation message" } }
Where "name of field" is the name config option in your field, and "validation message" is the message you want to display to the user.
When you send a response like that ExtJS will take care of the rest.
EDIT: You may also need to enable QuickTips:
Ext.QuickTips.init();
Add that line before you declare your form
EDIT 2: Also, make sure you're using the submit() method found on the BasicForm:
buttons:[{
text: 'Submit',
handler: function(){
basicInfo.getForm().submit({
params: {
foo: 'bar',
uid: 34
}
});
}
}],