"ExtJS ve Coolite ne ola ki?" Yazı Dizisi Vol.2

Yazar: Mehmet Sencer KARADAYI
Kategori: ASP.NET
Eklenme Tarihi: 19.3.2010 11:14:34



Serinin ikinci makalesinde, ExtJS ile nasıl uygulama geliştiririz ' i örnekleriyle birlikte inceliyor olacağız.

Bu makalemde " ExtJS ve Coolite ne ola ki? " yazı dizisinin devamı olarak ExtJS objelerinden "Grid" objesini nasıl kullanırız?, datada grid üzerinden nasıl değişiklik yaparız? ana başlıkları altında bir çok kavrama değineceğim. 

Lafa başlamadan önce iki makale arasında bu kadar ara verdiğim için herkesten özür dilerim. Okul ve iş yoğunluğu arasında boğulmakla uğraştığımdan makaleye zaman ayıramadım. Bu aksaklığı telafi etmeye çalışacağıma söz veriyorum.

ExtJS' nin genel hatlarının üstünden geçmiştik. Şimdi ise birçok konuyu harmanlayan bir senaryo üzerinden devam edelim. Amacımız, ExtJS objelerini kullanarak hem güzel bir UI elde etmek, hem de nasıl data işlemleri yaparız sorusunun cevabını aramak olacak. Senaryomuz da şu olsun : Biz bir meyve üreticisiyiz. Ürettiğimiz meyveleri görmek, kayıtlarının üstünde değişiklik yapmak ve onları satmak istiyoruz.

Senaryomuzu hayata geçirmeye başlamadan önce yapmamız gereken bazı önemli şeyler var :

  1. ExtJS' nin güncel kütüphanesini (versiyon 3.1.1) indirmek
  2. HTML ve JavaScript kodlarımızı düzenlemek için uygun bir editör seçmek: Visual Studio ortamını kullanabilirsiniz.

Bu iki öngereksinimi de gerçekleştirdikten sonra projemize başlamamız için önümüzde bir engel kalmıyor. Visual Studio' da bir "Web Site" oluşturarak başlayabiliriz.

Projeyi oluşturduktan sonra indirdiğimiz ExtJS kütüphanesinden bir kaç dosyayı projemize dahil etmeliyiz. Bunun için site içinde "extLib" adlı bir dosya oluşturduktan sonra ExtJS kütüphanesinin kök dosyasından yola çıkarak,

  1. ext-all.js javascript dosyasını,
  2. "adaptor" klasörünü,
  3. "resources" klasörünü,
  4. "examples/ux" klasörünü,
  5. "examples/shared" klasörünü,
  6. "examples/grid/grid-example.css" stil dosyasını

oluşturduğumuz klasöre kopyalayalım. Neden bu dosyaları ve klasörleri kopyaladığımıza gelicek olursak; içlerinde bize lazım olan temel ext javascript dosyaları ve css dosyaları bulunuyor. Bu yüzden bu öğeleri projemize dahil etmemiz gerekiyor.

İşlemlerden sonra oluşması gereken ekran görüntüsü

undefined

Kodlama kısmına yavaş yavaş geçerken neler yapmamız gerektiğine adım adım bakarsak,

1) <head></head>  tagları arasına gerekli olan referanlarımızı eklemeliyiz. Bahsettiğim javascript ve css referansları aşağıdaki gibidir.

undefined
undefined

    <!--JS dosyaları-->

    <script type="text/javascript" src="extLib/adapter/ext/ext-base.js"></script>

    <script type="text/javascript" src="extLib/ext-all.js"></script>

    <script type="text/javascript" src="extLib/ux/RowEditor.js"></script>

 

    <!--CSS dosyaları-->

    <link rel="stylesheet" type="text/css" href="extLib/resources/css/ext-all.css" />

    <link rel="stylesheet" type="text/css" href="extLib/grid-examples.css" />

    <link rel="stylesheet" type="text/css" href="extLib/shared/examples.css" />

    <link rel="stylesheet" type="text/css" href="extLib/ux/css/RowEditor.css" />

 

    <style type="text/css">

        .icon-user-add {

            background-image: url(extLib/shared/icons/fam/user_add.gif) !important;

        }

        .icon-user-delete {

            background-image: url(extLib/shared/icons/fam/user_delete.gif) !important;

        }       

    </style>

undefined

 

undefined

Bu noktada "ext-base.js" ve "ext-all.js" dosyalarının bizim için vazgeçilmez olduğunu vurgulamakta fayda var. Her ne yapıyor olursak olalım, bu iki dosyayı mutlaka referans almalıyız. Onların yanında kullandığımız ekstra özellikleri içeren JavaScript dosyalarını da projeye dahil etmeliyiz. Örneğin, benim örneğimde RowEditor kullanıldığından, aynı isimli JavaScript dosyasını da projeye dahil ettim.

2) Eklememiz gereken bütün dosyaları projemize referans aldıktan sonra, bütün işlemlerimizi yapacağımız JavaScript kodumuzu oluşturmaya geçebiliriz.

Uygulamada kullanacağımız dataların şablonunu hazırlamalıyız. 

          var Urun = Ext.data.Record.create([{

              name: 'ad',

              type: 'string'

          }, {

              name: 'tip',

              type: 'string'

          }, {

              name: 'uretim',

              type: 'date',

              dateFormat: 'n/j/Y'

          }, {

              name: 'adet',

              type: 'integer'

          }, {

              name: 'fiyat',

              type: 'integer'}]);

undefined

Yukarıda da gördüğünüz gibi Ext.data.Record.create metodunu kullanarak; alan adları ad, tip, uretim, adet ve fiyat olan bir tablo oluşturduk ve adına da "Urun" dedik.

Doğal olarak bu şablonu kullanarak data oluşturmamız gerekmektedir. Ben bu örnek için istemci-taraflı data oluşturup oynamaları o datanın üstünde yaparız diye düşündüm. Bir sonraki makalemde sunucu-taraflı dataları çekip istemci tarafında oynamaları yapıp değişikliklerin kaydedilmesi için yine sunucu tarafına göndermeyi nasıl yapıcağımıza göz atacağız. Dediğim gibi kayıt oluşturmak için bir metoda ihtiyacımız var.

         var genData = function() {

                  var data = [];

                  var s = new Date(2007, 0, 1);

                  var now = new Date(), i = -1;

                  while (s.getTime() < now.getTime()) {

                      var ecount = Ext.ux.getRandomInt(0, 1);

                      for (var i = 0; i < ecount; i++) {

                          var name = Ext.ux.generateName();

                          data.push({

                              uretim: s.clearTime(true).add(Date.DAY, Ext.ux.getRandomInt(0, 27)),

                              ad: name,

                              tip: 'Meyve',

                              adet: Ext.ux.getRandomInt(10, 100),

                              fiyat: Ext.ux.getRandomInt(10, 100)

                          });

                      }

                      s = s.add(Date.MONTH, 1);

                  }

                  return data;

              }

undefined

Bu fonksiyon bizim işimizi görür. Nasıl işlediğine biraz göz atalım : 2007 den başlayarak günümüze kadar düzgün devam etmeyen bi döngü var. Her bir turda oluşturduğumuz diziye, alan değerleri gelişi güzel olan yeni bir kayıt ekliyoruz. Bu sayede yaklaşık on yedi adet, birbirinden farklı kayıt elde etmiş oluyoruz.

 Bir sonraki adımda oluşan bu kayıtları grid objemize nasıl bağlayacağız sorunu ortaya çıkıyor. Tabii ki imdadımıza yetişen bir Ext objesi var : Store. Store objesi, bizim datalarımızı, üstünde yapılan değişiklikleri, son halini kısaca herşeyi barındıran, çok özel bir nesne. Kullanımı ise çok kolay.

              var store = new Ext.data.GroupingStore({

                  reader: new Ext.data.JsonReader({ fields: Urun }),

                  //datayı nereden alıcagını belirttik.

                  data: genData(),

                  sortInfo: { field: 'uretim', direction: 'ASC' }

              });

