Part 1 Basics (mostly server side)
Part 2 (this) ExtJS Client Side Details

  

In the first article, a very simple updater was build using Sencha’s ExtJS and Microsoft’s Entity Framework Code First.  The focus was really on the server side while the client side project was included for reference.  The client side app was barely discussed.  In this article, we are going to discuss in more detail what is happening on the client side and how the Sencha ExtJS JavaScript library helps us to implement these updates.

 

The Basics

Let’s start out with some basics rather than jump right in to the real project.   I think we can all assume the displaying of the data is pretty simple. We just create a store, add some fields, hook it up to a Ext.grid.Panel and set the store to autoload and it all just works.  Updating though does add a little more complexity and for that, we are going to add some structure.  So, let’s take a look at the very basics without any UI at all.

Just by way of reminders, we create two simple services in our project.  One that reads and the other that updates.  For the purpose of this article, those are the three (of four) CRUD operations we are going to implement (read,insert and update).  Let’s first implement those operations directly.  Below is a very straight forward JavaScript which basically represents a completely working ExtJS app with a single button in the viewport.  Here is the code below.

Ext.Loader.setConfig({ enabled: true });
Ext.require('Ext.container.Viewport');

Ext.application({
    name: 'AM',

    controllers: [
        'Users'
    ],

    launch: function() {
        Ext.create('Ext.container.Viewport', {
            layout: 'border',
            items: [
                {
                    xtype: 'button',
                    region: 'center',
                    text: 'Insert a Record',
                    handler: function () {
                        var writer = new Ext.data.JsonWriter({
                            type: 'json',
                            encode: false,
                            listful: true,
                            writeAllFields: true,
                            returnJson: true
                        });

                        var reader = new Ext.data.JsonReader({
                            totalProperty: 'total',
                            successProperty: 'success',
                            idProperty: 'Id',
                            root: 'Data',
                            messageProperty: 'message'
                        });

                        var proxy = new Ext.data.HttpProxy({
                            reader: reader,
                            writer: writer,
                            type: 'ajax',
                            api: {
                                read: '/UserInfo/Get',
                                create: '/UserInfo/Create',
                                update: '/UserInfo/Update',
                                destroy: '/UserInfo/Delete'
                            },
                            headers: {
                                'Content-Type': 'application/json; charset=UTF-8'
                            }
                        });

                        Ext.define('MyModel', {
                            extend: 'Ext.data.Model',
                            fields: ['Id', 'Name', 'Email'],
                            proxy: proxy
                        });

                        Ext.define('MyStore', {
                            extend: 'Ext.data.Store',
                            model: 'MyModel',
                            autoLoad: true,
                            paramsAsHash: true,
                            proxy: proxy
                        });

                        var myStore = Ext.create('MyStore', {
                        });

                        myStore.add({
                            Name: 'TestName',
                            Email: 'TestEmail@Test.com'
                        });

                        myStore.sync();
                    }
                }
            ]
        });
    }
});

Without going into to much detail, basically, what has been done above is a to create a simple model (myModel) which contains a JsonReader and JsonWriter and proxy of course. This model has a couple fields in it (Id,Name and Email), then a simple store is created that uses this model called myStore.  Once this store has been created, we simply call the store’s “add” method with a config object that represents the data, then calling sync() on that store forces an insert (or create) to be executed through the proxy.  If I look at Chrome’s JavaScript debugger (network tab), you can see from the picture below that indeed, the servers UserInfo/Create method has been called passing in the parameters Name and Email.

 

image

 

It’s important to understand these steps because we will be using the store and model in a similar way when we update the data in our next section.

 

Implementation in Grid and Editor Panel

 

We are using the ExtJS MVC architecture for this app so all our procedural code is in the controller.  For the Ext.grid.Panel, all we have for the view is the following (app/view/List.js).

 

image

 

Ext.define('AM.view.user.List', {
    extend: 'Ext.grid.Panel',
    alias: 'widget.userlist',

    title: 'All Users',
    store: 'Users',

    columns: [
    { header: 'Name', dataIndex: 'Name', flex: 1 },
    { header: 'Email', dataIndex: 'Email', flex: 1 }
    ]
});

