Tutorial Langkah-demi-Langkah untuk Aplikasi AngularJS Pertama Anda

Diterbitkan: 2022-03-11
AngularJS telah berkembang dan menjadi lebih baik. Sekarang disebut Angular, itu sepenuhnya ditulis ulang menuju alur kerja pengembangan baru. Lihat tutorial Angular 5 baru kami, dan bahkan tutorial full-stack Angular 6 yang lebih baru, yang menampilkan Material dan Firebase.

Apa itu AngularJS?

AngularJS adalah kerangka kerja JavaScript MVC yang dikembangkan oleh Google yang memungkinkan Anda membangun aplikasi front-end yang terstruktur dengan baik, mudah diuji, dan dapat dipelihara.

Dan Mengapa Saya Harus Menggunakannya?

Jika Anda belum mencoba AngularJS, Anda ketinggalan. Kerangka kerja ini terdiri dari seperangkat alat yang terintegrasi erat yang akan membantu Anda membangun aplikasi sisi klien yang kaya dan terstruktur dengan baik secara modular—dengan lebih sedikit kode dan lebih banyak fleksibilitas.

AngularJS memperluas HTML dengan menyediakan arahan yang menambahkan fungsionalitas ke markup Anda dan memungkinkan Anda membuat template dinamis yang kuat. Anda juga dapat membuat arahan Anda sendiri, menyusun komponen yang dapat digunakan kembali yang memenuhi kebutuhan Anda dan mengabstraksikan semua logika manipulasi DOM.

Ini juga mengimplementasikan pengikatan data dua arah, menghubungkan HTML (tampilan) Anda ke objek (model) JavaScript Anda dengan mulus. Secara sederhana, ini berarti bahwa setiap pembaruan pada model Anda akan segera tercermin dalam tampilan Anda tanpa perlu manipulasi DOM atau penanganan peristiwa (misalnya, dengan jQuery).

Angular menyediakan layanan di atas XHR yang secara dramatis menyederhanakan kode Anda dan memungkinkan Anda untuk mengabstraksi panggilan API menjadi layanan yang dapat digunakan kembali. Dengan itu, Anda dapat memindahkan model dan logika bisnis Anda ke front-end dan membangun aplikasi web agnostik back-end.

Terakhir, saya menyukai Angular karena fleksibilitasnya terkait komunikasi server. Seperti kebanyakan kerangka kerja JavaScript MVC, ini memungkinkan Anda bekerja dengan teknologi sisi server apa pun asalkan dapat melayani aplikasi Anda melalui RESTful web API. Tetapi Angular juga menyediakan layanan di atas XHR yang secara dramatis menyederhanakan kode Anda dan memungkinkan Anda untuk mengabstraksi panggilan API menjadi layanan yang dapat digunakan kembali. Hasilnya, Anda dapat memindahkan model dan logika bisnis Anda ke front-end dan membangun aplikasi web agnostik back-end. Dalam posting ini, kita akan melakukan hal itu, selangkah demi selangkah.

Jadi, Di Mana Saya Mulai?

Pertama, mari kita putuskan sifat aplikasi yang ingin kita buat. Dalam panduan ini, kami memilih untuk tidak menghabiskan terlalu banyak waktu di back-end, jadi kami akan menulis sesuatu berdasarkan data yang mudah didapat di Internet—seperti aplikasi feed olahraga!

Karena saya adalah penggemar berat balap motor dan Formula 1, saya akan menggunakan layanan API autosport untuk bertindak sebagai back-end kami. Untungnya, orang-orang di Ergast cukup baik untuk menyediakan API motorsport gratis yang akan sempurna untuk kita.

Untuk mengetahui apa yang akan kami buat, lihat demo langsungnya. Untuk mempercantik demo dan memamerkan beberapa templating Angular, saya menerapkan tema Bootstrap dari WrapBootstrap, tetapi karena artikel ini bukan tentang CSS, saya hanya akan mengabstraksikannya dari contoh dan mengabaikannya.

Memulai Tutorial

