Angular2’yi Mvc Üzerine Çalıştırma ve Routing, Http Service, Input, Output ve Custom Pipe

Selamlar,

Bugün Asp.Net Mvc üzerinde Angular2 projesi nasıl yaratılır? Angular2’de bir sevisden data nasıl çekilir? Routing nasıl yapılır? Ve son olarak çekilen bu datanın, farklı bir directive’de gösterimi nasıl olur gibi konularını hep beraber inceleyeceğiz. Bu gösterme işini ilgili provider ve @input, @output parametrelerini de kullanarak, nasıl tekrarlanabilir koddan kurtulunabileceğini ve her yerde çalışabilecek farklı directiveleri de yine bu makalede incelemiş olacağız.

Öncelikle yeni bir MVC projesi oluşturulur. Oluşturulacak proje template tipinin makinanızda olmadığı farz edilip, Visual Studio 2015’de Online Project Type sekmesinden angular diye aranıp, “Angular2WebTemplate” seçilir. Ve ilgili Angular2 projesi aşağıdaki gibi oluşturulur.

 

Daha sonra ilgili solution sağ tıklanıp “Controllers” folder’ı eklenir. Ve daha sonra içerisine sağ click ile “Controller” yani boş bir HomeController eklenir. Ayrıca otomatik oluşan Index action’ı sağ tıklanıp, boş bir Index view oluşturulur. Projenin son durumu yandaki gibidir. Dikkat edilir ise “app” klasörü altına, tüm Angular 2 için gerekli yapılar oluşturulmuştur.Burada başlangıç noktamız “app.modules.ts“‘dir.

Ayrıca ilgili tüm paketlerin indirilmesi için, admin ile açılmış bir command propmt’da, oluşturulan projenin folder’ı altına gelinip, “npm install” komutu yazılır. Ayrıca var olan paketlerin son versionlarına yükseltilmesi için, aşağıdaki adresden de görüldüğü gibi “npm install -g npm-check-updates” şeklinde ilgili paket indirilir. Ve “ncu -u” komutu ile tüm paketler son güncel haline getirilir.

npm-check-updates

app.modules.ts’in son hali aşağıdaki gibidir: Aşağıdaki kodlara bakıp aklınız karışmasın, projenin son halini görmektesiniz. Yani yazılmış, bitmiş olan tüm projenin son halidir. Dikkat ederseniz tüm oluşturulan classlar burada importlu olarak tanımlanmıştır.

@NgModule: Angular2 için bir kabuktur. Yani bu kabuk içinde angular ayağa kalkmaktadır.

 

imports:

  • BrowserModule: İle anguların web ortamında çalışacağı tanımlanır. Bildiğiniz gibi Mobilede de çalıştırılabilmektedir.
  • routing: Bir menu mantığının kullanılması ve çeşitli Componentlare gidilebilmesi için tanımlanır.
  • HttpModule: Bir Get, Post yani request, response işlerinin yapılması için tanımlanır.

declarations: Tüm componentlar ve pipe eski adı ile filterlar burada tanımlanır.

bootstrap: Başlangıç component’ı belirlenir. Bu projede “AppComponent”‘dır.

providers: Proje içindeki tüm servisler burada tanımlanır. Bu projede sadece bir service vardır. O da “PersonService”‘dir.

Routing: Yukarıda dikkat ederseniz routing bir dosya içinde tanımlanmıştır: “import { routing } from ‘./app.routing’;”

app.routing.ts: Aşağıda görüldüğü gibi url satırına girilecek key yani adres satırında olacak link “path” kısmında tanımlanmıştır. İlgili url’e göre gidilecek sayfaya ait sınıfın adı “component” tarafında tanımlanmıştır. Gidilecek tüm componentlar yine bu dosya altında import ile tanımlanmıştır. Ayrıca route ve providerlar için de ilgili modulelerin tanımlanması unutulmamalıdır.

AppComponent: Başlangış sayfası aşağıda görülen sınıftır. Index sayfasında selector “<my-app><my-app/>” şeklinde tanımlanmıştır. Ilgili html sayfası “templateUrl” sayesinde belirlenmiştir. styleUrls ile de ilgili sayfada kullanılacak css dosyası yolu gösterilmiştir. Hatırlarsanız templateUrl yerine, bir template yapısı da kullanabilir ve ilgili html’i buraya string olarak tanımlayabilirdik. Son olarak sayfanın title’ı ilgili sınıf altında tanımlanmıştır.

