A composed finish

Now, we come to the view that allows you to actually send e-mails, a pretty important part of this application!

// app/view/composer/Composer.js
Ext.define('Postcard.view.composer.Composer', {
    extend: 'Ext.form.Panel',
    xtype: 'composer',
    cls: 'composer',
    viewModel: 'composer',
    controller: 'composer',
    session: true,
    items: [
        { xtype: 'hiddenfield', bind: '{newMessage.parentId}' },
        {
            fieldLabel: 'To', xtype: 'combo', width: '100%',
            valueField: 'e-mail',
            displayField: 'e-mail',
            queryMode: 'local',
            bind: {
                hidden: '{newMessage.parentId}',
                store: '{contacts}',
                value: '{newMessage.people}'
            }
        },
        {
            xtype: 'textfield', fieldLabel: 'Subject',
            cls: 'subject', emptyText: 'Subject',
            bind: {
                value: '{newMessage.subject}',
                hidden: '{newMessage.parentId}'
            },
            width: '100%'
        },
        {
            xtype: 'htmleditor',
            bind: { value: '{newMessage.body}' }
        }
    ],
    bbar: [
        '->',
        { xtype: 'button', text: 'Send' }
    ]
});

Another straightforward component definition, with the values of the form fields being bound to the newMessage object in the view model for later use. There's another view model trick here, that is, if this newMessage object has a parentId value, we know that we're replying to an existing thread. This means that we can hide the subject and recipient form fields, so we bind the parentId to their hidden value, making this step automatic as follows:

// app/view/composer/ComposerModel.js
Ext.define('Postcard.view.Composer.ComposerModel', {
    extend: 'Ext.app.ViewModel',
    alias: 'viewmodel.composer',
    stores: {
        contacts: {
            type: 'contacts'
        }
    },

    data: {
        newMessage: {}
    }
});

We have the contacts store that corresponds to the one in the view that was bound to the recipient's combo and then an empty definition for the newMessage object discussed previously.

// app/view/composer/ComposerController.js
Ext.define('Postcard.view.composer.ComposerController', {
    extend: 'Ext.app.ViewController',
    alias: 'controller.composer',
    listen: {
        component: {
            'button': {
                click: 'onSendClick'
            }
        }
    },

    routes: {
        'thread/:id/messages': 'hideComposer',
        'thread/:id/messages/new': 'showComposer',
        'thread/new': 'showComposer'
    },

    hideComposer: function() {
        this.getView().hide();
    },

    showComposer: function(parentId) {
        this.getViewModel().set('newMessage.parentId', parentId);
        this.getView().show();
    },

    onSendClick: function() {
        var session = this.getSession(),
            data = this.getViewModel().get('newMessage'),

        session.createRecord('Postcard.model.Message', {
            people: data.people,
            subject: data.subject,
            body: data.body,
            parentId: data.parentId
        });

        var batch = session.getSaveBatch().start();

        batch.on('complete', this.onSaveComplete, this);
    },

    onSaveComplete: function(batch, operation) {
        var record = operation.getRecords()[0],
            id = record.getId(),
            parentId = record.get('parentId'),

        this.redirectTo('thread/' + (parentId || id) + '/messages'),
    }
});

In component listeners, we handle the click event of the send button with the onSendClick method. This creates a new record on the current session and saves it to the server. In the callback method, we dispatch the application to the route that shows thread messages, but note that we'll use the ID of the new message in the event of it being a brand new thread and the parentID of the new message if it's a reply.

In terms of handling routes, there's one (hideComposer) that hides the composer when viewing the messages in a thread because there's no need for it to be visible at that point. Then, there's a second (showComposer) that sets the parentId on the newMessage and shows the composer. For new threads, there's no ID captured by the route, so the parentId argument will be undefined and newMessage.parentId will be set as such. This enables the automatic viewing and hiding of the recipient and subject back in the composer view itself. Back when designing the app, we referred to this as currentThreadId, but we can see now that it makes sense to incorporate it in the newMessage object and pass this to the server when we save the new record.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset