PDA

View Full Version : Form <-> Model binding



htammen
27 Feb 2011, 1:50 AM
In the comments of the blog about the new data package Ed Spencer mentioned that it is or will be possible to bind form data to a model (s. below).
I canīt find more details in the API docs. Is this feature already available?


2) Indeed - I prefer to do everything through the Model and just use the form for dumb data collection
3) Yes - if you configure a form with a Model it will ask the Model to validate itself, showing any errors on the appropriate field. This makes it easy to create very powerful validations

mitchellsimoens
27 Feb 2011, 7:40 AM
Have you tried using the loadRecord method on the form? Sencha Touch and ExtJS 3 has this.

htammen
27 Feb 2011, 9:07 AM
A model is more complex than a record. As far as I know a record is just a flat collection of fields. A model can furthermore contain associations. So a model can be a huge object tree.
BTW the Ext.data.Record class seem to have gone in Ext 4.

I know the model binding from Flex (BlazeDS). There you can exchange objects between frontend and backend and vice versa. Additionally there are tools that generate the frontend models from the backend models. So they are in sync at every time of development state. This makes life really easy.
Would be great to have something like that in ExtJS.

mitchellsimoens
27 Feb 2011, 9:14 AM
According to the API docs for ExtJS 4... do this:


formpanel.getForm().loadRecord(rec);

Model and Record mean the same in ExtJS4/ST.

htammen
27 Feb 2011, 10:07 AM
Iīve just had a look at the ExtJS 4 source code and I canīt imaging that this will work. The loadRecord method calls setValues and this method just tries to set the values of the form fields. So far it may work for fields and array. But I donīt see a way to have 1:1 relationships between two objects yet. On the other side I don't think that the reverse method udpateRecord does it's work in deep hierarchy.
Despite of my doubts I will give it a try.

mitchellsimoens
28 Feb 2011, 6:16 AM
How is it making out for you?

htammen
28 Feb 2011, 11:05 AM
The first attempt wasnīt successful. Will hopefully have more time to spend on this tomorrow.

icflorescu
3 Mar 2011, 9:23 AM
Have you got more time to play around with it?
If you're thinking what I'm thinking, i.e. something like binding complex related models to forms with dynamically generated field blocks, you'll probably have to implement your own logic anyway. As you said a model can be far more complex than a record and there's no way for the framework to know what exactly you want to do with it.

One might think it could be done automatically with some sort of 'binding paths' mechanism (i.e. bind field X to user.comment.name) but a generic framework-level implementation would only work for one-to-one associations.

wizkid
9 Mar 2011, 8:25 PM
I am really struggling with this tonight. I finally got my model working client-to server round tripping like a dream. So, naturally the next logical step was to put a UI on it. After all that's part of the big draw for ExtJS.

So what was suggested previously I did try:

simple.getForm().loadRecord(singleUserFormObj);

This is from my model. It looked like one way binding to me. I got the values in there. But then if I changed the value in my form they did not update my model object! Looks like a simple "reflection" type deal where it just setValue on the form.

So, now I guess I have a philosophical question before my technical question.

Did the new Model, with validation rules, ever have the intention to have the model and the form interact? I just don't see them in the API. Maybe I missed it. I have this awesome model object which I totally love. It has validation rules that are sweet. But what is the point of it all if I can't use it in a visual context? I see no reason to have a model that can't have a UI on top of it.

So with that in mind.

How do I connect up any ExtJS UI controls with my model and have automatic red halos around fields that violate client side validation rules on the model? If this is not possible please explain why I would want to use a model in ExtJS with validation rules?

I can see an argument related to having a model do the heavy chaotic lifting of getting and setting data server to client. Although it appears a form can do that for me as well. So I am getting a little confused what the Model is intended for in the context of this UI framework...

What I expected is a config option for the form that took a model or a store. Once that data is loaded I fully thought it would two-way bind and then typing in text that would violate a model rule would automatically show up in the UI!

