Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / examples / writer / writer.js
index 61f60c4..6a41811 100644 (file)
-/*!
- * Ext JS Library 3.3.1
- * Copyright(c) 2006-2010 Sencha Inc.
- * licensing@sencha.com
- * http://www.sencha.com/license
- */
-// Application instance for showing user-feedback messages.
-var App = new Ext.App({});
-
-// Create HttpProxy instance.  Notice new configuration parameter "api" here instead of load.  However, you can still use
-// the "url" paramater -- All CRUD requests will be directed to your single url instead.
-var proxy = new Ext.data.HttpProxy({
-    api: {
-        read : 'app.php/users/view',
-        create : 'app.php/users/create',
-        update: 'app.php/users/update',
-        destroy: 'app.php/users/destroy'
+Ext.define('Writer.Form', {
+    extend: 'Ext.form.Panel',
+    alias: 'widget.writerform',
+
+    requires: ['Ext.form.field.Text'],
+
+    initComponent: function(){
+        this.addEvents('create');
+        Ext.apply(this, {
+            activeRecord: null,
+            iconCls: 'icon-user',
+            frame: true,
+            title: 'User -- All fields are required',
+            defaultType: 'textfield',
+            bodyPadding: 5,
+            fieldDefaults: {
+                anchor: '100%',
+                labelAlign: 'right'
+            },
+            items: [{
+                fieldLabel: 'Email',
+                name: 'email',
+                allowBlank: false,
+                vtype: 'email'
+            }, {
+                fieldLabel: 'First',
+                name: 'first',
+                allowBlank: false
+            }, {
+                fieldLabel: 'Last',
+                name: 'last',
+                allowBlank: false
+            }],
+            dockedItems: [{
+                xtype: 'toolbar',
+                dock: 'bottom',
+                ui: 'footer',
+                items: ['->', {
+                    iconCls: 'icon-save',
+                    itemId: 'save',
+                    text: 'Save',
+                    disabled: true,
+                    scope: this,
+                    handler: this.onSave
+                }, {
+                    iconCls: 'icon-user-add',
+                    text: 'Create',
+                    scope: this,
+                    handler: this.onCreate
+                }, {
+                    iconCls: 'icon-reset',
+                    text: 'Reset',
+                    scope: this,
+                    handler: this.onReset
+                }]
+            }]
+        });
+        this.callParent();
+    },
+
+    setActiveRecord: function(record){
+        this.activeRecord = record;
+        if (record) {
+            this.down('#save').enable();
+            this.getForm().loadRecord(record);
+        } else {
+            this.down('#save').disable();
+            this.getForm().reset();
+        }
+    },
+
+    onSave: function(){
+        var active = this.activeRecord,
+            form = this.getForm();
+
+        if (!active) {
+            return;
+        }
+        if (form.isValid()) {
+            form.updateRecord(active);
+            this.onReset();
+        }
+    },
+
+    onCreate: function(){
+        var form = this.getForm();
+
+        if (form.isValid()) {
+            this.fireEvent('create', this, form.getValues());
+            form.reset();
+        }
+
+    },
+
+    onReset: function(){
+        this.setActiveRecord(null);
+        this.getForm().reset();
     }
 });
 
-// Typical JsonReader.  Notice additional meta-data params for defining the core attributes of your json-response
-var reader = new Ext.data.JsonReader({
-    totalProperty: 'total',
-    successProperty: 'success',
-    idProperty: 'id',
-    root: 'data',
-    messageProperty: 'message'  // <-- New "messageProperty" meta-data
-}, [
-    {name: 'id'},
-    {name: 'email', allowBlank: false},
-    {name: 'first', allowBlank: false},
-    {name: 'last', allowBlank: false}
-]);
+Ext.define('Writer.Grid', {
+    extend: 'Ext.grid.Panel',
+    alias: 'widget.writergrid',
 
-// The new DataWriter component.
-var writer = new Ext.data.JsonWriter({
-    encode: true,
-    writeAllFields: false
-});
+    requires: [
+        'Ext.grid.plugin.CellEditing',
+        'Ext.form.field.Text',
+        'Ext.toolbar.TextItem'
+    ],
 
-// Typical Store collecting the Proxy, Reader and Writer together.
-var store = new Ext.data.Store({
-    id: 'user',
-    proxy: proxy,
-    reader: reader,
-    writer: writer,  // <-- plug a DataWriter into the store just as you would a Reader
-    autoSave: true // <-- false would delay executing create, update, destroy requests until specifically told to do so with some [save] buton.
-});
+    initComponent: function(){
 
-// load the store immeditately
-store.load();
-
-////
-// ***New*** centralized listening of DataProxy events "beforewrite", "write" and "writeexception"
-// upon Ext.data.DataProxy class.  This is handy for centralizing user-feedback messaging into one place rather than
-// attaching listenrs to EACH Store.
-//
-// Listen to all DataProxy beforewrite events
-//
-Ext.data.DataProxy.addListener('beforewrite', function(proxy, action) {
-    App.setAlert(App.STATUS_NOTICE, "Before " + action);
-});
+        this.editing = Ext.create('Ext.grid.plugin.CellEditing');
 
-////
-// all write events
-//
-Ext.data.DataProxy.addListener('write', function(proxy, action, result, res, rs) {
-    App.setAlert(true, action + ':' + res.message);
-});
+        Ext.apply(this, {
+            iconCls: 'icon-grid',
+            frame: true,
+            plugins: [this.editing],
+            dockedItems: [{
+                xtype: 'toolbar',
+                items: [{
+                    iconCls: 'icon-add',
+                    text: 'Add',
+                    scope: this,
+                    handler: this.onAddClick
+                }, {
+                    iconCls: 'icon-delete',
+                    text: 'Delete',
+                    disabled: true,
+                    itemId: 'delete',
+                    scope: this,
+                    handler: this.onDeleteClick
+                }]
+            }, {
+                weight: 2,
+                xtype: 'toolbar',
+                dock: 'bottom',
+                items: [{
+                    xtype: 'tbtext',
+                    text: '<b>@cfg</b>'
+                }, '|', {
+                    text: 'autoSync',
+                    enableToggle: true,
+                    pressed: true,
+                    tooltip: 'When enabled, Store will execute Ajax requests as soon as a Record becomes dirty.',
+                    scope: this,
+                    toggleHandler: function(btn, pressed){
+                        this.store.autoSync = pressed;
+                    }
+                }, {
+                    text: 'batch',
+                    enableToggle: true,
+                    pressed: true,
+                    tooltip: 'When enabled, Store will batch all records for each type of CRUD verb into a single Ajax request.',
+                    scope: this,
+                    toggleHandler: function(btn, pressed){
+                        this.store.getProxy().batchActions = pressed;
+                    }
+                }, {
+                    text: 'writeAllFields',
+                    enableToggle: true,
+                    pressed: false,
+                    tooltip: 'When enabled, Writer will write *all* fields to the server -- not just those that changed.',
+                    scope: this,
+                    toggleHandler: function(btn, pressed){
+                        this.store.getProxy().getWriter().writeAllFields = pressed;
+                    }
+                }]
+            }, {
+                weight: 1,
+                xtype: 'toolbar',
+                dock: 'bottom',
+                ui: 'footer',
+                items: ['->', {
+                    iconCls: 'icon-save',
+                    text: 'Sync',
+                    scope: this,
+                    handler: this.onSync
+                }]
+            }],
+            columns: [{
+                text: 'ID',
+                width: 40,
+                sortable: true,
+                dataIndex: 'id'
+            }, {
+                header: 'Email',
+                flex: 1,
+                sortable: true,
+                dataIndex: 'email',
+                field: {
+                    type: 'textfield'
+                }
+            }, {
+                header: 'First',
+                width: 100,
+                sortable: true,
+                dataIndex: 'first',
+                field: {
+                    type: 'textfield'
+                }
+            }, {
+                header: 'Last',
+                width: 100,
+                sortable: true,
+                dataIndex: 'last',
+                field: {
+                    type: 'textfield'
+                }
+            }]
+        });
+        this.callParent();
+        this.getSelectionModel().on('selectionchange', this.onSelectChange, this);
+    },
+    
+    onSelectChange: function(selModel, selections){
+        this.down('#delete').setDisabled(selections.length === 0);
+    },
 
-////
-// all exception events
-//
-Ext.data.DataProxy.addListener('exception', function(proxy, type, action, options, res) {
-    if (type === 'remote') {
-        Ext.Msg.show({
-            title: 'REMOTE EXCEPTION',
-            msg: res.message,
-            icon: Ext.MessageBox.ERROR,
-            buttons: Ext.Msg.OK
+    onSync: function(){
+        this.store.sync();
+    },
+
+    onDeleteClick: function(){
+        var selection = this.getView().getSelectionModel().getSelection()[0];
+        if (selection) {
+            this.store.remove(selection);
+        }
+    },
+
+    onAddClick: function(){
+        var rec = new Writer.Person({
+            first: '',
+            last: '',
+            email: ''
+        }), edit = this.editing;
+
+        edit.cancelEdit();
+        this.store.insert(0, rec);
+        edit.startEditByPosition({
+            row: 0,
+            column: 1
         });
     }
 });
 
-// A new generic text field
-var textField =  new Ext.form.TextField();
-
-// Let's pretend we rendered our grid-columns with meta-data from our ORM framework.
-var userColumns =  [
-    {header: "ID", width: 40, sortable: true, dataIndex: 'id'},
-    {header: "Email", width: 100, sortable: true, dataIndex: 'email', editor: textField},
-    {header: "First", width: 50, sortable: true, dataIndex: 'first', editor: textField},
-    {header: "Last", width: 50, sortable: true, dataIndex: 'last', editor: textField}
-];
+Ext.define('Writer.Person', {
+    extend: 'Ext.data.Model',
+    fields: [{
+        name: 'id',
+        type: 'int',
+        useNull: true
+    }, 'email', 'first', 'last'],
+    validations: [{
+        type: 'length',
+        field: 'email',
+        min: 1
+    }, {
+        type: 'length',
+        field: 'first',
+        min: 1
+    }, {
+        type: 'length',
+        field: 'last',
+        min: 1
+    }]
+});
 
-Ext.onReady(function() {
-    Ext.QuickTips.init();
+Ext.require([
+    'Ext.data.*',
+    'Ext.tip.QuickTipManager',
+    'Ext.window.MessageBox'
+]);
 
-    // create user.Form instance (@see UserForm.js)
-    var userForm = new App.user.Form({
-        renderTo: 'user-form',
+Ext.onReady(function(){
+    Ext.tip.QuickTipManager.init();
+    var store = Ext.create('Ext.data.Store', {
+        model: 'Writer.Person',
+        autoLoad: true,
+        autoSync: true,
+        proxy: {
+            type: 'ajax',
+            api: {
+                read: 'app.php/users/view',
+                create: 'app.php/users/create',
+                update: 'app.php/users/update',
+                destroy: 'app.php/users/destroy'
+            },
+            reader: {
+                type: 'json',
+                successProperty: 'success',
+                root: 'data',
+                messageProperty: 'message'
+            },
+            writer: {
+                type: 'json',
+                writeAllFields: false,
+                root: 'data'
+            },
+            listeners: {
+                exception: function(proxy, response, operation){
+                    Ext.MessageBox.show({
+                        title: 'REMOTE EXCEPTION',
+                        msg: operation.getError(),
+                        icon: Ext.MessageBox.ERROR,
+                        buttons: Ext.Msg.OK
+                    });
+                }
+            }
+        },
         listeners: {
-            create : function(fpanel, data) {   // <-- custom "create" event defined in App.user.Form class
-                var rec = new userGrid.store.recordType(data);
-                userGrid.store.insert(0, rec);
+            write: function(proxy, operation){
+                if (operation.action == 'destroy') {
+                    main.child('#form').setActiveRecord(null);
+                }
+                Ext.example.msg(operation.action, operation.resultSet.message);
             }
         }
     });
 
-    // create user.Grid instance (@see UserGrid.js)
-    var userGrid = new App.user.Grid({
-        renderTo: 'user-grid',
-        store: store,
-        columns : userColumns,
-        listeners: {
-            rowclick: function(g, index, ev) {
-                var rec = g.store.getAt(index);
-                userForm.loadRecord(rec);
-            },
-            destroy : function() {
-                userForm.getForm().reset();
+    var main = Ext.create('Ext.container.Container', {
+        padding: '0 0 0 20',
+        width: 500,
+        height: 450,
+        renderTo: document.body,
+        layout: {
+            type: 'vbox',
+            align: 'stretch'
+        },
+        items: [{
+            itemId: 'form',
+            xtype: 'writerform',
+            height: 150,
+            margins: '0 0 10 0',
+            listeners: {
+                create: function(form, data){
+                    store.insert(0, data);
+                }
             }
-        }
+        }, {
+            itemId: 'grid',
+            xtype: 'writergrid',
+            title: 'User List',
+            flex: 1,
+            store: store,
+            listeners: {
+                selectionchange: function(selModel, selected) {
+                    main.child('#form').setActiveRecord(selected[0] || null);
+                }
+            }
+        }]
     });
 });