app.component.template.html: Aşağıda görüldüğü gibi bir Menu ve benim de başta bunun nerden geldiğini anlamlandıramadığım, “@angular/core”‘dan gelen “<router-outlet></router-outlet>” directive’i konulmuştur.

Not: Dikkat edilir ise, artık ilgili classlarda Directiveler tanımlanmamaktadır.

HomeController/Index: İlgili action’da hiçbir kod tanımlı değildir.

Views/Home/Index: Aşağıda görüldüğü gibi ilgili Angular2 templatin’den gelen script dosyaları ve AppComponent selector’ü olan “<my-app><my-app/>” sayfa içerisinde tanımlanmıştır.

Bu makalede üzerinde çalışılacak sayfa “ListPersonComponent” olucaktır. Öncelikle ilgili kişilerin çekileceği bir “person.json” dosyası oluşturulur.

person.json: Aşağıda görüldüğü gibi “id” ve “name” alanlarının bulunduğu bir data kümesi vardır.  Amaç bu öğrencileri bir ekranda listelemek ve istenen kişinin seçilebilmesidir.

Şimdi öncelikle bir servis yazalım. İlgili Json dosyasını okusun ve bir property olarak dönsün.

PersonService: Aşağıda görüldüğü gibi ilgili provider’ın, başka bir sınıfın constructer’ında çağrılıp kullanılabilmesi için “@Injectable()” olarak tanımlanması gerekmektedir. Ayrıca “http.request” yapılabilmesi için ilgili kütüpahanelerin sayfanın başında import edilmesi gerekmektedir.  “People” adında bir property tanımlanmıştır. İlgili request işleminden sonra, “subscribe()” methodu içinde lambda kullanılarak dönen response.json() “People” property’sine atanmaktadır.  Ayrıca hata durumu “err=>console.error(err)” örnek amaçlı console’a yazılmaktadır. İlgili provider’ın kullanılabilmesi için makalenin başında da anlatıldığı gibi ilgili tüm fileların “app.modules.ts“‘de tanımlanması gerekmektedir.

Şimdi gelin ilgili servisi, yaratılma anında constructer’ında alıp, listeleme işlemi yapacak sayfayı tanımlayalım:

ListPersonComponent(Part 1): Aşağıda görüldüğü gibi yukarıda tanımlanan provider yani services modules’de tanımlandığı için, bir daha burada provider olarak tanımlanmamış sadece dosya yolu sayfanın tepesinde belirtilmiştir. “ModuleWithProviders” librarysi bu yüzden kullanılmıştır. Aşağıdaki component’de “Service” değişkenine constructer’dan dönen “@Injectable()” “PersonService“‘ı atanmıştır.

Önemli Not: Constructer’da service yerine, ilgili service’e ait json “People” propertysi doğrudan çekilmeye çalışıldığında, çekilmeye çalışılan bu datanın gelmediği, “null” döndüğü görülmüştür. Bunun için öncelikle service nesnesinin kendisi çekilmiştir. Nedenine gelince, constructer işlemi sırasında ilgili datanın dönmesi beklenmemektedir. Bu sorun ilgili servisden data, promises ile asenkron olarak çekilir ise çözülme ihtimali yüksektir. Aşağıda görüldüğü gibi henüz bir sıralama işlemi yapılmamıştır. Ben bu işlem için bir başka directive kullanmayı doğru buldum. Böylece ilgili sıralama, projenin başka yerlerinde de kullanılabilecektir.

PersonComponent: İlgili listelemenin yapılacağı directive aşağıdaki gibidir. Burada @Input ve @Output kullanılmıştır. @Input: Servisden dönen herbir person nesnesinine ait ismi almaktadır. @Output: Bu list directivine dışardan bağlanan eventi tetiklemek için kullanılır. Yani bu nesnenin kullanıldığı sayfa üzerindeki event’i tetikler. Parametre olarak dışarı, kendisine atanan bu “name” değişkenini gönderir. Selector: “<list></list>“‘dir. Template olarak bir <span> içine ilgili isim ve yanına görüşme button’u konulmuştur.

Not: Button’un tıklanma eventinde “getChat()” methodu çağrılmış ve bu method sırasında yeni yaratılan “EventEmitter” ile dışarıda kendisine (talk) eventi ile bağlı method, tıklanan isim ile birlikte çağrılmıştır. Kısaca dışarı bir iletişim söz konusudur. (@Output)