Was this wishful thinking? :(

I am not being critical. Just inquisitive as I am just thinking I missed something in the examples or the documentation. I also understand this is pre-release....

htammen
10 Mar 2011, 12:19 AM
To fill the model from the form there is the method Ext.form.Basic.updateRecord. This, as far as I remember, works for simple bindings (form field name == model property name) only.

It does not work for complex data 1:1 and 1:n associations.

I came to the same questions as you and I also thought that Iīve overseen something. As you mentioned I also donīt see a reason to implement a frontend model if it cannot be bound to the UI.

In the meantime it seems to me that this is still a field of basic development in which Sencha has to invest more effort.
As already mentioned Adobe solved this problem (http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_2.html) and combined with BlazeDS you can work seamless between backend and frontend.

wizkid
10 Mar 2011, 6:15 AM
updateRecord will work for me for the values. It's not automatic. But I suppose I could live with that aspect.

Anybody know at this point in time what the validation rules on the model are good for? I looked at
loadRecord for Forms and I don't see it doing anything with the validation rules. I am starting
to get a little disappointed. I had this whole architectural idea of using reflection
on my server's CSLA business object layer to dynamically create a ExtJS model protoype with validation rules.
It was going to be real cool. But I don't see any of the UI using the validation on the model.

I am hoping a Sencha developer can correct me and show me where I am going wrong.

Thoughts?

mitchellsimoens
10 Mar 2011, 6:24 AM
There is no automatic, bidirectional updating from Model < - > Form. You need to use loadRecord to load a record (model instance) into the form and then when you save the form, you will need to update the record that you loaded via basicForm.updateRecord(rec)


/**
* Persists the values in this form into the passed {@link Ext.data.Model} object in a beginEdit/endEdit block.
* @param {Ext.data.Record} record The record to edit
* @return {Ext.form.Basic} this
*/
updateRecord: function(record) {
//record.beginEdit();
var fields = record.fields,
values = this.getValues(),
name,
obj = {};
fields.each(function(f) {
name = f.name;
if (name in values) {
obj[name] = values[name];
}
});
record.set(obj);
//record.endEdit();
return this;
},

As for validations, that is for if you try to update/create a record. If it passes the validation, it will return no errors. If there are errors, it will return an Ext.data.Errors object. Love this approach. More robust than just using vtypes and allowBlank.


So on saving you can do this:


var basicForm = this.getForm(),
rec = this.rec;

basicForm.updateRecord(rec);
var success = rec.validate().isValid();
if (success) {
//handle success
} else {
//handle failure
}

wizkid
10 Mar 2011, 6:31 AM
Ok that sounds good, but how do I use this "errors object" that returns from the model to show up in the UI?

To me that would be very important in using the validation logic on the model (because this is all pretty much just client side type of validation anyway).

wizkid
10 Mar 2011, 6:35 AM
Ahh I think I found it on basic form... markInvalid(..)

Ok, I am starting to feel better again :)

Would be nicer if it was all automatic like .NET... But I can live with this.

mitchellsimoens
10 Mar 2011, 6:37 AM
Yes, you should not 100% rely on JS code but for 99% of users aren't hackers. Weird things happen so even though only 1% of users may have bad intent, something funky can go wrong for the 99% of people.

Anyway, the API docs for Ext.data.Errors has a pretty good example:


var errors = myModel.validate();

errors.isValid(); //false

errors.length; //2
errors.getByField('name'); // [{field: 'name', error: 'must be present'}]
errors.getByField('title'); // [{field: 'title', error: 'is too short'}]

All the Ext.data.Errors is is an instance of MixedCollection. Notice that when you getByField("..."), it returns an array. This tripped me up.

mitchellsimoens
10 Mar 2011, 6:38 AM
Ahh I think I found it on basic form... markInvalid(..)

Whoa, I missed that. I was doing it manually myself. Nice catch!

