Why success callback is not called in extjs form submission? - file-upload

I'm trying to upload a file using Ext JS forms and in case of success or failure, show appropriate messages. But I'm not able to get the desired result. I'm not able to make success or failure callbacks work in form.submit action.
What I've done till now is:
Creating a form with this script:
new Ext.FormPanel({
fileUpload: true,
frame: true,
url: '/profiler/certificate/update',
success: function() {
console.log(arguments);
},
failure: function() {
console.log(arguments);
}
}).getForm().submit()
​/*
The response Content-Type is text/html (with charcode=utf8);
The response JSON is: { "success": true }
*/​​
Setting the response Content-Type to text/html based on this answer.
Sending an appropriate JSON result back, based on Ext JS docs. The response captured via Fiddler is:
{"success":false}
or
{"success":true}
I even set the response Content-Type to application/json. But still no success.
I've read links like this and this, but none of them helped. Please note that I also tried another script which creates a form, with an upload field in it, and a save button, and I submitted the form in the handler of the save button. But still no callback is fired.

Here's a working example - Javascript code:
Ext.onReady(function () {
Ext.define('ImagePanel', {
extend: 'Ext.form.Panel',
fileUpload: true,
title: 'Upload Panel',
width: 300,
height: 100,
onUpload: function () {
this.getForm().submit({
url: 'upload.php',
scope: this,
success: function (formPanel, action) {
var data = Ext.decode(action.response.responseText);
alert("Success: " + data.msg);
},
failure: function (formPanel, action) {
var data = Ext.decode(action.response.responseText);
alert("Failure: " + data.msg);
}
});
},
initComponent: function () {
var config = {
items: [
{
xtype: 'fileuploadfield',
buttonText: 'Upload',
name: 'uploadedFile',
listeners: {
'change': {
scope: this,
fn: function (field, e) {
this.onUpload();
}
}
}
}
]
};
Ext.apply(this, Ext.apply(this.initialConfig, config));
this.callParent(arguments);
}
});
var panel = Ext.create('ImagePanel', {
renderTo: Ext.getBody()
});
});
And PHP code:
<?php
if (isset($_FILES)) {
$temp_file_name = $_FILES['uploadedFile']['tmp_name'];
$original_file_name = $_FILES['uploadedFile']['name'];
echo '{"success": true, "msg": "'.$original_file_name.'"}';
} else {
echo '{"success": false, "msg": "No Files"}';
}

I have been struggling with this for quite some time now as well. Here's my code:
Ext.getCmp('media-upload-form').getForm().doAction('submit', {
url: './services/recordmedia/upload',
method: 'post',
waitMsg: 'Please wait...',
params: {
entityId: this.entityId,
},
failure: function(form, action){
alert(_('Error uploading file'));
this.fireEvent('file-upload');
this.close();
},
success: function(form, action){
this.fireEvent('file-upload');
this.close();
},
scope: this
})
The response was always wrapped in <pre> tags by the browser, what caused the Extj lib not to call the callbacks. To fix this:
make sure your server returns the correct json: {"success":true}
make sure that the content-type is set to text/html

Actually, this is well covered by docs for Ext.form.Panel and Ext.form.Basic. The problem with your code not working is that there are no config options "success", "failure" for the form panel. You should put them in the config object passed to the submit action. So your code should look like:
new Ext.FormPanel({
fileUpload: true,
frame: true
}).getForm().submit({
url: '/profiler/certificate/update',
success: function() {
console.log(arguments);
},
failure: function() {
console.log(arguments);
}
});
Note the difference: In Ext 4, there is a form component (Ext.form.Panel) which is basically a view component concerned with how you form looks, and then there is the underlying form class (e.g. Ext.form.Basic) concerned with the functionality. Form submissions are handled by Ext.form.Basic (or whatever returned by your form.getForm()).

Related

Add a auto initialize function inside a Sencha Touch model to manipulate model's data

When I load a store, due to the API structure, I get a json object inside my model:
Ext.define('TestApp.model.SecretKeyModel', {
extend: 'Ext.data.Model',
config:{
identifier: {
type: 'uuid'
},
fields: [
{ name:'theRecord', type:'json' }
]
},
extractToken: function() {
var record = this;
var token = record.initSession.token;
console.log('token: ' + token);
}
});
I need to extract the token from that json object.
For that, i think I should write a function right there, inside the model.
How can I call it, when the store loads, to manipulate the data and extract the token?
I faced a similar situation 1 hour ago, i needed to edit data during loading or immidiatly after. I ended with this solution:
Ext.define('TestApp.store.MyStore', {
extend: 'Ext.data.Store',
requires: ['TestApp.model.SecretKeyModel'],
config :{
model: 'TestApp.model.SecretKeyModel',
proxy: {
type: 'ajax',
url: TestApp.utils.GlobalVariables.getServerUrl(),
reader: {
type: 'json',
rootProperty: ''
}
},
listeners: {
refresh: function(store, data, eOpts) {
store.each(function (item, index, length) {
item.extractToken(); // call this on every record loaded in the store
});
}
}
}
});

Blueimp fileupload() callbacks not called