Mari kita mulai aplikasi contoh kita dengan beberapa boilerplate. Saya merekomendasikan proyek angular-seed karena tidak hanya memberi Anda kerangka yang bagus untuk bootstrap, tetapi juga menetapkan dasar untuk pengujian unit dengan Karma dan Jasmine (kami tidak akan melakukan pengujian apa pun dalam demo ini, jadi kami hanya akan kesampingkan hal itu untuk saat ini; lihat Bagian 2 dari tutorial ini untuk info lebih lanjut tentang menyiapkan proyek Anda untuk pengujian unit dan ujung ke ujung).

EDIT (Mei 2014): Sejak saya menulis tutorial ini, proyek angular-seed telah mengalami beberapa perubahan besar (termasuk penambahan Bower sebagai manajer paket). Jika Anda ragu tentang cara menerapkan proyek, lihat sekilas bagian pertama dari panduan referensi mereka. Di Bagian 2 dari tutorial ini, Bower, di antara alat-alat lainnya, dibahas secara lebih rinci.

Oke, sekarang setelah kita mengkloning repositori dan menginstal dependensi, kerangka aplikasi kita akan terlihat seperti ini:

tutorial angularjs - mulai dengan kerangkanya

Sekarang kita bisa mulai coding. Saat kami mencoba membuat umpan olahraga untuk kejuaraan balap, mari kita mulai dengan tampilan yang paling relevan: tabel kejuaraan .

meja kejuaraan

Mengingat bahwa kita sudah memiliki daftar driver yang ditentukan dalam lingkup kita (bertahanlah – kita akan sampai di sana), dan mengabaikan CSS apa pun (agar mudah dibaca), HTML kita mungkin terlihat seperti:

 <body ng-app="F1FeederApp" ng-controller="driversController"> <table> <thead> <tr><th colspan="4">Drivers Championship Standings</th></tr> </thead> <tbody> <tr ng-repeat="driver in driversList"> <td>{{$index + 1}}</td> <td> <img src="img/flags/{{driver.Driver.nationality}}.png" /> {{driver.Driver.givenName}}&nbsp;{{driver.Driver.familyName}} </td> <td>{{driver.Constructors[0].name}}</td> <td>{{driver.points}}</td> </tr> </tbody> </table> </body>

Hal pertama yang akan Anda perhatikan dalam template ini adalah penggunaan ekspresi (“{{“ dan “}}”) untuk mengembalikan nilai variabel. Dalam pengembangan AngularJS, ekspresi memungkinkan Anda untuk menjalankan beberapa komputasi untuk mengembalikan nilai yang diinginkan. Beberapa ekspresi yang valid adalah:

  • {{ 1 + 1 }}
  • {{ 946757880 | date }}
  • {{ user.name }}

Secara efektif, ekspresi adalah cuplikan seperti JavaScript. Tetapi meskipun sangat kuat, Anda tidak boleh menggunakan ekspresi untuk mengimplementasikan logika tingkat yang lebih tinggi. Untuk itu, kami menggunakan arahan.

Memahami Arahan Dasar

Hal kedua yang akan Anda perhatikan adalah keberadaan ng-attributes , yang tidak akan Anda lihat di markup biasa. Itu adalah arahan.

Pada tingkat tinggi, arahan adalah penanda (seperti atribut, tag, dan nama kelas) yang memberi tahu AngularJS untuk melampirkan perilaku tertentu ke elemen DOM (atau mengubahnya, menggantinya, dll.). Mari kita lihat yang sudah kita lihat:

  • Arahan ng-app bertanggung jawab untuk mem-bootstrap aplikasi Anda dengan menentukan cakupannya. Di AngularJS, Anda dapat memiliki beberapa aplikasi dalam halaman yang sama, jadi arahan ini menentukan di mana setiap aplikasi berbeda dimulai dan diakhiri.

  • Arahan ng-controller menentukan pengontrol mana yang akan bertanggung jawab atas tampilan Anda. Dalam hal ini, kami menunjukkan driversController , yang akan memberikan daftar driver kami ( driversList ).

  • Direktif ng-repeat adalah salah satu yang paling umum digunakan dan berfungsi untuk menentukan cakupan template Anda saat mengulang koleksi. Dalam contoh di atas, ini mereplikasi baris dalam tabel untuk setiap driver di driversList .

Menambahkan Pengontrol

Tentu saja, tidak ada gunanya tampilan kita tanpa pengontrol. Mari tambahkan driversController ke controllers.js kita:

 angular.module('F1FeederApp.controllers', []). controller('driversController', function($scope) { $scope.driversList = [ { Driver: { givenName: 'Sebastian', familyName: 'Vettel' }, points: 322, nationality: "German", Constructors: [ {name: "Red Bull"} ] }, { Driver: { givenName: 'Fernando', familyName: 'Alonso' }, points: 207, nationality: "Spanish", Constructors: [ {name: "Ferrari"} ] } ]; });

Anda mungkin telah memperhatikan variabel $scope yang kita lewati sebagai parameter ke controller. Variabel $scope seharusnya menautkan pengontrol dan tampilan Anda. Secara khusus, ini menampung semua data yang akan digunakan dalam template Anda. Apa pun yang Anda tambahkan ke dalamnya (seperti daftar driversList dalam contoh di atas) akan langsung dapat diakses di tampilan Anda. Untuk saat ini, mari kita bekerja dengan array data dummy (statis), yang akan kita ganti nanti dengan layanan API kita.

Sekarang, tambahkan ini ke app.js:

 angular.module('F1FeederApp', [ 'F1FeederApp.controllers' ]);

Dengan baris kode ini, kami sebenarnya menginisialisasi aplikasi kami dan mendaftarkan modul yang bergantung padanya. Kami akan kembali ke file itu ( app.js ) nanti.

Sekarang, mari kita gabungkan semuanya di index.html :

 <!DOCTYPE html> <html> <head> <title>F-1 Feeder</title> </head> <body ng-app="F1FeederApp" ng-controller="driversController"> <table> <thead> <tr><th colspan="4">Drivers Championship Standings</th></tr> </thead> <tbody> <tr ng-repeat="driver in driversList"> <td>{{$index + 1}}</td> <td> <img src="img/flags/{{driver.Driver.nationality}}.png" /> {{driver.Driver.givenName}}&nbsp;{{driver.Driver.familyName}} </td> <td>{{driver.Constructors[0].name}}</td> <td>{{driver.points}}</td> </tr> </tbody> </table> <script src="bower_components/angular/angular.js"></script> <script src="bower_components/angular-route/angular-route.js"></script> <script src="js/app.js"></script> <script src="js/services.js"></script> <script src="js/controllers.js"></script> </body> </html>

Modulo kesalahan kecil, Anda sekarang dapat mem-boot aplikasi Anda dan memeriksa daftar driver (statis) Anda.

Catatan: Jika Anda memerlukan bantuan untuk men-debug aplikasi Anda dan memvisualisasikan model dan cakupan Anda di dalam browser, saya sarankan untuk melihat plugin Batarang yang mengagumkan untuk Chrome.

Memuat Data Dari Server

Karena kita sudah tahu cara menampilkan data pengontrol dalam tampilan kita, inilah saatnya untuk benar-benar mengambil data langsung dari server RESTful.

Untuk memfasilitasi komunikasi dengan server HTTP, AngularJS menyediakan layanan $http dan $resource . Yang pertama hanyalah lapisan di atas XMLHttpRequest atau JSONP, sedangkan yang kedua menyediakan tingkat abstraksi yang lebih tinggi. Kami akan menggunakan $http .

Untuk mengabstraksi panggilan API server kita dari controller, mari buat layanan kustom kita sendiri yang akan mengambil data kita dan bertindak sebagai pembungkus $http dengan menambahkan ini ke services.js kita :

 angular.module('F1FeederApp.services', []). factory('ergastAPIservice', function($http) { var ergastAPI = {}; ergastAPI.getDrivers = function() { return $http({ method: 'JSONP', url: 'http://ergast.com/api/f1/2013/driverStandings.json?callback=JSON_CALLBACK' }); } return ergastAPI; });

Dengan dua baris pertama, kita membuat modul baru ( F1FeederApp.services ) dan mendaftarkan layanan di dalam modul itu ( ergastAPIservice ). Perhatikan bahwa kami meneruskan $http sebagai parameter ke layanan itu. Ini memberi tahu mesin injeksi ketergantungan Angular bahwa layanan baru kami memerlukan (atau bergantung pada ) layanan $http .

Dengan cara yang sama, kita perlu memberi tahu Angular untuk memasukkan modul baru kita ke dalam aplikasi kita. Mari kita daftarkan dengan app.js , ganti kode kita yang ada dengan:

 angular.module('F1FeederApp', [ 'F1FeederApp.controllers', 'F1FeederApp.services' ]);