undefined

Store nesnesi kayıtları json halinde saklıyor. Bu yüzden hangi tip kayıtları okuyacağını belirtmemiz gerekiyor. Ayrıca bir çok başka özelliği daha var. Yukarıda örnek olarak sortInfo özelliğine hangi alanı ne tipte sıralayacağını belirtmişim. API dökümantasyonunu incelerseniz, bu güzel nesnenin bir çok farklı özelliğe sahip olduğunu göreceksiniz.

Sıra geldi Grid nesnemizi yaratmaya.

//gridimizi yaratalım

              var grid = new Ext.grid.GridPanel({

                  //grid oluştururken 'store' degerini vermeyi unutmayınız.

                  store: store,

                  width: 600,

                  region: 'center',

                  margins: '0 5 5 5',

                  autoExpandColumn: 'ad',

                  plugins: [editor],

                  view: new Ext.grid.GroupingView({

                      markDirty: false

                  }),

                  // 'topbar' daki butonlarımızı oluşturuyoruz.

                  tbar: [{

                      iconCls: 'icon-user-add',

                      text: 'Urun Ekle',

                      handler: function() {

                          var e = new Urun({

                              ad: 'Meyve Adi',

                              tip: 'Meyve',

                              uretim: (new Date()).clearTime(),

                              adet: 1,

                              fiyat: 10

                          });

                          editor.stopEditing();

                          store.insert(0, e);

                          grid.getView().refresh();

                          grid.getSelectionModel().selectRow(0);

                          editor.startEditing(0);

                      }

                  }, {

                      ref: '../removeBtn',

                      iconCls: 'icon-user-delete',

                      text: 'Urun Sil',

                      disabled: true,

                      handler: function() {

                          editor.stopEditing();

                          var s = grid.getSelectionModel().getSelections();

                          for (var i = 0, r; r = s[i]; i++) {

                              store.remove(r);

                          }

                      }

                  }, {

                      ref: '../removeBtn',

                      iconCls: 'icon-user-delete',

                      text: 'Urun Sat',

                      disabled: true,

                      handler: function() {

                          editor.stopEditing();

                          var s = grid.getSelectionModel().getSelections();

                          for (var i = 0, r; r = s[i]; i++) {

                              if (r.data['adet'] == 1) {

                                  para = para + r.data['fiyat'];

                                  store.remove(r);

                                  Ext.MessageBox.alert('Satis', 'Satis Islemi tamamlandi. Urun kalmadi!Suan ' + para + ' kadar paraniz var.');

                              }

                              else {

                                  para = para + r.data['fiyat'];

                                  r.set("adet", r.data['adet'] - 1);

                                  r.commit();

                                  Ext.MessageBox.alert('Satis', 'Satis Islemi tamamlandi. Suan ' + para + ' kadar paraniz var.');

                              }

                          }

                      }

}],

                      //Kolonlarımızı özellestirelim.

                      columns: [

        new Ext.grid.RowNumberer(),

        {

            id: 'ad',

            header: 'Meyve Adi',

            dataIndex: 'ad',

            width: 220,

            sortable: true,

            editor: {

                xtype: 'textfield',

                allowBlank: false

            }

        }, {

            header: 'Tip',

            dataIndex: 'tip',

            width: 150,

            sortable: true,

            editor: {

                xtype: 'textfield',

                blankText: "Bos Birakma!",

                allowBlank: false

            }

        }, {

            xtype: 'datecolumn',

            header: 'Uretim Tarihi',

            dataIndex: 'uretim',

            format: 'm/d/Y',

            width: 100,

            sortable: true,

            groupRenderer: Ext.util.Format.dateRenderer('M y'),

            editor: {

                xtype: 'datefield',

                allowBlank: false,

                blankText: "Bos Birakma!",

                maxValue: (new Date()).format('m/d/Y')

            }

        },

        {

            header: 'Adet',

            dataIndex: 'adet',

            minValue: 1,

            width: 50,

            sortable: true,

            editor: {

                xtype: 'numberfield',

                blankText: "Bos Birakma!",

                allowBlank: false

            }

        },

        {

            header: 'Fiyat',

            dataIndex: 'fiyat',

            minValue: 1,

            width: 50,

            sortable: true,

            editor: {

                xtype: 'numberfield',

                allowBlank: false

            }

}]

                  });