I am using Blueimp fileupload() to post image files to a django-tastypie API.
The code below works correctly as far as the file is being uploaded:
$("#image").fileupload({
dataType: 'json',
start: function() {
console.log("start fileupload");
},
progress: function(e, data) {
console.log(data.loaded + " " + data.total);
},
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
},
done: function(e, data) {
console.log("done uploading file.");
}
});
$("#image").bind('fileuploadfinished', function (e, data) {
console.log("fileuploadfinished");
});
However, the done callback is never called. I tried binding the fileuploadfinished and that is also never called.
start and progress are both called as expected.
beforeSend is undocumented, but is needed by django-tastypie for SessionAuthentication - removing it doesn't change that done and fileuploadfinished is never called.
As it turns out, django-tastypie correctly returns a 201 status code. However, this status code is not considered a success by fileupload.
This code handles the status code manually:
$("#image").fileupload({
dataType: 'json',
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
},
complete: function(xhr) {
if (xhr.readyState == 4) {
if (xhr.status == 201) {
console.log("Created");
}
} else {
console.log("NoGood");
}
},
});
That means, the complete callback is called whether success or failure, and checking the readyState and status together can tell whether it succeeded.
There are some other ways to get this to work, however I think this is the best. More details here:
Data inserted successful but jquery still returning error
I was having the same problem. it is because you set your datatype 'json'.
Just leave this out or put it to plain and it will work.
Your server , or uploadhandler isn't return a json answer.

ExtJS4 direct form submit

Common form with Ext.direct submit n load, load is working properly, but submit is return error, coz in post data in undefined
var _form = Ext.create('Ext.form.Panel', {
api: {
submit: submit, //actions I took from code that going above, and never mind what I ll write here. Its not a problem
load: load
},
baseParams: {
st_id: st_id,
id: id
},
paramsAsHash: true,
defaultType: 'textfield',
buttons: [{
text: 'Cancel',
handler: function() {
this.up('form').getForm().reset();
}
}, {
text: 'Save',
handler: function() {
var values = this.up('form').getForm().getValues();
this.up('form').getForm().submit({
success: function() {
grid.getStore().load();
}
});
this.up('form').getForm().reset();
}
}]
});
in to headers wrote that content type is "application/json;" but in other cases its "application/x-www-form-urlencoded", last it make sense, right? and it work, but in other forms.
all of this is under Kohana, so when I look clearly what is going on in controllers, in Extdirect Router I see what for this form there is no info about submit method.
it was kind of stupid mistake: I forgot #formHandler in a definition

Update record in Sencha Touch Data Store with Ajaxproxy

I'm developing a simple form with Secha Touch. I have defined a DataStore for my model like this:
App.stores.shopinglists = new Ext.data.Store({
model: 'ShopingList',
autoLoad: false,
proxy: new Ext.data.AjaxProxy({
type: 'ajax',
url: 'http://localhost:2795/ShopingListService/',
reader: {
type: 'json',
root: 'ResultData',
totalProperty: 'Total',
successProperty: 'Success'
},
writer: {
encode: true,
type: 'json'
}
})
});
The view loads fine, and I can see a list of items and edit them. However, when I click the update button, I get the following error:
Uncaught Error: You are using a ServerProxy but have not supplied it with a url.
What I am missing here? The proxy has the url defined, but when update is invoked, it's undefined.
Edit: The button just call a controller action.
onSaveAction: function () {
var model = this.getRecord();
Ext.dispatch({
controller: 'ShopingLists',
action: (model.phantom ? 'save' : 'update'),
data: this.getValues(),
record: model,
form: this
});
},
The code executed by the controller is this:
update: function (params) {
debugger;
var tmpshopingList = new App.models.ShopingList(params.data);
var errors = tmpshopingList.validate();
if (errors.isValid()) {
params.record.set(params.data);
params.record.save();
this.index();
} else {
params.form.showErrors(errors);
}
},
I think I know what is happening: The model knows it has a server proxy, but all of the configurations are not being copied over. Perhaps this is a bug with Sencha Touch 1.x.
Try putting the proxy configuration into your model, not your store.

Read ExtJS message from ajax store

I have an ExtJS store with an ajax proxy and json reader:
Ext.create('Ext.data.Store', {
proxy: {
type: 'ajax',
url: '...',
reader: {
type: 'json',
root: 'data',
totalProperty: 'totalCount',
messageProperty: 'message',
successProperty: 'success'
},
...
This is what I get from the server:
data: [...]
message: "I want to read this string after the store is loaded"
success: true
totalCount: x
Now I want to access the 'message' when the store is loaded - where do I get it? I looked a lot but I can't find a place to hook in? The only listener in the proxy is exception, that doesn't really help me.
use store load event:
Ext.create('Ext.data.Store', {
listeners: {
'load': function(store, records, successful, operation) {
alert(operation.resultSet.message);
}
},
proxy: {
// ...
UPDATE
It appears that documentation for load event is wrong. The correct list of arguments is (store, records, successful) (no operation argument). Therefore the solution above wouldn't work.
However there is reader's rawData property which can help:
Ext.create('Ext.data.Store', {
listeners: {
'load': function(store, records, successful) {
alert(store.getProxy().getReader().rawData.message);
}
},
proxy: {
// ...
My answer applies to ExtJs 4.1.x. I spent some time reading the code and it seems that one way to do this is to provide a callback in the store beforeload event instead of handling the load event. The callback is passed the operation object which will contain the original request parameters and in case of success it will contain the response object and the data (parsed) under the resultSet property.
In other case:
myStore.load({
callback : function(object, response, success) {
// on error response: success = false
if(!success) {
// i don't remember de correct path to get "message" or "responseText"
console.log(response.response.responseText);
} else {
...
}
});
Cya!
I get the message in the following way although I load manually and do not use events here:
var initData = Ext.create('My.data.SomeAjaxStore');
initData.load(function(records, operation, success) {
if (!success || operation.hasException()) {
// Here is your message from server
// In case of HTTP error you get:
// {
// status: 404,
// statusText: "Not Found"
// }
var error = operation.getError();
Ext.log({msg:[Ext.getClassName(me), ": Command failure: ", error].join(""), level:"error"});
}