Önemli bir nokta da aşağaıda görüldüğü gibi ilgili isimlerin baş harfleri büyük yazılmıştır. Bunu custom Pipe ile yapmaktayız. “{{name | capital}}” burada yazılan capital eski adı ile bir filter yeni adı ile Angular2’de bir pipedır. Amacı ismi boşluklarına göre bölmek. Ve herbir kelimenin baş harfini büyütmektir. Bu örnekteki sözkonusu durum adın ve soyadın büyük harf ile yazılmasıdır.

CapitalPipe: Yukarıda bahsedilen pipe aşağıdaki gibi kodlanmıştır. Görüldüğü gibi regex ile boşluklarına göre ayrılan herbir kelimenin ilk harfi büyük harf ile değiştirilmiş ve geri dönülmüştür.

ListPersonComponent(Full): Aşağıda görüldüğü gibi “<List>” directive’i “Service.People“‘daki eleman sayısı kadar “*ngFor” ile  dönülmüş ve “[name]” @Input elemanına “person.name” değeri atanmıştır. Ayrıca (talk)@Output EventEmitter’a “chatPerson()” methodu bağlanımıştır. İlgili method’da “doneList[]” dizisine tıklanan isim ve state durumu “completed” şeklinde eklenmektedir. “.completed” style’ı aşağıda görüldüğü gibi tanımlanmıştır. Kısaca ilgili isimin üstü çizilmektedir. Yani görüşüldü anlamına gelmektedir.

En altta ise yani “Kayıt Yaptırılan Öğrenciler” kısmında, ilgili listeye eklenen, yani görüşülen isimler “<li *ngFor” ile dönülüp listelenmektedir. İlgili listenin içine basılan span’a “<span [ngClass=’person.state’]” şeklinde ilgili “person.state” değeri sitil olarak atanmıştır. Ayrıca ilgili span’ın yanına konan “Kaldır” button’unun “(click)” event’ine “removeFromList()” methodu bağlanmıştır. İlgili button tıklanınca “doneList[]” içerisinden, ilgili öğrenci çıkartılar ve böylece tıklanan kişi kayıt yaptıran öğrenciler listesinden kaldırılmış olunur.

Bu makalede önce Angular2’yi Mvc bir projede beraberce nasıl kullanacağımızı inceledik. Daha sonra Angular2’de Routing konusuna ve ilgili paketleri neden app.modules’e eklememiz gerektiğini gördük. Daha sonra “Json” bir dosyadan nasıl data okunur, okunan dosya başka bir directive’de @Input kullanılarak listelenir. Directive’den dışarı doğru @Output kullanılarak nasıl bir event tetiklenir gördük. Son olarak bir html element’in class’ına nasıl model ile atama yapacağımızı gördük. Ve böylece bu makalenin de sonuna geldik :)

Yeni bir makalede görüşmek üzere hoşçakalın.

Kaynak : https://github.com/Drag13/MvcWithAngular2/tree/master/WebProject

Herkes Görsün:

Bunlar da hoşunuza gidebilir...