undefined

Öncellikle Grid' imizin store özelliğine değer atamamız gerekiyor. Bu değer tabii ki bizim oluşturduğumuz store nesnesinin adı olacak.

Bu noktada size Grid nesnesinin Top Bar özelliğinden bahsetmek istiyorum. Top Bar bize grid üzerine buton koyma imkanı sağlayan bir bölüm. Bu sayede grid üzerinde işlem yaparken kullanacağımız butonları buraya tanımlayabiliyoruz. Yukarıda da görebileceğiniz üzere Top Bar' a 3 tane buton tanımladık. Bu butonların her birinin text, disabled, iconCls gibi özellikleri var. Fakat handler özelliği diğer hepsinden daha çekici bana kalırsa. Bu özelliğe istersek işlem yapıcak foksiyonun sadece ismini tanımlarız, istersek örnekteki gibi fonksiyonu oraya yazarız.

Son olarak sıra geldi grid üzerindeki kolonları tanımlamaya. Kolonları özelleştirme noktasında da Ext bize baya bir esneklik sağlıyor. Başlığından, editörünün kısıtlanmasına kadar örnekte de görebileceğiniz bir çok özelleştirmede bulunabiliyoruz.

Böylece kodumuzdaki önemli noktaların ve kavramların üstünden geçmiş olduk. Kodun tamamı aşağıdaki gibidir.

