Một vài lưu ý khi sử dụng AngularJS (Phần 2)
Phần trước chúng ta đã tìm hiểu qua về Directives, Data Binding và ng-repeat. Trong phần này chúng ta tìm hiểu thêm một số điểm cần lưu ý nữa khi sử dụng AngularJS. Chuyển filter từ view vào controller Bình thường khi viết một đoạn ng-repeat với điều kiện nào đó, ta thường để filer ngay ngoài ...
Phần trước chúng ta đã tìm hiểu qua về Directives, Data Binding và ng-repeat. Trong phần này chúng ta tìm hiểu thêm một số điểm cần lưu ý nữa khi sử dụng AngularJS.
Chuyển filter từ view vào controller
Bình thường khi viết một đoạn ng-repeat với điều kiện nào đó, ta thường để filer ngay ngoài view như sau:
vm.users = [ {name: "Phong", company: "Framgia"}, {name: "Hoang", company: "Framgia"}, {name: "Tuan", company: "Other"} ]
<div ng-repeat="user in vm.users | filter: {company: "Framgia"} track by $index"
ng-bind="user.name">
</div>
Tuy nhiên với lượng dữ liệu lớn, việc filter ngoài view sẽ giảm performance. Cách cải thiện là đưa filer vào trong controller như sau:
vm.users = [ {name: "Phong", company: "Framgia"}, {name: "Hoang", company: "Framgia"}, {name: "Tuan", company: "Other"} ]; vm.options = function(company) { return _.compact(_.map(vm.users, fuction(user) { if (user.company = company) { return user; } })); };
<div ng-repeat="option in vm.options("Framgia") track by $index"
ng-bind="option.name">
</div>
Ngoài việc cải thiện performance, ta còn có thể sử dụng lại ở nhiều chỗ mà chỉ cần thay đổi điều kiện. Tiện lợi cho việc thay đổi và chỉnh sửa sau này.
ng-value
Khi muốn truyền một hidden_field lên controller ta dùng:
<input type="hidden" name="email" value="phong@gmail.com">
Tuy nhiên, nếu giá trị của email ta muốn truyền lại nằm trong một biến (ví dụ: vm.email) thì ta có thể dùng ng-value.
vm.email = "phong@gmail.com";
<input type="hidden" name="email" ng-value="vm.email">
Nó rất tiện lợi khi vm.email thay đổi thì giá trị ta muốn truyền lên cũng sẽ thay đổi theo ý mình.
vm.email = "phong@gmail.com"; vn.changeEmail = function() { vm.email = "phong@framgia.com"; };
<a type="button" ng-click="vm.changeEmail()">Change Email</a> <input type="hidden" name="email" ng-value="vm.email">
Nếu không click vào "Change Email" thì giá trị của email trong hidden_field là "phong@gmail.com". Khi click vào "Change Email" thì giá trị đó sẽ thay đổi thành "phong@framgia.com".
Nếu chỉ đơn thuần dùng value, thì giá trị đó đôi khi không được cập nhật. Đặc biệt là trong trường hợp ta sử dụng nút 'Back' của trình duyệt.
ng-if và ng-show
Khi ta sử dụng ng-if cho 1 thẻ html, thì chỉ khi điều kiện trong đó đúng, thì thẻ đó mới được render ra DOM. Còn không sẽ bị loại bỏ hẳn khỏi DOM.
Còn ng-show thì dù điều kiện đúng hay không đúng thì thẻ html đó vẫn được render ra DOM, chỉ là khi điều kiện sai thì thẻ đó được gắn thêm 'display: none' để ẩn đi.
Ta cần nắm rõ vấn đề này để sử dụng ng-if và ng-show một cách hợp lý.
Trong thực tế, ng-if được ưu tiên sử dụng hơn. Vì nó không render thẻ html khi không cần thiết làm tăng performance. Và còn giúp chúng ta tránh nhầm lẫn khi viết các hàm liên quan hoặc viết css.
Ví dụ: Ta muốn thay đổi màu chữ của thẻ p đầu tiên được hiển thị sang màu đỏ.
.test{ p { &:first-child { color: red; } } }
Nếu ta dùng ng-show:
<div class="test"> <p ng-show="false">Name: Phong Henry<p> <p ng-show="true">Email: phong@framgia.com<p> </div>
Trên màn hình rõ ràng ta chỉ thấy duy nhất một trường Email, nhưng email đó lại không có màu đỏ như mong muốn. Do trên DOM vẫn còn trường Name chỉ là nó được ẩn đi thôi.
Nếu dùng ng-if:
<div class="test"> <p ng-if="false">Name: Phong Henry<p> <p ng-if="true">Email: phong@framgia.com<p> </div>
Bây giờ thì trường Email đã có màu đỏ như ý của chúng ta. Vì trường name đã bị loại bỏ hẳn khỏi DOM, nên thẻ p chứa email đã là thẻ p đầu tiên trong class test.