wizkid
10 Mar 2011, 6:41 AM
I agree when I code I assume anything coming into my server is hostile and should not be trusted. The client side validation is just a "nicety" for the UI. All it takes is some kid to use a JS debugger and you are in trouble unless you protected the server.

mitchellsimoens
10 Mar 2011, 6:44 AM
The client side validation is just a "nicety" for the UI.

Yes and another huge benefit is that it cuts down on server stress also. Imagine you are the size of Facebook and if you didn't have client side validations, your calls to the server would quadruple when it doesn't need to.

wizkid
10 Mar 2011, 6:48 AM
Lol, I wish I had that problem! I do code however for that day :D

wizkid
10 Mar 2011, 7:13 AM
I want each field to validate itself on focus out. No point in getting people all the way down to the save button just to tell them a client side rule failed. I suppose I could hook validating the model on every focus out event?

mitchellsimoens
10 Mar 2011, 7:16 AM
When you create the form, create a blank model instance. Then listen to the field's blur event and set that value to the field in the model instance. Then validate and getByField to see if it's valid.

Not sure if that will work but it should :D

estesbubba
10 Mar 2011, 9:23 AM
You guys doing a Form.markInvalid and getting it to display errors on the form? Mine is not. Debugging shows there are errors but no red squigglies...


this.deviceCoverage.getForm().updateRecord(this.deviceCoverageRecord);
var errors = this.deviceCoverageRecord.validate();
if (!errors.isValid()) {
this.deviceCoverage.getForm().markInvalid(errors);
return;
}

mitchellsimoens
10 Mar 2011, 9:26 AM
I haven't tried it but your code could be cleaned up a bit, don't take this the wrong way...



var me = this,
form = me.deviceCoverage,
basic = form.getForm(),
rec = me.deviceCoverageRecord;

basic.updateRecord(rec);
var errors = rec.validate();
if (!errors.isValid()) {
basic.markInvalid(errors);
return;
}

estesbubba
10 Mar 2011, 9:40 AM
I noticed that Ext JS 4 uses var me = this; What is the reason behind doing this?

mitchellsimoens
10 Mar 2011, 9:44 AM
Cuts down 2 characters per reference after the length of the line that creates the 'me' variable
Minifies better


Sure there are other reasons. I have talked to Jay Garcia and Ed Spencer about it one day and this is what we decided. It's agreed that we don't like it. Only reason I don't is because the IDE (BBEdit) I use highlights 'this' as blue. May be able to do it with 'me' but I'm too lazy.

You don't always need to do


var me = this;

On listeners, you can do it.


listeners: {
afterrender: function(grid) {
var me = grid;
}
}

estesbubba
10 Mar 2011, 10:15 AM
So debugging the code shows markInvalid wants 'id' and 'msg' but errors.items contains 'field' and 'message'. It appears to be the same data just with different field names. So is the best solution to iterate over errors.items and build a new object with the desired names? Easy to do but will get repetitive for all form validation. I would think that if a form uses a model, it should be able to understand the model's errors.

Maybe I'm missing something?

estesbubba
10 Mar 2011, 3:14 PM
I know this got a little off-topic but back to the "me" code style. Is what I did below:

var nextButton = me.nextButton = <object> taking it too far for object creation?



index: function(options) {

var me = this,
app = me.application;

if (!options.back) {
me.deviceCoverage = Ext.create('Prepaid.views.DeviceCoverage', {});
me.deviceCoverageRecord = Ext.ModelMgr.create({}, 'DeviceCoverage');
me.deviceCoverage.getForm().loadRecord(me.deviceCoverageRecord);

me.wizard = Ext.create('CsgPrepaid.views.Wizard', {
items: me.deviceCoverage
});

app.viewport.add(me.wizard);

var nextButton = me.nextButton = me.wizard.wizardButtons.nextButton;
me.backButton = me.wizard.wizardButtons.backButton;

nextButton.setDisabled(true);

nextButton.on('click', me.nextHandler, me);
me.backButton.on('click', me.backHandler, me);

me.deviceCoverage.viewCoverageButton.on('click', me.viewCoverageHandler, me);
}

me.backButton.setDisabled(true);
nextButton.setText('[View Products]');

},

