View Full Version : Forms and custom ServerProxy (DNode instead of ExtDirect) - not working

15 Mar 2011, 5:41 PM
Hi there,

I'm porting an application over from ExtJS3 at the moment, and with this application we have heavy use of NodeJS + DNode for client/server communication, instead of Ajax/REST or Direct implementations.

I've implemented our DNodeProxy for ExtJS4, but so far cannot get it to work. It seems that with ExtJS4 forms, if I add an `api` member, and call submit - it assumes it's a 'directsubmit':

submit: function(options) {
return this.doAction(this.standardSubmit ? 'standardsubmit' : this.api ? 'directsubmit' : 'submit', options);
However this worked in ExtJS3 for us fine. From what I can tell with form, you cannot currently override what proxy the form uses, and will always try to default to Ext.direct with this.

Calling it just throws a 'uncaught exception: No URL specified'

The code for the proxy so far is [autogenerated from coffeescript, the bind function allows easier scope passing]:

(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
Ext.define('Ext.data.DNodeProxy', {
extend: 'Ext.data.ServerProxy',
alias: 'proxy.dnode',
requires: ['Ext.util.MixedCollection'],
DNodeFN: void 0,
constructor: function(config) {
Ext.apply(this, config);
return this.callParent(arguments);
doRequest: function(operation, callback, scope) {
var args, fn, params, request, writer;
writer = this.getWriter();
request = this.buildRequest(operation, callback, scope);
fn = this.api[request.action] || this.DNodeFN;
args = [];
params = request.params;
if (!fn) {
throw 'No DNode function specified for this proxy';
if (operation.allowWrite()) {
request = writer.write(request);
if (operation.action === 'read') {
} else {
Ext.apply(request, {
args: args,
directFn: fn
args.push(this.createRequestCallback(request, operation, callback, scope), this);
return fn.apply(window, args);
createRequestCallback: function(request, operation, callback, scope) {
return __bind(function(data, event) {
return this.processResponse(event.status, operation, request, data, callback, scope);
}, this);
buildUrl: function() {
return '';
An example form using this would be:

(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
Ext.define('Quartermaster.components.user.FormLogin', {
extend: 'Ext.form.FormPanel',
alias: 'Quartermaster.FormLogin',
initComponent: function() {
Ext.apply(this, {
frame: true,
defaultType: 'textfield',
defaults: {
anchor: '100%'
proxy: 'proxy.dnode',
api: {
submit: Quartermaster.remote.userLogin
dockedItems: [
dock: 'bottom',
xtype: 'toolbar',
ui: 'footer',
items: [
'->', {
text: 'Login',
iconCls: 'icon-door_in',
handler: __bind(function() {
return this.getForm().submit();
form = @getForm()
if form.isValid()
@el.mask 'Please wait...Logging In'
Quartermaster.remote.userLogin form.getValues(), (error, response) =>
if error
title: 'Login Error'
msg: error.message
buttons: Ext.Msg.OK
icon: Ext.Msg.ERROR
Quartermaster.session = response
@fireEvent 'login_success'
}, this)
items: [
fieldLabel: 'Client Name',
name: 'clientname',
allowBlank: false,
}, {
fieldLabel: 'Username',
name: 'username',
allowBlank: false,
}, {
fieldLabel: 'Password',
name: 'password',
allowBlank: false,
inputType: 'password',
return this.callParent(arguments);
As you can see, there is commented code for the code that does work by manually calling the RPC method attached to the application, and is what we are expecting the DNodeProxy stuff to do on the whole.

Any help on getting this implemented with ExtJS4 would be much appreciated.

16 Mar 2011, 7:57 AM
As an update, I've implemented the following DNodeProxy below. This works absolutly fine on stores/grid's, I can load and save stuff fine there, but on forms still has issues binding to it and executing either via api or DNodeFN:

Ext.define 'Ext.data.DNodeProxy',

extend: 'Ext.data.ServerProxy'

alias: 'proxy.dnode'

requires: ['Ext.util.MixedCollection']

DNodeFN: undefined

constructor: (config) ->
Ext.apply @, config
@callParent arguments

doRequest: (operation, callback, scope) ->
writer = @getWriter()
request = @buildRequest operation, callback, scope
console.log request
fn = @api[request.action] or @DNodeFN
args = []
params = request.params

if not fn
throw 'No DNode function specified for this proxy';

if operation.allowWrite()
request = writer.write request

if operation.action is 'read'
args.push params
args.push request.jsonData

# Add each className to the request
Ext.apply request,
args: args
DNodeFN: fn

args.push @createRequestCallback(request, operation, callback, scope), @
fn.apply window, args;

createRequestCallback: (request, operation, callback, scope) ->
return (error, response) =>
if error
@processResponse no, operation, request, error, callback, scope
@processResponse yes, operation, request, response, callback, scope
return (data, event) =>
@processResponse event.status, operation, request, data, callback, scope

# This is required to prevent an error in the parent
buildUrl: -> ''