Ana Sayfa > ASP.NET > “ExtJS, Coolite ne ola ki? ” Yazı Dizisi Vol.2

“ExtJS, Coolite ne ola ki? ” Yazı Dizisi Vol.2

30 Nisan 2010

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ü

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.

   
<!–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>

 

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'}]);

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;

             
}

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' }

             
});

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

           
}

}]

                 
});

Ö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>

 

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.