[Default.aspx]

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title></title>

    <!--JS dosyaları-->

    <script type="text/javascript" src="extLib/adapter/ext/ext-base.js"></script>

    <script type="text/javascript" src="extLib/ext-all.js"></script>

    <script type="text/javascript" src="extLib/ux/RowEditor.js"></script>

 

    <!--CSS dosyaları-->

    <link rel="stylesheet" type="text/css" href="extLib/resources/css/ext-all.css" />

    <link rel="stylesheet" type="text/css" href="extLib/grid-examples.css" />

    <link rel="stylesheet" type="text/css" href="extLib/shared/examples.css" />

    <link rel="stylesheet" type="text/css" href="extLib/ux/css/RowEditor.css" />

 

    <style type="text/css">

        .icon-user-add {

            background-image: url(extLib/shared/icons/fam/user_add.gif) !important;

        }

        .icon-user-delete {

            background-image: url(extLib/shared/icons/fam/user_delete.gif) !important;

        }       

    </style>

 

    <script type="text/javascript">

      // gelişi güzel isim oluşturma

      (function() {

          //Birkaç meyve adı tanımlaması yaptık

          var meyveler = ['Elma', 'Armut', 'Muz', 'Kavun', 'Karpuz', 'Portakal', 'Nar', 'Mandalina', 'Yeni Dunya', 'Ananas'];

          var firstLen = meyveler.length;

 

          //adından da anlaşılacağı üzere gelişi güzel sayı değerleri oluşturmamıza

          //yarayan bir fonksiyon

          Ext.ux.getRandomInt = function(min, max) {

              return Math.floor(Math.random() * (max - min + 1)) + min;

          }

 

          //yine gelişi güzel bir şekilde meyve isimleri oluşturacağız.

          Ext.ux.generateName = function() {

              var name = meyveler[Ext.ux.getRandomInt(0, firstLen - 1)] + " Meyvesi " + Ext.ux.getRandomInt(0, 10);

              //dataların 'ad' degerlerini identity olarak da kullandığımız için bir kez

              //oluşturduğumuz ismi tekrar oluşturmamalıyız

              if (Ext.ux.generateName.usedNames[name]) {

                  return Ext.ux.generateName();

              }

              Ext.ux.generateName.usedNames[name] = true;

              return name;

          }

          Ext.ux.generateName.usedNames = {};

 

      })();

 

      Ext.onReady(function() {

          var para = 0;

 

          //Urun adlı kayıt şablonunun alan adlarını tanıtalım.

          var Urun = Ext.data.Record.create([{

              name: 'ad',

              type: 'string'

          }, {

              name: 'tip',

              type: 'string'

          }, {

              name: 'uretim',

              type: 'date',

              dateFormat: 'n/j/Y'

          }, {

              name: 'adet',

              type: 'integer'

          }, {

              name: 'fiyat',

              type: 'integer'}]);

              //

              //Kullanıcağımız dataları oluşturalım.

              var genData = function() {

                  var data = [];

                  var s = new Date(2007, 0, 1);

                  var now = new Date(), i = -1;

                  while (s.getTime() < now.getTime()) {

                      var ecount = Ext.ux.getRandomInt(0, 1);

                      for (var i = 0; i < ecount; i++) {

                          var name = Ext.ux.generateName();

                          data.push({

                              uretim: s.clearTime(true).add(Date.DAY, Ext.ux.getRandomInt(0, 27)),

                              ad: name,

                              tip: 'Meyve',

                              adet: Ext.ux.getRandomInt(10, 100),

                              fiyat: Ext.ux.getRandomInt(10, 100)

                          });

                      }

                      s = s.add(Date.MONTH, 1);

                  }

                  return data;

              }

              //

              //Json tipindeki datalarımızı tutacağımız store objemiz

              var store = new Ext.data.GroupingStore({

                  reader: new Ext.data.JsonReader({ fields: Urun }),

                  //datayı nereden alıcagını belirttik.

                  data: genData(),

                  sortInfo: { field: 'uretim', direction: 'ASC' }

              });

 

              //Editor butonlarımızın etiketlerin dilediğimiz gibi değiştirebiliriz

              var editor = new Ext.ux.grid.RowEditor({

                  saveText: 'Kaydet',

                  cancelText: 'Iptal'

              });

 

              //

              //gridimizi yaratalım

              var grid = new Ext.grid.GridPanel({

                  //grid oluştururken 'store' degerini vermeyi unutmayınız.

                  store: store,

                  width: 600,

                  region: 'center',

                  margins: '0 5 5 5',

                  autoExpandColumn: 'ad',

                  plugins: [editor],

                  view: new Ext.grid.GroupingView({

                      markDirty: false

                  }),

                  // 'topbar' daki butonlarımızı oluşturuyoruz.

                  tbar: [{

                      iconCls: 'icon-user-add',

                      text: 'Urun Ekle',

                      handler: function() {

                          var e = new Urun({

                              ad: 'Meyve Adi',

                              tip: 'Meyve',

                              uretim: (new Date()).clearTime(),

                              adet: 1,

                              fiyat: 10

                          });

                          editor.stopEditing();

                          store.insert(0, e);

                          grid.getView().refresh();

                          grid.getSelectionModel().selectRow(0);

                          editor.startEditing(0);

                      }

                  }, {

                      ref: '../removeBtn',

                      iconCls: 'icon-user-delete',

                      text: 'Urun Sil',

                      disabled: true,

                      handler: function() {

                          editor.stopEditing();

                          var s = grid.getSelectionModel().getSelections();

                          for (var i = 0, r; r = s[i]; i++) {

                              store.remove(r);

                          }

                      }

                  }, {

                      ref: '../removeBtn',

                      iconCls: 'icon-user-delete',

                      text: 'Urun Sat',

                      disabled: true,

                      handler: function() {

                          editor.stopEditing();

                          var s = grid.getSelectionModel().getSelections();

                          for (var i = 0, r; r = s[i]; i++) {

                              if (r.data['adet'] == 1) {

                                  para = para + r.data['fiyat'];

                                  store.remove(r);

                                  Ext.MessageBox.alert('Satis', 'Satis Islemi tamamlandi. Urun kalmadi!Suan ' + para + ' kadar paraniz var.');

                              }

                              else {

                                  para = para + r.data['fiyat'];

                                  r.set("adet", r.data['adet'] - 1);

                                  r.commit();

                                  Ext.MessageBox.alert('Satis', 'Satis Islemi tamamlandi. Suan ' + para + ' kadar paraniz var.');

                              }

                          }

                      }

}],

                      //Kolonlarımızı özellestirelim.

                      columns: [

        new Ext.grid.RowNumberer(),

        {

            id: 'ad',

            header: 'Meyve Adi',

            dataIndex: 'ad',

            width: 220,

            sortable: true,

            editor: {

                xtype: 'textfield',

                allowBlank: false

            }

        }, {

            header: 'Tip',

            dataIndex: 'tip',

            width: 150,

            sortable: true,

            editor: {

                xtype: 'textfield',

                blankText: "Bos Birakma!",

                allowBlank: false

            }

        }, {

            xtype: 'datecolumn',

            header: 'Uretim Tarihi',

            dataIndex: 'uretim',

            format: 'm/d/Y',

            width: 100,

            sortable: true,

            groupRenderer: Ext.util.Format.dateRenderer('M y'),

            editor: {

                xtype: 'datefield',

                allowBlank: false,

                blankText: "Bos Birakma!",

                maxValue: (new Date()).format('m/d/Y')

            }

        },

        {

            header: 'Adet',

            dataIndex: 'adet',

            minValue: 1,

            width: 50,

            sortable: true,

            editor: {

                xtype: 'numberfield',

                blankText: "Bos Birakma!",

                allowBlank: false

            }

        },

        {

            header: 'Fiyat',

            dataIndex: 'fiyat',

            minValue: 1,

            width: 50,

            sortable: true,

            editor: {

                xtype: 'numberfield',

                allowBlank: false

            }

}]

                  });

                  //

                  //

                  var layout = new Ext.Panel({

                      title: 'Meyveler',

                      layout: 'border',

                      layoutConfig: {

                          columns: 1

                      },

                      width: 600,

                      height: 600,

                      items: [grid]

                  });

                  layout.render(Ext.getBody());

 

                  grid.getSelectionModel().on('selectionchange', function(sm) {

                      grid.removeBtn.setDisabled(sm.getCount() < 1);

                  });

              });

  </script>

 

    <link rel="stylesheet" type="text/css" href="extLib/resources/css/ext-all.css" />

    <link rel="stylesheet" type="text/css" href="extLib/grid-examples.css" />

    <link rel="stylesheet" type="text/css" href="extLib/shared/examples.css" />

    <link rel="stylesheet" type="text/css" href="extLib/ux/css/RowEditor.css" />

 

 

 

</head>

<body>

    <form id="form1" runat="server">

    <div>

    </div>

    </form>

</body>

</html>

undefined

 

Tüm bu işlemler sonrasında aşağıdaki gibi bir görüntü elde edeceğiz.

 

 

 

Böylece bu makalemizin de sonuna gelmiş olduk. Eğer örnekteki herhangi bir yeri anlamadığınızı düşünüyorsanız bana mail aracılığıyla ulaşabilirsiniz.

 

Serinin devamında sunucu-taraflı data işlemlerine değiniyor olacağız, yani işin içine biraz AJAX girecek.

 

Herkese iyi kodlamalar.


Mehmet Sencer KARADAYI

2008 'den beri MCPD, MCTS ünvanlarını taşıyan yazar, Orta Doğu Teknik Üniversitesi 'nde Bilgisayar Mühendisliği bölümünde eğitimine devam etmektedir.
Bu makaleye ilk yorum yapan siz olun.

Yorumunuz