Then, in our controller (app/controller/Users.js) we have the working code that actually does the editing and updating of the record.  the code is below:

Ext.define('AM.controller.Users', {
    extend: 'Ext.app.Controller',
    stores: ['Users'],
    models: ['User'],
    views: ['user.Edit', 'user.List'],
    refs: [
        {
            ref: 'usersPanel',
            selector: 'panel'
        }
    ],
    init: function() {
        this.control({
            'viewport > userlist dataview': {
                itemdblclick: this.editUser
            },
            'useredit button[action=save]': {
                click: this.updateUser
            }
        });
    },
    editUser: function(grid, record) {
        var edit = Ext.create('AM.view.user.Edit').show();

        edit.down('form').loadRecord(record);
    },
    updateUser: function(button) {
        var win    = button.up('window'),
            form   = win.down('form'),
            record = form.getRecord(),
            values = form.getValues();
        record.set(values);
        win.close();
        this.getUsersStore().sync();
    }
});

Basically, this follows the exact same method we described above for implementing the CRUD.  Note getUsersStore().sync.  This does the same thing as shown above to force the appropriate call the back end.

 

Remarks

Hope this helps give you a little more understanding into updating with the ExtJS library. If you are looking for the source, it’s in part 1 of this series.

 

Introduction

This three part series demonstrates a very simple example of using Entity Framework Code First (Version 4.3) to create a SqlServer Table and populate it with data (that is part 1).  Part 2 adds two new columns to the table a populates the data conditionally (while migrating from a non migration enabled project), and Part 3 adds a new column with a default value to a migration enabled code first project.

As it happens, I watched President Obama drive by me in San Francisco yesterday so he will be the star of the post.  The table we will use is called Presidents, and the columns we will add are Year Elected and Current.  We will obviously only have one current president so we will have to have our migration conditionally set CurrentPresident to true for Obama.

 

 

 
 

 

What To Do

We simply create a console version with Visual Studio 2010 in c#.  Using nuget package manager console we say “Install-Package EntityFramework”, then replace the primary Program.cs with the following file (you should add a connection string with the name SiteDB also if you want it to create a SqlServer Database.
 
Here is the code:
 
namespace ConApp
{
    internal class Program
    {
        private static void Main()
        {
            Database.SetInitializer<SiteDB>(new SiteDBInitialize());
            using (var myContext = new SiteDB())
            {
                var x = myContext.Presidents.ToList();
            }
        }
    }

    public class SiteDB : DbContext
    {
        public DbSet<Presidents> Presidents { get; set; }
    }

    public class Presidents
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public long Id { get; set; }
        public string LastName { get; set; }
    }

    public class SiteDBInitialize :
        DropCreateDatabaseIfModelChanges<SiteDB>
    {
        protected override void Seed(SiteDB context)
        {
            context.Presidents.Add(new Presidents { LastName = "Reagan" });
            context.Presidents.Add(new Presidents { LastName = "Bush" });
            context.Presidents.Add(new Presidents { LastName = "Obama" });
            context.SaveChanges();
        }
    }

}

I won’t go into details of all the steps because this is all very well documented on the EF site at this url among others:

http://msdn.microsoft.com/en-us/library/gg696189(v=vs.103).aspx

What is interesting to note is that I am implementing the interface DropCreateDatabaseIfModelChanges.  What stumped me for a while was that in my main console, we always call new SiteDBInitialize), however what that class implments determines the action on creation.  There are three choices.

  1. DropCreateDatabaseIfModelChanges
  2. DropCreateDatabaseAlways
  3. CreateDatabaseIfNotExists

The meaning is self explanatory, you just need to derive from the appropriate class depending on what your intention is.  All the calls can be seen here in the MSDN documentation:  http://msdn.microsoft.com/en-us/library/gg696142(v=vs.103).aspx

Hope this helps, read on to part 2 to find out how to add some columns and conditionally populate them.

 


© 2012 PeterKellner.net. All Rights Reserved
Follow

Get every new post delivered to your Inbox

Join other followers: