Our Project
, Task
, and TaskLog
models were created with basic fields using Sencha Cmd in Chapter 9, Getting Started with Ext JS 4, but they lacked in persistence or validation logic. It is now time to add the required code.
The TaskLog
model is the most complicated model in our application. The complete TaskLog
model with all required logic is as follows:
Ext.define('TTT.model.TaskLog', { extend: 'Ext.data.Model', fields: [ { name: 'idTaskLog', type: 'int', useNull:true }, { name: 'taskDescription', type: 'string' }, { name: 'taskLogDate', type: 'date', dateFormat:'Ymd' }, { name: 'taskMinutes', type: 'int' }, { name: 'hours', type: 'float', persist:false, convert:function(value, record){ return record.get('taskMinutes') / 60; }}, { name: 'username', type: 'string' }, { name: 'userFullName', type: 'string', persist:false }, { name: 'idTask', type: 'int', useNull:true }, { name: 'taskName', type: 'string', persist:false }, { name: 'idProject', type: 'int', persist:false }, { name: 'projectName', type: 'string', persist:false }, { name: 'idCompany', type: 'int', persist:false }, { name: 'companyName', type: 'string', persist:false } ], idProperty: 'idTaskLog', proxy: { type: 'ajax', idParam:'idTaskLog', api:{ create:'taskLog/store.json', read:'taskLog/find.json', update:'taskLog/store.json', destroy:'taskLog/remove.json' }, reader: { type: 'json', root: 'data' }, writer: { type: 'json', allowSingle:true, encode:true, root:'data', writeAllFields: true } }, validations: [ {type: 'presence', field: 'taskDescription'}, {type: 'length', field: 'taskDescription', min: 2}, {type: 'presence', field: 'username'}, {type: 'presence', field: 'taskLogDate'}, {type: 'presence', field: 'idTask'}, {type: 'length', field: 'idTask', min: 1}, {type: 'length', field: 'taskMinutes', min: 0} ] });
This is the first time we have used the useNull
property on a field. The useNull
property is important when converting JSON data into an int
, float
, Boolean
, or String
type. When a value cannot be parsed by the reader, the following default values are set for the model field:
Field type |
Default value with |
Default value with |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
If the value cannot be parsed by the reader, null
will be assigned to the field value if the field is configured with useNull:true
. Otherwise, a default value for that type will be used as displayed in the third column in the preceding table. Note that the Date
fields are always set to null
if the value cannot be parsed. In most circumstances, it is important to be able to discern whether a field is null after reading the record, and hence, we recommend setting the useNull:true
property for all primary key fields.
This is also the first time that we have used the dateFormat
property. This property defines the format of the date while encoding or decoding JSON date
fields via the configured writer
and reader
classes. The YYYYMMDD
format string represents an 8-digit number. For example, the date 18th August, 2013, is equivalent to 20130818. The other format strings are documented in the Ext.Date
API at http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.Date. It is strongly recommended that you always specify an explicit date format for any date
field.
The use of the convert
function for the hours
field is also new. It converts a value provided by the reader
class and stores it in the configured name
field of the model. In our TaskLog
model, the number of minutes is converted into a decimal value and stored in the hours
field. It will be far more convenient for the 3T user to enter a value of 2.5 hours rather than 150 minutes.
Note that we have once again used the persist:false
property to restrict the fields that are not required for persistence in our TaskLogHandler
methods. Our validations for the TaskLog
model should also be self-explanatory!
The Project
model defines our usual proxy and validation properties:
Ext.define('TTT.model.Project', { extend: 'Ext.data.Model', fields: [ { name: 'idProject', type: 'int', useNull:true }, { name: 'projectName', type: 'string' }, { name: 'idCompany', type:'int', useNull:true }, { name: 'companyName', type:'string', persist:false } ], idProperty: 'idProject', proxy: { type: 'ajax', idParam:'idProject', api:{ create:'project/store.json', read:'project/find.json', update:'project/store.json', destroy:'project/remove.json' }, reader: { type: 'json', root: 'data' }, writer: { type: 'json', allowSingle:true, encode:true, root:'data', writeAllFields: true } }, validations: [ {type: 'presence', field: 'projectName'}, {type: 'length', field: 'projectName', min: 2}, {type: 'presence', field: 'idCompany'}, {type: 'length', field: 'idCompany', min: 1} ] });
There is no need to include the companyName
field while persisting a record and hence the field includes the persist:false
property.
The Task
model also has a simple structure:
Ext.define('TTT.model.Task', { extend: 'Ext.data.Model', fields: [ { name: 'idTask', type: 'int', useNull:true }, { name: 'taskName', type: 'string' }, { name: 'idProject', type: 'int', useNull:true }, { name: 'projectName', type: 'string', persist:false }, { name: 'idCompany', type: 'int', useNull:true, persist:false }, { name: 'companyName', type: 'string', persist:false } ], idProperty: 'idTask', proxy: { type: 'ajax', idParam:'idTask', api:{ create:'task/store.json', read:'task/find.json', update:'task/store.json', destroy:'task/remove.json' }, reader: { type: 'json', root: 'data' }, writer: { type: 'json', allowSingle:true, encode:true, root:'data', writeAllFields: true } }, validations: [ {type: 'presence', field: 'taskName'}, {type: 'length', field: 'taskName', min: 2}, {type: 'presence', field: 'idProject'}, {type: 'length', field: 'idProject', min: 1} ] });
Once again we have several fields that do not need to be persisted and are hence configured with the persist:false
property. It is now time to define the stores required to build our task log user interface.
18.117.74.231