├── README.md ├── _learning └── overview.md ├── controller ├── function.html ├── object.html └── variable.html ├── directive ├── count.html ├── debounce.html ├── define.html ├── dom-manipulation.html ├── input-validation ├── ng-bind-html.html ├── ng-bind-template.html ├── ng-bind.html ├── toggle.html ├── two-way.html └── updateOn.html ├── expression └── expression.html ├── filter └── comic.html ├── form ├── calculator.html ├── list.html └── validation.html ├── route ├── overview │ ├── index.html │ └── templates │ │ ├── about.html │ │ ├── contact │ │ └── home.html └── params │ ├── index.html │ ├── server.php │ └── templates │ └── detail.html ├── scope └── rootScope.html └── service ├── http.get ├── index.html └── server.php ├── http.post ├── index.html └── login.php ├── service&factory.html └── square.html /README.md: -------------------------------------------------------------------------------- 1 | # angular1-tutorial 2 | Hướng dẫn về framework AngularJS

3 | ## Tổng quan về AngularJS 1 4 | ### Giới thiệu 5 | AngularJS là một bộ Javascript Framework rất mạnh và thường được sử dụng để xây dựng project Single Page Application (SPA). Nó mở rộng HTML DOM với các thuộc tính bổ sung cho nên đáp ứng được nhiều yêu cầu từ phía người dùng. AngularJS là một Framework mã nguồn mở hoàn toàn miễn phí và được hàng ngàn các lập trình viên trên thế giới ưa chuộng và sử dụng. Angular JS hỗ trợ mô hình MVC. 6 | 7 | Dưới đây là một số tính năng cốt lõi quan trọng của AngularJS: 8 | - Data-binding (Ràng buộc dữ liệu): tự động đồng bộ dữ liệu giữa model và view 9 | - Scope: những đối tượng kết nối Controller và View 10 | - Controller: lớp business logic phía sau views 11 | - Service: mục đích của xây dựng service là để tái sử dụng các phương thức chung ở nhiều view hoặc controller khác nhau 12 | - Filters (Bộ lọc): format lại dữ liệu hiển thị ra ngoài view người dùn 13 | - Directives: cho phép mở rộng HTML và bạn có thể custom lại các thuộc tính (attribute), phần tử (elements) 14 | - Templates: hiển thị thông tin từ controller, đây là một thành phần của views 15 | - Routing: chuyển đổi giữa các action trong controller 16 | - MVW: Model-View-Whatever, từ MVW chúng ta có thể phát triển thành MVC Model-View-Controller hoặc là MVVM Model-View-ViewModel 17 | - Deep Linking (Liên kết sâu): cho phép bạn mã hóa trạng thái của ứng dụng trong các URL để nó có thể đánh dấu được với công cụ tìm kiếm. 18 | - Dependency Injection: liên kết, thống nhất các đối tượng và chức năng. 19 | 20 | Mối liên hệ giữa các thành phần trong AngularJS
21 | 22 | 23 | ### Cài đặt 24 | Để sử dụng AngularJS trong project, bạn cần phải khai báo 1 cặp thẻ `` chứa đường link tới file angular.min.js. Trong tutorial này, tôi sẽ sử dụng AngularJS phiên bản 1.4.9 (phiên bản ổn định). Bạn có thể tải AngularJS trên [trang chủ](https://angularjs.org/) rồi giải nén, hoặc sử dụng CDN như sau `https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js`. 25 | 26 | 27 | 28 | 29 | ## Expression - Controller - Scope 30 | ### Expression 31 | AngularJS đồng bộ dữ liệu giữa ứng dụng với HTML bằng cách sử dụng _expression_. Hiểu 1 cách đơn giản, expression là dữ liệu chúng ta muốn hiển thị ra màn hình. Dữ liệu ở đây có thể là số, chuỗi, phần tử của mảng hoặc thuộc tính của đối tượng... 32 | Expression được viết bên trong cặp dấu {{ }} 33 | 34 | [Demo expression](https://github.com/ntaback26/angular-tutorial/blob/master/expression/expression.html) 35 | 36 | **Giải thích:** thuộc tính ng-app ở thẻ body là thuộc tính của AngularJS. Nó đánh dấu vị trí mà code AngularJS bắt đầu có hiệu lực. Thuộc tính ng-init có nhiệm vụ khởi tạo giá trị cho các biến. ng-app và ng-init được gọi là _directive (điều hướng)_ 37 | 38 | ### Controller 39 | Trong AngularJS, controller có nhiệm vụ chính là điều khiển dữ liệu của ứng dụng. Một controller được định nghĩa bằng cách sử dụng directive ng-controller. Một controller là một đối tượng Javascript bao gồm các thuộc tính và các phương thức. 40 | 41 | _Ví dụ 1:_ 42 | 43 | [Hiển thị dòng chữ Hello AngularJS trên màn hình](https://github.com/ntaback26/angular-tutorial/blob/master/controller/variable.html) 44 | 45 | **Giải thích:** Trong đoạn code trên, controller và view đồng bộ dữ liệu với nhau thông qua đối tượng $scope. Giá trị của ng-app sẽ được truyền vào trong câu lệnh `angular.module('giá trị của ng-app', [])` 46 | 47 | _Ví dụ 2:_ 48 | 49 | Ở ví dụ trên là ta truyền 1 biến vào đối tượng $scope. Ví dụ dưới đây ta sẽ thử truyền 1 hàm vào $scope 50 | 51 | [Truyền hàm vào $scope](https://github.com/ntaback26/angular-tutorial/blob/master/controller/function.html) 52 | 53 | _Ví dụ 3:_ 54 | 55 | [Truyền đối tượng vào $scope](https://github.com/ntaback26/angular-tutorial/blob/master/controller/object.html) 56 | 57 | ### Scope 58 | Scope có nhiệm vụ đồng bộ dữ liệu giữa HTML (View) và Javascript (Controller). Một scope là 1 đối tượng Javascript đặc biệt bao gồm các thuộc tính và các phương thức. Các thuộc tính và phương thức này có thể được sử dụng ở cả View và Controller.
59 | Trong mô hình MVC của AngularJS thì: 60 | - View chính là những đoạn mã HTML hiển thị phía người dùng 61 | - Model là dữ liệu phục vụ cho view hiện tại 62 | - Controller là những hàm Javascript có nhiệm vụ thêm, sửa, xóa, điều khiển dữ liệu 63 | 64 | Và scope chính là Model. 65 | 66 | **$rootScope** 67 | Nếu như $scope chỉ ảnh hưởng trong phạm vi của controller (tính từ phần tử HTML khai báo ng-controller), thì $rootScope ảnh hưởng lên toàn bộ ứng dụng (tính từ phần tử HTML khai báo ng-app). 68 | 69 | [Demo rootScope](https://github.com/ntaback26/angular-tutorial/blob/master/scope/rootScope.html) 70 | 71 | Trong ví dụ trên, ta có thể thấy nếu như $rootScope và $scope có một thuộc tính cùng tên, thì ở trong div khai báo ng-controller, thuộc tính của $scope sẽ ghi đè thuộc tính của $rootScope, nhưng ở bên ngoài div đó, thuộc tính của $rootScope sẽ không bị ghi đè. 72 | 73 | 74 | 75 | 76 | ## Directive 77 | ### Khái niệm 78 | AngularJS cho phép chúng ta mở rộng các phần tử HTML bằng cách thêm các thuộc tính mới gọi là _directive_. Bên cạnh những directive mà AngularJS đã cung cấp sẵn thì chúng ta cũng có thể tự định nghĩa các directive của riêng mình. 79 | 80 | Các thuộc tính là directive thường có tiền tố **ng-** ở phía trước, ví dụ như: ng-app, ng-controller, ng-model, ... Danh sách các directive của AngularJS bạn có thể xem ở [đây](https://docs.angularjs.org/api/ng/directive) 81 | 82 | Dựa theo chức năng, các directive có thể phân chia thành các nhóm như sau: 83 | 84 | 85 | ### Tự định nghĩa directive 86 | Ví dụ dưới đây sẽ định nghĩa 1 directive có nhiệm vụ render ra 1 form đăng nhập 87 | 88 | [Tự định nghĩa directive](https://github.com/ntaback26/angular-tutorial/blob/master/directive/define.html) 89 | 90 | **Giải thích:** Ta đặt tên cho directive theo kiểu camel case myLoginForm, khi triệu gọi directive thì ta sẽ viết tên directive theo kiểu my-login-form. [Đọc thêm](http://www.w3schools.com/angular/angular_directives.asp) 91 | 92 | ### Data binding 93 | **1. ng-model** 94 | 95 | Directive ng-model có những nhiệm vụ sau: 96 | - Đồng bộ giá trị của các HTML control (input, select, button, textarea) với dữ liệu của ứng dụng 97 | - Cung cấp các validation như required, number, email, url,... 98 | - Kiểm soát trạng thái của các HTML control (valid/invalid, dirty/pristine, touched/untouched, validation errors) 99 | - Thêm vào hoặc xóa đi các class CSS ở các HTML control dựa theo trạng thái của model. Danh sách các class: 100 | - ng-valid: the model is valid 101 | - ng-invalid: the model is invalid 102 | - ng-valid-[key]: for each valid key added by $setValidity 103 | - ng-invalid-[key]: for each invalid key added by $setValidity 104 | - ng-pristine: the control hasn't been interacted with yet 105 | - ng-dirty: the control has been interacted with 106 | - ng-touched: the control has been blurred 107 | - ng-untouched: the control hasn't been blurred 108 | - ng-pending: any $asyncValidators are unfulfilled 109 | - ng-empty: the view does not contain a value or the value is deemed "empty", as defined by the ngModel.NgModelController method 110 | - ng-not-empty: the view contains a non-empty value 111 | 112 | 113 | _Ví dụ 1: Cho 1 thẻ input, khi nhập giá trị vào input thì expression cùng tên cũng sẽ mang giá trị tương ứng_ 114 | 115 | [Two-Way Binding](https://github.com/ntaback26/angular-tutorial/blob/master/directive/two-way.html) 116 | 117 | [Đọc thêm về Data Binding](https://docs.angularjs.org/guide/databinding) 118 | 119 | _Ví dụ 2: Cho 1 thẻ input, kiểm tra xem giá trị nhập vào có phải là chữ số hay không_ 120 | 121 | [Input validation](https://github.com/ntaback26/angular-tutorial/blob/master/directive/input-validation) 122 | 123 | **Giải thích:** Ta thử nhập 1 chữ cái vào ô input, bật firebug lên ta sẽ thấy thẻ \ có thêm 1 class ng-invalid 124 | 125 | **2. ng-model-options** 126 | ng-model-options dùng để cấu hình một số thông số liên quan tới ng-model. Khi ứng dụng được chạy lên thì ng-model-options sẽ thực thi trước và sau đó ng-model mới được tạo. Các thông số bao gồm: 127 | - updateOn: xác định thao tác nào (blur, default, keypress, ...) sẽ quyết định việc update $scope 128 | - debounce: xác định khoảng thời gian sau bao lâu (tính bằng millisecond) thì update $scope 129 | - getterSetter 130 | - allowInvalid 131 | - timezone 132 | 133 | _Ví dụ 1: Cho 1 thẻ input, sau khi nhập giá trị, phải click chuột ra ngoài input thì expression mới thay đổi_ 134 | 135 | [updateOn](https://github.com/ntaback26/angular-tutorial/blob/master/directive/updateOn.html) 136 | 137 | _Ví dụ 2: Cho 1 thẻ input, sau khi nhập giá trị, phải đợi 1s thì expression mới thay đổi_ 138 | 139 | [debounce](https://github.com/ntaback26/angular-tutorial/blob/master/directive/debounce.html) 140 | 141 | **3. ng-bind** 142 | 143 | ng-bind cũng có tác dụng giống như expression. So sánh expression và ng-bind: 144 | 145 | **Expression:** Thỉnh thoảng khi load ứng dụng trên trình duyệt, ta có thể thấy đoạn mã expression sẽ nhấp nháy khoảng vài millisecond trước khi dữ liệu trong expression được load. Bởi vì template được load trước khi AngularJS biên dịch các phần tử. Để giải quyết vấn đề này ta có thể sử dụng directive [ng-cloak](https://docs.angularjs.org/api/ng/directive/ngCloak) 146 | 147 | **ng-bind:** được sử dụng bên trong các phần tử HTML DOM. ng-bind sẽ được thực thi ngay khi dữ liệu thay đổi. 148 | 149 | Trong [ví dụ 1](https://github.com/ntaback26/angular-tutorial/blob/master/directive/two-way.html) ở phần ng-model, thay vì sử dụng expression ta sẽ sử dụng ng-bind: [ng-bind](https://github.com/ntaback26/angular-tutorial/blob/master/directive/ng-bind.html) 150 | 151 | **4. ng-bind-html** 152 | 153 | Directive này cho phép chúng ta in ra 1 đoạn mã HTML, điều mà ta không thể làm với ng-bind. Khi sử dụng ng-bind-html, ta cần phải thêm thư viện [sanitize](http://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular-sanitize.js) 154 | 155 | _Ví dụ:_ Cho 1 thẻ input, nhập vào 1 thẻ `` thì thẻ `` đó sẽ hiện ra. 156 | 157 | [ng-bind-html](https://github.com/ntaback26/angular-tutorial/blob/master/directive/ng-bind-html.html) 158 | 159 | **5. ng-bind-template** 160 | 161 | Directive này sẽ xác định nội dung cần thay thế thông qua expression {{}} đặt trong nó. Không giống như ng-bind, ng-bind-template có thể chứa nhiều expression trong nó, ví dụ như `ng-bind-template="{{firstName}} {{lastName}}"` 162 | 163 | _Ví dụ:_ Cho 2 thẻ input nhập vào firstName và lastName, giá trị nhập vào 2 thẻ sẽ hiển thị trong cùng 1 thẻ \ 164 | 165 | [ng-bind-template](https://github.com/ntaback26/angular-tutorial/blob/master/directive/ng-bind-template.html) 166 | 167 | 168 | ### DOM Manipulation 169 | Trong AngularJS, chúng ta có 3 directive để liên kết dữ liệu của ứng dụng với thuộc tính của các phần tử HTML DOM là: **ng-disabled**, **ng-show** và **ng-hide**. Nếu biểu thức bên trong 3 thuộc tính này mà **true** thì các phần tử HTML DOM sẽ thay đổi như sau: 170 | - Với phần tử có chứa thuộc tính ng-disabled: sẽ được thêm thuộc tính disabled="disabled" 171 | - Với phần tử có chứa thuộc tính ng-show: sẽ xóa đi class .ng-hide 172 | - Với phần tử có chứa thuộc tính ng-hide: sẽ thêm vào class .ng-hide 173 | 174 | _Ví dụ:_ Cho 3 checkbox và 3 button. Khi click checkbox 1, button 1 sẽ bị disabled. Click checkbox 2, button 2 sẽ hiện ra. Click checkbox 3, button 3 sẽ bị ẩn đi. 175 | 176 | [DOM manipulation](https://github.com/ntaback26/angular-tutorial/blob/master/directive/dom-manipulation.html) 177 | 178 | **Giải thích:** Với checkbox 1 và button 1, checkbox 1 nếu chưa được tích vào thì biểu thức disableButton sẽ mang giá trị false, còn khi tích vào nó sẽ sẽ trả về giá trị true. Khi disbaleButton mang giá trị true, button 1 sẽ được thêm thuộc tính disabled="disabled". Tương tự với 2 checkbox và button còn lại. 179 | 180 | 181 | ### Events 182 | AngularJS cung cấp một số event directive cho phép chúng ta chạy hàm của AngularJS khi xảy ra sự kiện người dùng. Một sự kiện của AngularJS sẽ không ghi đè sự kiện tương ứng của HTML, cả 2 sự kiện sẽ được thực thi cùng nhau. 183 | 184 | Danh sách các event directive trong angular: 185 | - ng-blur 186 | - ng-change 187 | - ng-click 188 | - ng-copy 189 | - ng-cut 190 | - ng-dblclick 191 | - ng-focus 192 | - ng-keydown 193 | - ng-keypress 194 | - ng-keyup 195 | - ng-mousedown 196 | - ng-mouseenter 197 | - ng-mouseleave 198 | - ng-mousemove 199 | - ng-mouseover 200 | - ng-mouseup 201 | - ng-paste 202 | 203 | _Ví dụ 1:_ Mỗi lần click vào 1 button thì hiển thị ra số lần đã click 204 | 205 | [count](https://github.com/ntaback26/angular-tutorial/blob/master/directive/count.html) 206 | 207 | _Ví dụ 2:_ Hiển thị ra 1 menu dọc khi click vào 1 button, và ẩn menu đó đi khi click lần nữa. 208 | 209 | [toggle](https://github.com/ntaback26/angular-tutorial/blob/master/directive/toggle.html) 210 | 211 | 212 | 213 | 214 | ## Form 215 | 216 | ### Form submit 217 | Để submit 1 form trong AngularJS, ta có thể sử dụng 2 cách sau: 218 | - Sử dụng directive **ng-submit** trong thẻ form 219 | - Sử dụng directive **ng-click** ở thẻ input hoặc button có type="submit" đầu tiên 220 | 221 | Một vài lưu ý khi submit form: 222 | - Nếu form chỉ có một thẻ input duy nhất thì form sẽ submit khi chúng ta nhấn Enter vào thẻ input đó 223 | - Nếu form có hai thẻ input trở lên và không có button submit hoặc (input[type="submit"]) thì khi chúng ta nhấn Enter thì form sẽ không submit 224 | - Nếu form có một hoặc nhiều field và có một hoặc nhiều button submit hoặc (input[type="submit"]) thì khi chúng ta nhấn Enter vào một field bất kỳ, AngularJS sẽ kích hoạt sự kiện Click trên button hoặc input đầu tiên (ng-click) cũng như sự kiện submit của form (ng-submit) 225 | 226 | ### Form and Input state 227 | Để có thể kiểm tra dữ liệu đầu vào (validate data), AngularJs đã cung cấp cho chúng ta các **state** cho Input và Form 228 | Input có các thuộc tính state sau: 229 | - $untouched: trả về true nếu field chưa có tác động 230 | - $touched: trả về true nếu field đã bị tác động 231 | - $pristine: trả về true nếu field chưa bị thay đổi 232 | - $dirty: trả về true nếu field đã bị thay đổi 233 | - $invalid: trả về true nếu field hợp lệ 234 | - $valid: trả về true nếu field hợp lệ 235 | - $error: đối tượng này bao gồm tất cả các thuộc tính validation (required, pattern, maxlength, minlength, ...) 236 | 237 | Thuộc tính state của input có dạng: formName.inputFieldName.propertyName 238 | 239 | Form có các thuộc tính state sau: 240 | - $pristine: trả về true nếu không có field nào bị thay đổi 241 | - $dirty: trả về true nếu có một hoặc nhiều field bị thay đổi 242 | - $invalid: trả về true nếu nội dung của form không hợp lệ 243 | - $valid: trả về true nếu nội dung của form hợp lệ 244 | - $submitted: trả về true nếu form đã được submit 245 | 246 | Thuộc tính state của form có dạng: formName.propertyName 247 | 248 | Dựa trên các state, AngularJS sẽ thêm vào form và input các class CSS tương ứng 249 | 250 | ### Ví dụ 251 | 252 | _Ví dụ 1:_ Xây dựng chương trình nhập danh sách sinh viên và lưu vào trong một mảng rồi in ra ngoài trình duyệt 253 | 254 | [Student List](https://github.com/ntaback26/angular-tutorial/blob/master/form/list.html) 255 | 256 | **Giải thích:** Trong ví dụ này, ta bắt sự kiện submit form bằng cách sử dụng directive ng-submit ở thẻ form 257 | 258 | _Ví dụ 2:_ Tạo 2 input và cho người dùng nhâp vào 2 số, validate bắt buộc nhập vào phải là số, đồng thời xuất ra màn hình kết quả cộng trừ nhân chia của hai số đó. 259 | 260 | [Calculator](https://github.com/ntaback26/angular-tutorial/blob/master/form/calculator.html) 261 | 262 | _Ví dụ 3:_ Xây dựng 1 form đăng ký với các yêu cầu sau: 263 | - Input Username bắt buộc nhập, và có min length phải là 3 ký tự và max length là 8 ký tự, chỉ được chứa chữ và số 264 | - Input Email bắt buộc nhập, và phải nhập đúng định dạng email 265 | - Input Password bắt buộc nhập, và có min length phải là 5 ký tự và max length là 8 ký tự 266 | - Nếu các điều kiện validate không thỏa, thì sẽ khóa chức năng submit của Form, đồng thời xuất thông báo lỗi bên cạnh input bị lỗi 267 | - Nếu thỏa các điều kiện validate, sẽ hiện ra thông báo đăng ký thành công 268 | 269 | [Register Form Validation](https://github.com/ntaback26/angular-tutorial/blob/master/form/validation.html) 270 | 271 | **Giải thích:** Ở trong thẻ form, ta thêm thuộc tính novalidate để ngăn HTML5 validation 272 | 273 | ## Filter 274 | Filter (bộ lọc) cho phép chúng ta định dạng dữ liệu để hiển thị trên giao diện người dùng mà không thay đổi định dạng ban đầu. 275 | Cú pháp của Filter: `{{expression | filterName1:parameter1 | filterName2:parameter2 | ... }}` 276 | Danh sách các Filter: 277 | - currency: chuyển một số thành định dạng tiền tệ. 278 | - date: chuyển dữ liệu kiểu date thành string theo một định dạng nào đó. 279 | - filter: chọn ra một tập con các phần tử của mảng. 280 | - json: định dạng 1 Javascript object thành 1 JSON string. 281 | - limitTo: trả về 1 mảng mới từ mảng ban đầu 282 | - lowercase: chuyển 1 chuỗi về chữ thường. 283 | - number: định dạng 1 số giống hàm number_format trong PHP 284 | - orderBy: sắp xếp mảng theo biểu thức. 285 | - uppercase: chuyển 1 chuỗi thành chữ in hoa. 286 | 287 | _Ví dụ:_ Xây dựng 1 trang tìm kiếm truyện tranh gồm các yêu cầu sau: 288 | - Tạo 1 danh sách truyện tranh, mỗi truyện chứa các thông tin: ID, tên truyện, số chapter. 289 | - Sắp xếp và hiển thị danh sách truyện theo tên truyện. Sắp xếp theo alphabet. 290 | - Tạo 4 input để tìm kiếm truyện theo All (tất cả các thông tin), theo ID, theo tên truyện, theo số chapter. Nếu không có truyện thỏa mãn thì thông báo không tìm thấy kết quả. 291 | 292 | [Search Comic App](https://github.com/ntaback26/angular-tutorial/blob/master/filter/comic.html) 293 | 294 | ## Service 295 | Trong AngularJS, service là một hàm hoặc một đối tượng thực hiện một nhiệm vụ cụ thể nào đó. AngularJS đã xây dựng sẵn 27 service cho chúng ta, ví dụ như: $location, $http, $window, $timeout, $interval, ... 296 | 297 | ### Định nghĩa service mới 298 | Để tạo một service mới, chúng ta có thể làm theo 2 cách: 299 | - Sử dụng phương thức service 300 | - Sử dụng phương thức factory 301 | 302 | **1. Sử dụng phương thức service** 303 | 304 | Cách định nghĩa: 305 | ```` 306 | app.service('MyService', function () { 307 | this.sayHello = function () { 308 | console.log('hello'); 309 | }; 310 | }); 311 | ```` 312 | Sau khi định nghĩa, chúng ta có thể sử dụng ở tất cả controller, directive và filter: 313 | ```` 314 | app.controller('MyController', function (MyService) { 315 | MyService.sayHello(); // logs 'hello' 316 | }); 317 | ```` 318 | 319 | **2. Sử dụng phương thức factory** 320 | 321 | Cách định nghĩa: 322 | ```` 323 | app.factory('MyFactory', function () { 324 | return { 325 | sayHello: function () { 326 | console.log('hello'); 327 | } 328 | }; 329 | }); 330 | ```` 331 | Sau khi định nghĩa, chúng ta có thể sử dụng ở tất cả controller, directive và filter: 332 | ```` 333 | a.controller('MyController', function (MyFactory) { 334 | MyFactory.sayHello(); // logs 'hello' 335 | }); 336 | ```` 337 | 338 | _Ví dụ 1:_ Ví dụ này giúp chúng ta phân biệt cách sử dụng 2 phương thức trên 339 | 340 | [Service & Factory](https://github.com/ntaback26/angular-tutorial/blob/master/service/service%26factory.html) 341 | 342 | _Ví dụ 2:_ Tạo 1 factory có nhiệm vụ tính bình phương của 1 số. 1 service thông báo kết quả bình phương của 1 số. 343 | 344 | [Bình phương](https://github.com/ntaback26/angular-tutorial/blob/master/service/square.html) 345 | 346 | ### $http 347 | Service $http có nhiệm vụ gửi, trao đổi thông tin với server thông qua ajax. $http sẽ gửi lên server 1 request và trả về 1 response. 348 | 349 | $http có 7 shortcut method: 350 | - .delete() 351 | - .get() 352 | - .head() 353 | - .jsonp() 354 | - .patch() 355 | - .post() 356 | - .put() 357 | 358 | **Chú ý:** Để chạy những ví dụ trong phần này, ta phải bỏ các file vào thư mục htdocs, rồi chạy trên localhost. 359 | 360 | **1. $http.get** 361 | 362 | Method này sẽ gửi lên server 1 http GET request 363 | ```` 364 | $http.get(url) // url: đường dẫn tới file server 365 | ```` 366 | $http.get(url) sẽ trả về 1 HttpPromise object chứa các phương thức xử lý response của GET request: 367 | ```` 368 | $http.get(url).then(function(response) { 369 | // response là 1 object gồm các thuộc tính: 370 | // .config 371 | // .data: dữ liệu này đọc từ server. Server bắt buộc phải trả về client dữ liệu kiểu JSON 372 | // .headers 373 | // .status: kiểu number 374 | // .statusText: kiểu string 375 | }); 376 | ```` 377 | _Ví dụ:_ Tạo 1 file server.php trả về file index.html danh sách truyện tranh (dữ liệu lấy ở bài Search Comic App), ở trang index.html hiển thị danh sách truyện tranh đó. 378 | 379 | [$http.get demo](https://github.com/ntaback26/angular-tutorial/tree/master/service/http.get) 380 | 381 | **2. $http.post** 382 | 383 | Cú pháp: 384 | ```` 385 | $http.get(url, data, config).then(function(response) { 386 | // data: dữ liệu gửi lên server, kiểu Object. Server sẽ nhận được dữ liệu kiểu JSON 387 | // response: tương tự như trong $http.get, điểm khác là response.data không nhất thiết phải là kiểu JSON 388 | }); 389 | ```` 390 | _Ví dụ:_ Tạo 1 file index.html cho phép người dùng đăng nhập. Nếu username = "admin" và password = "123456" thì thông báo đăng nhập thành công, ngược lại thông báo sai username hoặc password (thông báo hiển thị ngay dưới form đăng nhập) 391 | 392 | [$http.post demo](https://github.com/ntaback26/angular-tutorial/tree/master/service/http.post) 393 | 394 | 395 | ## Route 396 | 397 | ### Overview 398 | AngularJS giúp chúng ta xây dựng 1 Single Page Application (SPA): ứng dụng sẽ được chia làm nhiều View mang nội dung khác nhau, khi chuyển View ta không cần phải load lại page. Mỗi View như thế sẽ được quản lý bởi 1 **route**. Mỗi một route được liên kết với 1 View và 1 Controller riêng. Khi ứng dụng được load, nó sẽ xác định route (phần đằng sau dấu # ở trên URL) để quyết định template HTML nào sẽ được show ra. 399 | ```` 400 | http://demo.com/index.html#View1 401 | http://demo.com/index.html#View2 402 | http://demo.com/index.html#View3 403 | http://demo.com/index.html#View4 404 | ```` 405 | Để sử dụng route, ta cần phải nạp thư viện angular-route.min.js và cấu hình thông qua $routeProvider (provider của service $route): 406 | ```` 407 | var app = angular.module('myApp', ['ngRoute']); 408 | app.config(function($routeProvider) { 409 | $routeProvider 410 | .when('/view1', 411 | { 412 | templateUrl: 'templates/view1.html' 413 | controller: 'FirstController', 414 | }) 415 | .when('/view2', 416 | { 417 | templateUrl: 'templates/view2.html' 418 | controller: 'SecondController', 419 | }) 420 | ... 421 | .otherwise({redirectTo: '/view1'}); 422 | }); 423 | ```` 424 | Giả sử khi gõ trên trình duyệt địa chỉ http://localhost/app/index.html#view1, AngularJS sẽ load view1.html đồng thời triệu gọi FirstController. Khối otherwise dùng để định nghĩa route mặc định. 425 | 426 | Để hiển thị View, ta sử dụng directive ng-view: `
` hoặc ``. 427 | 428 | _Ví dụ:_ Xây dựng 1 ứng dụng web gồm 3 page: home, about và contact 429 | 430 | [Overview demo](https://github.com/ntaback26/angular-tutorial/tree/master/route/overview) 431 | 432 | ### Truyền tham số 433 | Để định nghĩa 1 route có truyền tham số trên URL, thì ta chỉ cần thêm `/:tên_tham_số` ở templateUrl: 434 | ```` 435 | .when('/about/:id', { 436 | templateUrl: 'templates/about.html', 437 | controller: 'AboutCtrl' 438 | }) 439 | ```` 440 | URL trên browser lúc này sẽ có dạng http:localhost/app/index.html#/about/123 chẳng hạn. 441 | 442 | Để lấy được tham số trong controller, ta sử dụng **`$routeParams.tên_tham_số`** 443 | 444 | _Ví dụ:_ Phát triển tiếp [$http.get demo](https://github.com/ntaback26/angular-tutorial/tree/master/service/http.get): thêm 1 cột chứa đường link xem chi tiết truyện tranh, click vào link này sẽ hiển thị thông tin chi tiết của truyện đó (ID, name, chapter) 445 | 446 | [Show comic detail](https://github.com/ntaback26/angular-tutorial/tree/master/route/params) 447 | 448 | **Giải thích:** Trong DetailCtrl, sau khi lấy được tham số id, ta sẽ lấy object trong mảng comics mà có id như thế bằng cách sử dụng hàm filter của Javascript. 449 | -------------------------------------------------------------------------------- /_learning/overview.md: -------------------------------------------------------------------------------- 1 | # Angualr Overview 2 | 3 |
4 | ## Giới thiệu 5 | AngularJS là một bộ Javascript Framework rất mạnh và thường được sử dụng để xây dựng các project Single Page Application (SPA). Nó mở rộng HTML DOM với các thuộc tính bổ sung cho nên đáp ứng được nhiều yêu cầu từ phía người dùng. AngularJS là một Framework mã nguồn mở hoàn toàn miễn phí và được hàng ngàn các lập trình viên trên thế giới ưa chuộng và sử dụng. Angular JS hỗ trợ mô hình MVC và đồng bộ dữ liệu 2 chiều. 6 | 7 | ## Single Page Application (SPA) 8 | SPA cho phép các view khác nhau được load vào trong một trang web. Người dùng khi sử dụng SPA không có cảm giác trang web bị load lại. SPA dựa trên các công nghệ sau: 9 | * DOM manipulation 10 | * History 11 | * Routing 12 | * AJAX 13 | * Data Binding 14 | ... 15 | 16 | ## Các thành phần chính trong AngularJS 17 | 18 | 19 | ## Cài đặt 20 | Để sử dụng AngularJS trong 1 trang HTML, bạn cần phải khai báo đường dẫn tới file angular.min.js. Có 2 cách khai báo: 21 | * Cách 1: ` 31 | 32 | 33 |
34 |

Name :

35 |

Hello {{name}}

36 |
37 | 38 | 39 | ``` 40 | -------------------------------------------------------------------------------- /controller/function.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |

Hello {{ sayHello() }}

9 |
10 | 11 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /controller/object.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AngularJS Controller 5 | 6 | 7 | 8 |
9 | First Name: {{ person.firstName }}
10 | Last Name: {{ person.lastName }}
11 | Full Name: {{ person.fullName() }} 12 |
13 | 14 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /controller/variable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello World 5 | 6 | 7 | 8 |
9 |

Hello {{hello}}

10 |
11 | 12 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /directive/count.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | Số lần đã click:
11 | 12 |
13 | 14 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /directive/debounce.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | You entered: {{ yourtext }} 10 | 11 | 12 | -------------------------------------------------------------------------------- /directive/define.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /directive/dom-manipulation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
Disable Button
Show Button
Hide Button
25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /directive/input-validation: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 13 | 14 |

Please enter only number

15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /directive/ng-bind-html.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | You entered: 11 | 12 | 13 | -------------------------------------------------------------------------------- /directive/ng-bind-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 | You entered: 11 | 12 | 13 | -------------------------------------------------------------------------------- /directive/ng-bind.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | You entered: 10 | 11 | 12 | -------------------------------------------------------------------------------- /directive/toggle.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 |

Menu

11 |
    12 |
  • Menu 1
  • 13 |
  • Menu 2
  • 14 |
  • Menu 3
  • 15 |
16 |
17 | 18 | 19 |
20 | 21 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /directive/two-way.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | You entered: {{ yourtext }} 10 | 11 | 12 | -------------------------------------------------------------------------------- /directive/updateOn.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | You entered: {{ yourtext }} 10 | 11 | 12 | -------------------------------------------------------------------------------- /expression/expression.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | AngularJS Expressions 4 | 5 | 6 | 7 |
8 |

{{ 2 + 5 }}

9 |

Total price: {{ cost * quantity }}

10 |

{{ "Hello World!" }}

11 |

Hello {{name.firstname + " " + name.lastname}}!

12 |

Array[3]: {{ array[3] }}

13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /filter/comic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | All: 11 | ID: 12 | Name: 13 | Chapter: 14 |
15 |

ID:

16 |

Name:

17 |

Chapter:

18 |
19 |
Không tìm thấy kết quả
20 |
21 | 22 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /form/calculator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 13 | 14 | 15 |
16 |
17 | Nhập số thứ 1:
18 | Nhập số thứ 2: 19 |
20 |

Kết quả phép cộng:

21 |

Kết qủa phép trừ:

22 |

Kết qủa phép nhân:

23 |

Kết qủa phép chia:

24 |
25 | 26 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /form/list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 | Nhập danh sách sinh viên: 12 | 13 | 14 |
15 | 16 |

Danh sách sinh viên:

17 |
{{list}}
18 |
19 | 20 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /form/validation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 |
15 | 16 |

FORM ĐĂNG KÝ

17 | 18 | 19 |
20 | 21 | 22 |
23 | 24 | 25 |

Username là bắt buộc.

26 |

Username tối thiểu 3 ký tự.

27 |

Username tối đa 8 ký tự.

28 |

Username chỉ được chứa chữ và số.

29 |
30 | 31 | 32 |
33 | 34 | 35 |

Email là bắt buộc.

36 |

Vui lòng nhập 1 email.

37 |
38 | 39 | 40 |
41 | 42 | 43 |

Password là bắt buộc.

44 |

Password tối thiểu 5 ký tự.

45 |

Password tối đa 8 ký tự.

46 |
47 | 48 | 49 | 50 | 51 |
52 |
53 | 54 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /route/overview/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
Home About Contact 11 | 12 |
13 | 14 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /route/overview/templates/about.html: -------------------------------------------------------------------------------- 1 |

{{ message }}

2 | -------------------------------------------------------------------------------- /route/overview/templates/contact: -------------------------------------------------------------------------------- 1 |

{{ message }}

2 | -------------------------------------------------------------------------------- /route/overview/templates/home.html: -------------------------------------------------------------------------------- 1 |

{{ message }}

2 | -------------------------------------------------------------------------------- /route/params/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
IDNameChapter
{{ comic.id }}{{ comic.name }}{{ comic.chapter }}Show detail
40 | 41 | 42 |
43 |
44 | 45 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /route/params/server.php: -------------------------------------------------------------------------------- 1 | 1, 5 | 'name' => 'Doremon', 6 | 'chapter' => 400 7 | ), 8 | 9 | array( 10 | 'id' => 2, 11 | 'name' => 'Naruto', 12 | 'chapter' => 850 13 | ), 14 | 15 | array( 16 | 'id' => 3, 17 | 'name' => 'Dragon Ball', 18 | 'chapter' => 567 19 | ), 20 | 21 | array( 22 | 'id' => 4, 23 | 'name' => 'Pokemon', 24 | 'chapter' => 234 25 | ) 26 | ); 27 | 28 | echo json_encode($arr); 29 | -------------------------------------------------------------------------------- /route/params/templates/detail.html: -------------------------------------------------------------------------------- 1 |

Comic #{{ detail.id }}

2 | 7 | -------------------------------------------------------------------------------- /scope/rootScope.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

The rootScope's color

8 | 9 |
10 |

The scope's color

11 |
12 | 13 |

The rootScope's color not be overrided

14 | 15 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /service/http.get/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
IDNameChapter
{{ comic.id }}{{ comic.name }}{{ comic.chapter }}
37 |
38 | 39 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /service/http.get/server.php: -------------------------------------------------------------------------------- 1 | 1, 5 | 'name' => 'Doremon', 6 | 'chapter' => 400 7 | ), 8 | 9 | array( 10 | 'id' => 2, 11 | 'name' => 'Naruto', 12 | 'chapter' => 850 13 | ), 14 | 15 | array( 16 | 'id' => 3, 17 | 'name' => 'Dragon Ball', 18 | 'chapter' => 567 19 | ), 20 | 21 | array( 22 | 'id' => 4, 23 | 'name' => 'Pokemon', 24 | 'chapter' => 234 25 | ) 26 | ); 27 | 28 | echo json_encode($arr); 29 | -------------------------------------------------------------------------------- /service/http.post/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 | Username:
11 | Password:
12 | 13 |
14 | {{ message }} 15 |
16 | 17 | 35 | 36 | -------------------------------------------------------------------------------- /service/http.post/login.php: -------------------------------------------------------------------------------- 1 | username; 5 | $password = $request->password; 6 | if($username == "admin" && $password== "123456"){ 7 | echo "Login successfully"; 8 | } 9 | else { 10 | echo "Wrong username or password"; 11 | } 12 | 13 | ?> 14 | -------------------------------------------------------------------------------- /service/service&factory.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |

{{ hello.factory }}

10 |

{{ hello.service }}

11 |
12 |
13 |

{{ goodbye.factory }}

14 |

{{ goodbye.service }}

15 |
16 | 17 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /service/square.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 |
12 |
13 | 14 | 37 | 38 | 39 | --------------------------------------------------------------------------------