wizkid
10 Mar 2011, 5:11 PM
You guys doing a Form.markInvalid and getting it to display errors on the form? Mine is not. Debugging shows there are errors but no red squigglies...


this.deviceCoverage.getForm().updateRecord(this.deviceCoverageRecord);
var errors = this.deviceCoverageRecord.validate();
if (!errors.isValid()) {
this.deviceCoverage.getForm().markInvalid(errors);
return;
}


There is definitely a bug going on here... See my post / fix here:http://www.sencha.com/forum/showthread.php?126503-Bug-with-Ext.form.Basic.markInvalid%28...%29-taking-an-error-object

skullbooks
6 May 2011, 2:06 AM
hey,

we have the same problem and want the form to validate by a given model and it's validations.

now i wrote my own ux.form.ModelValidatedPanel and ux.form.ModelValidatedBasic class that do this for me.

see here: http://www.diloc.de/blog/2011/05/05/extjs4-form-validation-via-model-binding/

the main aim of the form is to hold a model-record what can validate by the model validations and give the error back to the form. and all this by behaving hopefully nearly the same like a normal Ext.form.Panel (validitychange etc.)

haven't tested it in our whole application context but my simple form example tests worked really fine.

wizkid
6 May 2011, 5:49 AM
I did something similar but I like yours allot better! I will have to give it a try! Thanks!

ykey
6 May 2011, 6:03 AM
I have been experimenting with this as well. I thought I'd show what I ended up with. I only ran this through the most basic test cases.

I added a new config option to form fields called 'bindToModel'. If you load a model using loadRecord() the formpanel then looks to the model and adds any validations it finds there if the 'bindToModel' property is set on the field.

Ext.form.field.Base override


Ext.override(Ext.form.field.Base, {
bindToModel : false,

getErrors: function() {
var errors = this.callOverridden(arguments),
record = this.up('form').getRecord(),
modelValidations,
fieldValidations;

if (!this.bindToModel || !record) return errors;

modelValidations = record.validate();
if (modelValidations.isValid()) {
return errors;
}

fieldValidations = modelValidations.getByField(this.name);
fieldValidationsLength = fieldValidations.length;

if (fieldValidationsLength > 0) {
for (var j = 0; j < fieldValidationsLength; j++) {
errors.push(fieldValidations[j].message);
}
}

return errors;
},

onChange: function() {
var form = this.up('form').getForm(),
record = form.getRecord();

if (this.bindToModel && record) {
form.updateRecord(record);
}

this.callOverridden(arguments);
}
});

Ext.define('Workgroup', {
extend: 'Ext.data.Model',
fields: [
'name',
{name: 'startDate', type: 'date'},
{name: 'endDate', type: 'date'}
],
validations: [
{type: 'presence', name: 'name', message: 'Name is required.'},
{type: 'length', name: 'name', min: 3, message: 'Names must be at least 3 characters in length.'},
{type: 'presence', name: 'startDate', message: 'Start Date is required.'}
]
});

var formPanel = Ext.create('Ext.form.Panel', {
frame: true,
title: 'Work Group',
width: 340,
bodyPadding: 5,
renderTo: Ext.getBody(),
fieldDefaults: {
anchor: '100%',
bindToModel: true
},

items: [
{
xtype: 'textfield',
name: 'name',
fieldLabel: 'Name'
},
{
xtype: 'datefield',
name: 'startDate',
fieldLabel: 'Start Date'
}
],

buttons: [
{
text: 'Check',
handler: function() {
console.log('Record data: ', workgroup.data);
console.log('Form record data: ', formPanel.getRecord().data);
console.log('Valid: ', formPanel.getForm().isValid());
}
}
]
});

