PDA

View Full Version : Server-Validation with JSON Response



infarbe
24 Oct 2011, 9:23 AM
Hi,

how should the server return the validation data when validated through the server?



{"success":false,"message":"Fehler im Formular",
"error":{"reason":"Fehler im Formular","code":10},
"errors":[
{"field":"name","msg":"You have to supply a Username."}
]}


http://dev.sencha.com/deploy/ext-4.0.2a/examples/form/xml-form.html
The JSON Example is gone.

In my record.save() failure routine how should I mark the fields as invalid?
What is done automatically by ExtJs and what do I have to do myself?

skirtle
24 Oct 2011, 9:41 AM
The example you've referenced uses a form submit to save the fields. This provides an automatic mechanism for marking fields as invalid. For a JSON equivalent see here:

http://docs.sencha.com/ext-js/4-0/#!/api/Ext.form.action.Submit

If you use record.save() then I don't believe you'll get anything for free. You can provide handlers for success, failure or callback and set whatever invalidity markings are required.

infarbe
25 Oct 2011, 5:18 AM
Thank you very much!
I now tried both ways simple submit and record.save(). It seems that for our approach the record.save() is more suited.

We need the Exception Listeners inside the proxy to handle if the session was timed out or other things send from the server during any request. At a first look the form submit did not seem to offer a way.

Anyway I haven't figured out so far on how to access the error properties from my server response.


record.save( {
success: function() {
Ext.Msg.show( {
title: 'Profile Saved',
msg: 'The Profile was saved',
buttons: Ext.Msg.OK,
icon: Ext.Msg.INFO
} );
me.cancelWindow();
},
failure: function( records, operation ) {
if( !operation.hasException() ) {
Ext.Msg.error( {
title: 'Error',
msg: 'Error',
buttons: Ext.Msg.OK,
icon: Ext.Msg.ERROR
} );
}
me.getFormPanel().getEl().unmask();
console.log( operation );
console.log( records );
var form = me.getFormPanel().getForm();
form.getFields();
[...] Invalidate Fields
},
callback: function( records, operation ) {
me.getFormPanel().getEl().unmask();
console.log( operation );
console.log( records );
}
} );

JambaFun
26 Oct 2011, 4:46 AM
Hi infarbe,

Here is some controller code I use to incorporate server-side validation into my form using a more MVC-like structure than using form.submit:



Ext.define("MyApp.controller.Subscriptions", {
extend:"Ext.app.Controller",

models:["Subscription"],
views:["subscription.Form"],

refs: [{
ref:"subscriberForm",
selector:"subscriberform > form"
}],

init:function() {
var model = this.getSubscriptionModel(),
proxy = model.getProxy();

proxy.on("exception", function(proxy, response, operation) {
console.log("exception");
var json = Ext.decode(response.responseText);
if (json && json.errors) {
this.getSubscriberForm().getForm().markInvalid(json.errors);
}
}, this);

this.control({
"subscriberform > button":{
click:this.onSubmitForm,
scope:this
}
});
},

onSubmitForm:function() {
var form = this.getSubscriberForm(),
record = form.getRecord(),
values = form.getValues();

record.set(values);
record.save({
success:function(records, operation) {
console.log("success");
},
failure:function(records, operation) {
console.log("failure");
}
});
}
});

I found almost the exact same approach in this post: http://www.sencha.com/forum/showthread.php?137580-ExtJS-4-Sync-and-success-failure-processing&p=615838&viewfull=1#post615838
(http://www.sencha.com/forum/showthread.php?137580-ExtJS-4-Sync-and-success-failure-processing&p=615838&viewfull=1#post615838)

JambaFun
26 Oct 2011, 5:16 AM
Hi again,


Did some refactoring. Let me know what you think. (Sorry if my code is too verbose.)


Model

Ext.define("MyApp.model.Subscription", {
extend:"Ext.data.Model",
fields:["id","first_name","last_name","address","zip_code","city","service"],
proxy:{
type:"rest",
url:"/subscriptions",
listeners:{
exception:function(proxy, response, operation) {
var json = Ext.decode(response.responseText);
if (json && json.errors) {
operation.setException(json.errors);
}
}
}
}
});



Controller

Ext.define("MyApp.controller.Subscriptions", {
extend:"Ext.app.Controller",


models:["Subscription"],
views:["subscription.Form"],


refs: [{
ref:"subscriberForm",
selector:"subscriberform > form"
}],


init:function() {
this.control({
"subscriberform > button":{
click:this.onSubmitForm,
scope:this
}
});
},

onSubmitForm:function() {
var form = this.getSubscriberForm(),
record = form.getRecord(),
values = form.getValues();

record.set(values);
record.save({
success:function(records, operation) {
console.log("success");
},
failure:function(records, operation) {
console.log("failure");
form.getForm().markInvalid(operation.getError());
}
});
}
});

infarbe
27 Oct 2011, 6:41 AM
That is wonderful I now have faith in ExtJs 4 MVC again.



var defaultProxyException = function( proxy, response, operation ) {

if( response.aborted ) {
return;
}

var text = response.responseText;
var data = null;
if( text ) {
data = Ext.JSON.decode( text, false );
}

if( !data ) {
Ext.MessageBox.show( {
title: 'Unknown Error',
msg: operation.getError(),
icon: Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK,
closable: false
} );
return;
}

var error = operation.getError();
var errorTitle = data.error.title ? data.error.title : 'Error';
var errorCode = data.error.code ? data.error.code : -1;
var errorReason = data.error.reason ? data.error.reason : operation
.getError();
var destination = data.destination ? data.destination : null;
var message = data.message ? data.message : operation.getError();

switch (errorCode) {
default:
case 10:
// Validation
if( data && data.errors ) {
operation.setException( data.errors );
}
break;
case 500:
case 401:
case 403:
var global = Ext.create( 'Ext.window.MessageBox', {
renderTo: Ext.getBody(),
autoDestroy: true
} );

global.show( {
title: errorTitle,
msg: errorReason,
icon: Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK,
closable: false,
modal: true,
fn: function( buttonId ) {
if( destination !== null ) {
window.location = destination;
}
}
} );
global.toFront();
break;
}
};

TampaBay55
22 Feb 2012, 2:25 PM
JambaFun:

It appears that your approach fires off two PUTS (one for the set and one for the save). Is this what you are seeing?

TB55