21 Cevaplar

  1. cengiz yektaş dedi ki:

    Bora Bey
    HomeController da olan bir veriyi nasıl alacağız ?
    httpGet yaparak servis veriyi controller üzerinden alabiliyormu ?

  2. cengiz yektaş dedi ki:

    Bora Bey
    HomeController da olan bir veriyi nasıl alacağız ?
    httpGet yaparak servis veriyi controller üzerinden alabiliyormu ?
    indirdiğimiz template de sanki en dışdaki index.html çalışıyor index.cshtml calışmıyor sanki ?

    • borsoft dedi ki:

      Selamlar,
      Bende uygulama Mvc şeklinde yani Index.cshtml sayfası ile start oluyor. Yani kısaca bir sorun olmaması lazım. Olmadı bendeki projeyi GitHub’a koyup paylaşırım.
      HomeController’daki veriyi Model ile ViewBag,ViewData ile veya clientSide taraftan AjaxPost ile alabilirsiniz. Daha farklı bir sürü yol var ama ilk etapta bunlar yeterli gibi..

      İyi çalışmalar.

  3. Ömrüm Baki Temiz dedi ki:

    Visual Studio 2017 için kullandığınız proje template tipi mevcut değil galiba. Dışarıdan elle indirdiğimde ise uyumsuz olduğu için yüklenmiyor. Acaba VS 17 için nasıl bir çözüm üretebiliriz?

    • borsoft dedi ki:

      Sanırım şuan Visual Studio 2017 için yok. Nedeni sanırım IDE’nin halen RC durumunda olmasından kaynaklanıyor.

      İyi çalışmalar.

  4. süleyman dedi ki:

    İyi günler bora bey.
    Daha önce bir yazınızda sormuştum tekrar olacak.
    Yaptığınız örneğinizde ilgili adrese( örnek olarak /listperson) direk tarayıcıdan set ederek girdiğimizde listeleme sayfası çıkıyormu?

  5. süleyman dedi ki:

    Teşekkürler.
    izniniz ile bir şey daha sormak istiyorum.
    RouterModule.forRoot(appRoutes); kodunda ki forRoot ve aynı nesnenin forChild fonksiyonları tam olarak ne işlevi yerine gertiriyor ?
    Orada forChild fonksiyonunu hangi durumlarda kullanmalıyız?

    • borsoft dedi ki:

      Selam Süleyman,

      Öncelikle sorun çok güzel:) Soru gibi soru :)

      Router yapısında bir başlangıç noktan olmak zorunda. İşte bu başlangıçtaki route yollarını forRoot ile tanımlıyorsun. Yani proje ilk başlarken bu maim moduleler yükleniyor. Bir de başta yüklenmeyen submoduleler, lazy load moduler gibi yapılar var. İşte bunları da routing için register etmek istediğinde forChild’ı kullanıyorsun. Yoksa bu tip yapıları forRootda tanımlasan başlangıçta direk hatayı alırsın.

      Umarım açıklayıcı olmuştur.
      İyi çalışmalar.

  6. Emre dedi ki:

    Hocam merhabalr , angular2webtemplate oluşturunca bu sizin attiginiz yapiya ulasamadim

    Sadece angular2 nin klasotleri geldi mvc ye ait olanlar gelmedi asp .net core olmadan olmuyor mu .
    Teşekkür ederim

    • borsoft dedi ki:

      Selam Emre,

      Eğere makaleyi okursan, ilgili template yüklendiği zaman Mvc ile alakalı hiçbir dosyanın oluşmadığı sadece ilgili kütüpahanelerin yüklendiğini görebilirsin.
      Bunu da makalede geçen Daha sonra ilgili solution sağ tıklanıp “Controllers” folder’ı eklenir. Ve daha sonra içerisine sağ click ile “Controller” yani boş bir HomeController eklenir. Ayrıca otomatik oluşan Index action’ı sağ tıklanıp, boş bir Index view oluşturulur.” çümlesinden çıkarabilirsin.

      Bu ara da Asp.Net Core, bu makalede uzaktan yakından bahsedilmemiştir.

      İyi çalışmalar.

  7. Harun dedi ki:

    routing işlemi bile angularjs ile yapılınca mvc projesi içinde kullanılmasında çokta bi önemi olmuyormuş gibi anladım.

    web api + html angularjs uygulama yapılsa daha iyi sanki, en azından derleme işlemini bi miktar aradan çıkarmış oluruz diye düşündüm.

  8. Emre dedi ki:

    http://prntscr.com/e7uha1
    http://prntscr.com/e7uhfh
    http://prntscr.com/e7uhq1
    http://prntscr.com/e7uhvq
    Hocam angular2 ile bir web apiden liste halinde gönderdiğim veriyi çekebiliyorum ancak bu şekilde id ye göre olunca undefined diyor nerde hata yapoyrum teşekkür ederim

    • borsoft dedi ki:

      Selam Emre,

      GetMacDetay()’ı bir Button’a tıklanınca çekiyorsan sync yapıp bir çek:) Eğer Constructer’da çağrıyor isen çağırma ve Propery ile çağır.
      Veya Delay(1000) koyup bir dene.

      İyi çalışmalar.

  9. oktay dedi ki:

    selamlar, örnekteki uygulamanın projesini github’ta paylaşabilir misiniz?

  10. Misafir dedi ki:

    Makale için teşekkürler.

    TypeScript for Visual Studio 2015 ‘in kurulması gerektiğinden bahsetmemişsiniz hocam. Bu olmayınca derleyince hatalar oluşuyor.

  11. Emre KARA dedi ki:

    Teşekkürler Hocam , Şuanda varolan bir asp.net mvc projemize angular4 eklemek istiyoruz nasıl bir yol izlememiz gerekiyor

borsoft için bir cevap yazın Cevabı iptal et

E-posta hesabınız yayımlanmayacak.