var workgroup = Ext.create('Workgroup', {
name: 'R12345'
});

formPanel.loadRecord(workgroup);

stuchy
2 Aug 2011, 2:44 PM
this works great. But when you start uploading files, it wont :(

shighfill
3 Aug 2011, 6:27 AM
I have a form that utilizes a HasMany association and find that the form initializes propperly when I alter loadRecord (http://docs.sencha.com/ext-js/4-0/#/api/Ext.form.Basic-method-loadRecord)to use record.raw rather than record.data because record.data does not include any association elements. This seems to have changed between ExtJs4.0 and ExtJs4.0.2a. If anyone could provide advice on this I would greatly appreciate it. Additionally, if there is a reason for the change that might help my understanding, please share. Thanks.

fishbone
10 Aug 2011, 2:53 AM
I just came up with this idea for handling forms and server-side validation:
It would be great, if there was a form-event which is called if updateRecord fails, because the server returned an error. Then I would be able to display the form again, load the record and display form-errors returned by the server. The event I'm suggesting passes form, record and server-response to the handler.

Can this be implemented? I don't have any ideas how to do this.

Here's why I need this feature and why I think it would be great:
server-side validation is always available, since it's required, whereas client-side validation will always be optional. Therefore, it would be nice if my programs "fall back" to sever-side validation automatically as soon as client-side validation isn't available.

Thanks in advance,
fishbone

skullbooks
10 Aug 2011, 5:39 AM
well at least this is on your backend.
i case of not validation on the backend you have to return a right error, something like

{"result":{"success":false,"errors":{"password":"Password wrong"},"data":null}
and on frontend side you have to handel not just success events, you should also check if you gote an error and if so do something like

this.getForm().markInvalid(_result.errors);

it's always good to work with both front and backend validation. frontend is faster for the user and can prevent annoying roundtrips for the user (send - error - send) he can see when he enters wrong values at realtime.
anyway the backend should validate anyhow, so that nobody can submit wrong data to your backend by hacking a bit js in the console.

robert.peszek
15 Aug 2011, 1:28 PM
I am working on a project using Ext 4 MVC.

I think it would be great if presentation of validation errors (from the server or from the model) were handled automatically by Ext.form.Basic/Panel and Ext.data.Model.
If not, maybe this would be a room for ux… to define something like ModelPlus and FormPanelPlus?
This would shorten the amount of project specific modifications/extensions that everybody working with MVC and Ext 4 probably has to do. I ended up overriding formPanel.loadRecord() and model.save() to accomplish this.

Some other comments:
I learned it the hard way that I need to set the trackResetOnLoad=true on the form.Basic. Otherwise things like isDirty() flag do not work properly.

Almost all form.Basic methods relevant to validation on (hasInvalidField() is one example) do not work with model validation.
I needed to query form directly to verify which fields are valid and which are not in my jasmine tests. I ended up using field.activeError property which seems not to care where the error came from. I do not know what it the best way to ask the form: are you presenting any errors to the user?

My so far experience with Ext 4 is very positive. Sure, there were (and are) rocky moments, but most of the time it was me who done something wrong.

Best,
Robert

Jeremy Solarz
24 Aug 2011, 9:05 AM
Hi shighfill (http://www.sencha.com/forum/member.php?285442-shighfill),

can you show an example how you defined your form (and eventual sub-forms) to load data from a model
that has "hasMany" associations?

I'm facing the exact problem right now and want to keep the data in the model, change the model via UI (e.g. a form) and POST it back to the server.

Any help much appreciated

OliverColeman
14 Jan 2012, 2:56 PM
The code from ykey works (thanks ykey!) great, except I found that if more than one form field was bound to the Model, and form.Basic.loadRecord was called on the form to set the initial form field values from those in the Model, then all except one form field (and the corresponding Model field) are cleared. This happens because the overridden onChange function in form.field.Base sets all the Model fields, via form.Basic.updateRecord, to the current values of the form fields whenever a form field is changed. When form.Basic.loadRecord is called and the first form field is updated and fires its onChange event, the overriden onChange function then sets the bound Model field values to the empty values of all the other form fields.

The following modified onChange function addresses this by only updating the individual Model field that is bound to the changed form field:



onChange: function() {
var me = this,
form = me.up('form').getForm(),
record = form.getRecord();

if (me.bindToModel && record && (me.name in record.data)) {
record.beginEdit();
record.set(me.name, me.getValue());
record.endEdit();
}

this.callOverridden(arguments);
}

ruslan.talpa
2 Feb 2012, 7:58 AM
The examples above, in order to validate based on model rules, had to update the model.
if that model is from a store and to that store you also have other bound views (or grids) then whenever you make a modification in the form, that change is instantly reflected in other components that "display" this particular model.
I modified the code so that you can call .updateRecord only when you need to (for example a save button) but still have the validation work based on the model.
In addition, i monitor the the bound model so whenever it changes i call again loadRecord to reset the field values.

Whant do you think?


<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Form <-> Model bind</title>
<link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-4.0.2a/resources/css/ext-all.css"/>
<script type="text/javascript" src="http://extjs.cachefly.net/ext-4.0.2a/ext-all-debug.js"></script>
<script>

Ext.override(Ext.form.Basic, {
loadRecord: function(record) {
var me = this;
me._validationRecord = record.copy();
me.callOverridden(arguments);
me.mon( record, 'changed', me.onRecordChanged, me );
},
onRecordChanged: function(){
this.loadRecord( this.getRecord() );
}
});
Ext.override(Ext.form.field.Base, {
getErrors: function() {
var me = this,
errors = me.callOverridden(arguments),
record = me.up('form').getForm()._validationRecord,
modelValidations,
fieldValidations;

if (!me.bindToModel || !record) return errors;

modelValidations = record.validate();
if (modelValidations.isValid()) {
return errors;
}

fieldValidations = modelValidations.getByField(me.name);
fieldValidationsLength = fieldValidations.length;

if (fieldValidationsLength > 0) {
for (var j = 0; j < fieldValidationsLength; j++) {
errors.push(fieldValidations[j].message);
}
}

return errors;
},

onChange: function() {
var me = this,
form = me.up('form').getForm(),
record = form._validationRecord;


if (me.bindToModel && record && (me.name in record.data)) {
record.beginEdit();
record.set(me.name, me.getValue());
record.endEdit();
}


this.callOverridden(arguments);
}

});

Ext.define('Workgroup', {
extend: 'Ext.data.Model',
fields: [
'name',
{name: 'startDate', type: 'date'},
{name: 'endDate', type: 'date'}
],
validations: [
{type: 'presence', name: 'name', message: 'Name is required.'},
{type: 'length', name: 'name', min: 3, message: 'Names must be at least 3 characters in length.'},
{type: 'presence', name: 'startDate', message: 'Start Date is required.'}
],
afterEdit: function() {

var me = this;
if(me.dirty){
me.fireEvent('changed', me);
}
this.callParent(arguments);
}
});


Ext.onReady(function() {
var formPanel = Ext.create('Ext.form.Panel', {
frame: true,
title: 'Work Group',
width: 340,
bodyPadding: 5,
renderTo: Ext.getBody(),

fieldDefaults: {
anchor: '100%',
bindToModel: true
},



items: [
{
xtype: 'textfield',
name: 'name',
fieldLabel: 'Name'
},
{
xtype: 'datefield',
name: 'startDate',
fieldLabel: 'Start Date'
}
],

buttons: [
{
text: 'Check',
handler: function() {
console.log('Record data: ', workgroup.data);
console.log('Form record data: ', formPanel.getRecord().data);
console.log('Form validation record data: ', formPanel.getForm()._validationRecord.data);
console.log('Valid: ', formPanel.getForm().isValid());
}
}
]
});


var workgroup = Ext.create('Workgroup', {
name: 'R12345'
});


formPanel.loadRecord(workgroup);
workgroup.set('name', 'New Name');
});


</script>
</head>
<body></body>
</html>

OliverColeman
2 Feb 2012, 2:20 PM
I actually quite like that changes in the form are echoed in other views (a tree panel in my case)!

JaiveekShah
31 Mar 2012, 5:02 AM
m using Ext 4.1 and stuck in form submitting using model api: create

can anyone show a small example how to get the data out of form and after passing it to a model, save it in database(Mysql)

quixit
12 Apr 2012, 7:14 AM
Another Solution see in:
http://www.sencha.com/forum/showthread.php?135732-Ext-4-Validating-a-Form-with-a-Model&p=778233#post778233

similian
20 Jul 2012, 9:22 AM
Hey Mitch,

this is a really great thread about bidirectional model binding.
The central question htammen asked was about:

How to bind complex objects (like the model) to a form.
The load record function is not sufficient


It does not work for complex data 1:1 and 1:n associations.

Well if there is a solution I would really look forward to see it solved.

So bringing back the Thread on track;

My question here is:

How can I load my complex data to the from? In a simple manner?

If I have a form containing fields like this:

username
address.zip
address.phone.mobile

How would i load it from my store (beloning to a model having the same structure) into the form ?

Kind Regards
Sim

mpost
27 Jan 2013, 8:56 AM
Sorry for the necro, but I felt it was important to point out that we still don't have automatic bidirectional model binding. This is one of the things I miss from Silverlight and XAML programming: it was very easy to bind a UI (any control really -- not just a form) to a model and have it all just work automatically. Put another way: this code is something that your customers write all the time so it's an ideal job that the framework could handle. KnockoutJS does this very nicely as well.

Charles Fator
29 Jan 2013, 3:02 PM
Agreed mpost. I'm astounded that proper form to model binding is not provided. Bidirectional form to model binding seems like it would be at the top of expectations for such a framework. :-? I'm actually a bit disappointed.

skullbooks
30 Jan 2013, 1:19 AM
well we don't use sencha command and the mvc (because in the time we started our application that didn't exist), so we had to build our own application structure with front- and backend and database connection.
for backend communication we use propel and generate php model classes for easy use.
and by porting our software to ext js 4... we came to the point that we enhanced our database schema xml with some more flag like (generate frontend model, generate frontend model relations, user visible names for columns,...) and we wrote a php script that generates us the ext js models.

the clou: we generate a UserBase and a User model the user model extends the UserBase, the base class will be overwritten every time we generate models, and on the script where we generate the models we don't just generate a fields list we also generate a getFormItems method on our models that returns a config object for a form to this model (depending on our schema enhancements)

with such generated models you can generate your own methods for things you have to do often (like writing a form config, grid column definitions maybe if you want, ...)

maybe this gives you an idea for your application to generate code you often need.

mpost
30 Jan 2013, 8:15 AM
maybe this gives you an idea for your application to generate code you often need.

But that's just my point: the whole point of using a framework like ExtJS is for exactly this sort of functionality. If I wanted to roll my own, I'd use jquery instead of giving money to Sencha.

skullbooks
30 Jan 2013, 10:27 AM
well yes and no...
1. i don't know exactly what is possible with sencha complete etc...
2. well extjs is just a frontend and not a backend with database access... so you have to write/generate your models u use as you need them... js can't make models by it self depending on a database ;)
3. if you compare extjs with jquery you should better compare it with jqueryUI but even then ext brings you a lot more standards and components for doing a web-app
but hey, both are js libs - sure u can also use jquery(UI) but in my opinion extjs code looks more clean and readable and the framework brings you a lot more help by building an nativ-app like web-app.

well sure i would be nice to have more things here and there, but i think for big applications it's a lot better then jquery.

if you just need it to build a simple online adress book that also should not look like a desktop app, then maybe jquery is the better option.

it all depends on the requirements for me.

xava
26 May 2013, 4:57 PM
The examples above, in order to validate based on model rules, had to update the model.
if that model is from a store and to that store you also have other bound views (or grids) then whenever you make a modification in the form, that change is instantly reflected in other components that "display" this particular model.
I modified the code so that you can call .updateRecord only when you need to (for example a save button) but still have the validation work based on the model.
In addition, i monitor the the bound model so whenever it changes i call again loadRecord to reset the field values.

Whant do you think?


<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Form <-> Model bind</title>
<link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-4.0.2a/resources/css/ext-all.css"/>
<script type="text/javascript" src="http://extjs.cachefly.net/ext-4.0.2a/ext-all-debug.js"></script>
<script>

Ext.override(Ext.form.Basic, {
loadRecord: function(record) {
var me = this;
me._validationRecord = record.copy();
me.callOverridden(arguments);
me.mon( record, 'changed', me.onRecordChanged, me );
},
onRecordChanged: function(){
this.loadRecord( this.getRecord() );
}
});
Ext.override(Ext.form.field.Base, {
getErrors: function() {
var me = this,
errors = me.callOverridden(arguments),
record = me.up('form').getForm()._validationRecord,
modelValidations,
fieldValidations;

if (!me.bindToModel || !record) return errors;

modelValidations = record.validate();
if (modelValidations.isValid()) {
return errors;
}

fieldValidations = modelValidations.getByField(me.name);
fieldValidationsLength = fieldValidations.length;

if (fieldValidationsLength > 0) {
for (var j = 0; j < fieldValidationsLength; j++) {
errors.push(fieldValidations[j].message);
}
}

return errors;
},

onChange: function() {
var me = this,
form = me.up('form').getForm(),
record = form._validationRecord;


if (me.bindToModel && record && (me.name in record.data)) {
record.beginEdit();
record.set(me.name, me.getValue());
record.endEdit();
}


this.callOverridden(arguments);
}

});

Ext.define('Workgroup', {
extend: 'Ext.data.Model',
fields: [
'name',
{name: 'startDate', type: 'date'},
{name: 'endDate', type: 'date'}
],
validations: [
{type: 'presence', name: 'name', message: 'Name is required.'},
{type: 'length', name: 'name', min: 3, message: 'Names must be at least 3 characters in length.'},
{type: 'presence', name: 'startDate', message: 'Start Date is required.'}
],
afterEdit: function() {

var me = this;
if(me.dirty){
me.fireEvent('changed', me);
}
this.callParent(arguments);
}
});


Ext.onReady(function() {
var formPanel = Ext.create('Ext.form.Panel', {
frame: true,
title: 'Work Group',
width: 340,
bodyPadding: 5,
renderTo: Ext.getBody(),

fieldDefaults: {
anchor: '100%',
bindToModel: true
},



items: [
{
xtype: 'textfield',
name: 'name',
fieldLabel: 'Name'
},
{
xtype: 'datefield',
name: 'startDate',
fieldLabel: 'Start Date'
}
],

buttons: [
{
text: 'Check',
handler: function() {
console.log('Record data: ', workgroup.data);
console.log('Form record data: ', formPanel.getRecord().data);
console.log('Form validation record data: ', formPanel.getForm()._validationRecord.data);
console.log('Valid: ', formPanel.getForm().isValid());
}
}
]
});


var workgroup = Ext.create('Workgroup', {
name: 'R12345'
});


formPanel.loadRecord(workgroup);
workgroup.set('name', 'New Name');
});


</script>
</head>
<body></body>
</html>




this code work perfect, i have only some problems trying to locale my ExtJS app, here i write one solution for this and move this code to MVC style

http://brainoverflow.co.nf/?p=25

T (http://brainoverflow.co.nf/?p=25)hanks you