Sekarang, yang perlu kita lakukan hanyalah sedikit men-tweak controller.js kita, memasukkan ergastAPIservice sebagai dependensi, dan kita akan baik-baik saja:

 angular.module('F1FeederApp.controllers', []). controller('driversController', function($scope, ergastAPIservice) { $scope.nameFilter = null; $scope.driversList = []; ergastAPIservice.getDrivers().success(function (response) { //Dig into the responde to get the relevant data $scope.driversList = response.MRData.StandingsTable.StandingsLists[0].DriverStandings; }); });

Sekarang muat ulang aplikasi dan lihat hasilnya. Perhatikan bahwa kami tidak membuat perubahan apa pun pada template kami, tetapi kami menambahkan variabel nameFilter ke cakupan kami. Mari kita gunakan variabel itu.

Filter

Besar! Kami memiliki pengontrol fungsional. Tapi itu hanya menampilkan daftar driver. Mari tambahkan beberapa fungsionalitas dengan menerapkan input pencarian teks sederhana yang akan menyaring daftar kita. Mari tambahkan baris berikut ke index.html kita, tepat di bawah tag <body> :

 <input type="text" ng-model="nameFilter" placeholder="Search..."/>

Kami sekarang menggunakan direktif ng-model . Arahan ini mengikat bidang teks kita ke variabel $scope.nameFilter dan memastikan bahwa nilainya selalu up-to-date dengan nilai input. Sekarang, mari kunjungi index.html sekali lagi dan buat sedikit penyesuaian pada baris yang berisi direktif ng-repeat :

 <tr ng-repeat="driver in driversList | filter: nameFilter">

Baris ini memberitahu ng-repeat bahwa, sebelum mengeluarkan data, array driversList harus difilter oleh nilai yang disimpan di nameFilter .

Pada titik ini, pengikatan data dua arah dimulai: setiap kali nilai dimasukkan di bidang pencarian, Angular segera memastikan bahwa $scope.nameFilter yang kita kaitkan dengannya diperbarui dengan nilai baru. Karena pengikatan bekerja dua arah, saat nilai nameFilter diperbarui, arahan kedua yang terkait dengannya (yaitu, ng-repeat ) juga mendapatkan nilai baru dan tampilan segera diperbarui.

Muat ulang aplikasi dan periksa bilah pencarian.

bilah pencarian aplikasi

Perhatikan bahwa filter ini akan mencari kata kunci pada semua atribut model, termasuk yang tidak digunakan. Katakanlah kita hanya ingin memfilter berdasarkan Driver.givenName dan Driver.familyName : Pertama, kita tambahkan ke driversController , tepat di bawah $scope.driversList = []; garis:

 $scope.searchFilter = function (driver) { var keyword = new RegExp($scope.nameFilter, 'i'); return !$scope.nameFilter || keyword.test(driver.Driver.givenName) || keyword.test(driver.Driver.familyName); };

Sekarang, kembali ke index.html , kami memperbarui baris yang berisi direktif ng-repeat :

 <tr ng-repeat="driver in driversList | filter: searchFilter">

Muat ulang aplikasi sekali lagi dan sekarang kami memiliki pencarian berdasarkan nama.

Rute

Tujuan kami selanjutnya adalah membuat halaman detail driver yang memungkinkan kami mengklik setiap driver dan melihat detail kariernya.

Pertama, mari sertakan layanan $routeProvider (dalam app.js ) yang akan membantu kita menangani berbagai rute aplikasi ini . Kemudian, kami akan menambahkan dua rute seperti itu: satu untuk tabel kejuaraan dan satu lagi untuk detail pengemudi. Inilah app.js baru kami:

 angular.module('F1FeederApp', [ 'F1FeederApp.services', 'F1FeederApp.controllers', 'ngRoute' ]). config(['$routeProvider', function($routeProvider) { $routeProvider. when("/drivers", {templateUrl: "partials/drivers.html", controller: "driversController"}). when("/drivers/:id", {templateUrl: "partials/driver.html", controller: "driverController"}). otherwise({redirectTo: '/drivers'}); }]);

Dengan perubahan itu, menavigasi ke http://domain/#/drivers akan memuat driversController dan mencari tampilan parsial untuk dirender di partials/drivers.html . Tapi tunggu! Kami belum memiliki pandangan parsial, kan? Kita harus membuatnya juga.

Tampilan Sebagian

AngularJS akan memungkinkan Anda untuk mengikat rute Anda ke pengontrol dan tampilan tertentu.

Tapi pertama-tama, kita perlu memberi tahu Angular di mana harus merender sebagian tampilan ini. Untuk itu, kita akan menggunakan direktif ng-view , memodifikasi index.html kita untuk mencerminkan yang berikut:

 <!DOCTYPE html> <html> <head> <title>F-1 Feeder</title> </head> <body ng-app="F1FeederApp"> <ng-view></ng-view> <script src="bower_components/angular/angular.js"></script> <script src="bower_components/angular-route/angular-route.js"></script> <script src="js/app.js"></script> <script src="js/services.js"></script> <script src="js/controllers.js"></script> </body> </html>

Sekarang, setiap kali kita menavigasi melalui rute aplikasi kita, Angular akan memuat tampilan terkait dan merendernya sebagai ganti <ng-view> . Yang perlu kita lakukan adalah membuat file bernama partials/drivers.html dan meletakkan HTML tabel kejuaraan kita di sana. Kami juga akan menggunakan kesempatan ini untuk menautkan nama pengemudi ke rute detail pengemudi kami:

 <input type="text" ng-model="nameFilter" placeholder="Search..."/> <table> <thead> <tr><th colspan="4">Drivers Championship Standings</th></tr> </thead> <tbody> <tr ng-repeat="driver in driversList | filter: searchFilter"> <td>{{$index + 1}}</td> <td> <img src="img/flags/{{driver.Driver.nationality}}.png" /> <a href="#/drivers/{{driver.Driver.driverId}}"> {{driver.Driver.givenName}}&nbsp;{{driver.Driver.familyName}} </a> </td> <td>{{driver.Constructors[0].name}}</td> <td>{{driver.points}}</td> </tr> </tbody> </table>

Terakhir, mari putuskan apa yang ingin kita tampilkan di halaman detail. Bagaimana ringkasan semua fakta yang relevan tentang pengemudi (misalnya, kelahiran, kebangsaan) bersama dengan tabel yang berisi hasil terbarunya? Untuk melakukan itu, kami menambahkan ke services.js :

 angular.module('F1FeederApp.services', []) .factory('ergastAPIservice', function($http) { var ergastAPI = {}; ergastAPI.getDrivers = function() { return $http({ method: 'JSONP', url: 'http://ergast.com/api/f1/2013/driverStandings.json?callback=JSON_CALLBACK' }); } ergastAPI.getDriverDetails = function(id) { return $http({ method: 'JSONP', url: 'http://ergast.com/api/f1/2013/drivers/'+ id +'/driverStandings.json?callback=JSON_CALLBACK' }); } ergastAPI.getDriverRaces = function(id) { return $http({ method: 'JSONP', url: 'http://ergast.com/api/f1/2013/drivers/'+ id +'/results.json?callback=JSON_CALLBACK' }); } return ergastAPI; });

Kali ini, kami memberikan ID pengemudi ke layanan sehingga kami mengambil informasi yang relevan hanya untuk pengemudi tertentu. Sekarang, kita memodifikasi controllers.js :

 angular.module('F1FeederApp.controllers', []). /* Drivers controller */ controller('driversController', function($scope, ergastAPIservice) { $scope.nameFilter = null; $scope.driversList = []; $scope.searchFilter = function (driver) { var re = new RegExp($scope.nameFilter, 'i'); return !$scope.nameFilter || re.test(driver.Driver.givenName) || re.test(driver.Driver.familyName); }; ergastAPIservice.getDrivers().success(function (response) { //Digging into the response to get the relevant data $scope.driversList = response.MRData.StandingsTable.StandingsLists[0].DriverStandings; }); }). /* Driver controller */ controller('driverController', function($scope, $routeParams, ergastAPIservice) { $scope.id = $routeParams.id; $scope.races = []; $scope.driver = null; ergastAPIservice.getDriverDetails($scope.id).success(function (response) { $scope.driver = response.MRData.StandingsTable.StandingsLists[0].DriverStandings[0]; }); ergastAPIservice.getDriverRaces($scope.id).success(function (response) { $scope.races = response.MRData.RaceTable.Races; }); });

Hal penting yang perlu diperhatikan di sini adalah bahwa kita baru saja menyuntikkan layanan $routeParams ke pengontrol driver. Layanan ini akan memungkinkan kami untuk mengakses parameter URL kami (untuk :id , dalam hal ini) menggunakan $routeParams.id .

Sekarang kami memiliki data kami dalam ruang lingkup, kami hanya membutuhkan tampilan sebagian yang tersisa. Mari buat file bernama partials/driver.html dan tambahkan:

 <section> <a href="./#/drivers"><- Back to drivers list</a> <nav class="main-nav"> <div class="driver-picture"> <div class="avatar"> <img ng-show="driver" src="img/drivers/{{driver.Driver.driverId}}.png" /> <img ng-show="driver" src="img/flags/{{driver.Driver.nationality}}.png" /><br/> {{driver.Driver.givenName}} {{driver.Driver.familyName}} </div> </div> <div class="driver-status"> Country: {{driver.Driver.nationality}} <br/> Team: {{driver.Constructors[0].name}}<br/> Birth: {{driver.Driver.dateOfBirth}}<br/> <a href="{{driver.Driver.url}}" target="_blank">Biography</a> </div> </nav> <div class="main-content"> <table class="result-table"> <thead> <tr><th colspan="5">Formula 1 2013 Results</th></tr> </thead> <tbody> <tr> <td>Round</td> <td>Grand Prix</td> <td>Team</td> <td>Grid</td> <td>Race</td> </tr> <tr ng-repeat="race in races"> <td>{{race.round}}</td> <td><img src="img/flags/{{race.Circuit.Location.country}}.png" />{{race.raceName}}</td> <td>{{race.Results[0].Constructor.name}}</td> <td>{{race.Results[0].grid}}</td> <td>{{race.Results[0].position}}</td> </tr> </tbody> </table> </div> </section>

Perhatikan bahwa kita sekarang menggunakan direktif ng-show dengan baik. Arahan ini hanya akan menampilkan elemen HTML jika ekspresi yang diberikan adalah true (yaitu, bukan false , atau null ). Dalam hal ini, avatar hanya akan muncul setelah objek driver dimuat ke dalam ruang lingkup oleh pengontrol.

Sentuhan Akhir

Tambahkan banyak CSS dan render halaman Anda. Anda harus berakhir dengan sesuatu seperti ini:

halaman yang dirender dengan CSS

Anda sekarang siap untuk menjalankan aplikasi Anda dan memastikan kedua rute berfungsi seperti yang diinginkan. Anda juga dapat menambahkan menu statis ke index.html untuk meningkatkan kemampuan navigasi pengguna. Kemungkinannya tidak terbatas.

EDIT (Mei 2014): Saya telah menerima banyak permintaan untuk versi yang dapat diunduh dari kode yang kami buat dalam tutorial ini. Karena itu saya memutuskan untuk merilisnya di sini (dihapus dari CSS apa pun). Namun, saya sangat tidak menyarankan untuk mengunduhnya, karena panduan ini berisi setiap langkah yang Anda perlukan untuk membuat aplikasi yang sama dengan tangan Anda sendiri, yang akan menjadi latihan belajar yang jauh lebih berguna dan efektif.

Kesimpulan

Pada titik ini dalam tutorial, kami telah membahas semua yang Anda perlukan untuk menulis aplikasi sederhana (seperti pengumpan Formula 1). Setiap halaman yang tersisa dalam demo langsung (misalnya, tabel kejuaraan konstruktor, detail tim, kalender) memiliki struktur dan konsep dasar yang sama dengan yang telah kami ulas di sini.

Terakhir, perlu diingat bahwa Angular adalah kerangka kerja yang sangat kuat dan kami hampir tidak menyentuh permukaan dalam hal semua yang ditawarkannya. Di Bagian 2 dari tutorial ini, kami akan memberikan contoh mengapa Angular menonjol di antara kerangka kerja MVC front-end peer-nya: testability. Kami akan meninjau proses penulisan dan menjalankan pengujian unit dengan Karma, mencapai integrasi berkelanjutan dengan Yeomen, Grunt, dan Bower, dan kekuatan lain dari kerangka kerja front-end yang fantastis ini.