Tìm hiểu chung về transclude trong AngularJs 1.x

Reference from: https://www.facebook.com/notes/h%E1%BB%93ng-ph%C3%B9ng-ph%C3%A1t/t%C3%ACm-hi%E1%BB%83u-chung-v%E1%BB%81-transclude-trong-angularjs-1x/1285652024779277

Bài viết chỉ đơn giản thuật lại những gì mình bị vướng và muốn đào sâu 1 chút về transclude.

Giới thiệu

Tranclude theo mình là 1 chủ để hơi khó (chắc là với mình) trong Angularjs. Thông thường, 1 directive nếu không khai báo transclude sẽ bỏ qua các thông tin bên trong custom element đó bằng template của directive (nếu có). Chính vì thế, khái niệm transclude ra đời như 1 cách để tích hợp nội dung bọc bên trong thẻ HTML của custom directive vào template của directive đó.
Phạm vi bài này mình chỉ muốn tìm hiểu sơ qua về ảnh hưởng của scope trong transclude.

Nội Dung

Giả sử chúng ta có 1 đoạn code angularjs sau:
Trong đoạn code trên, ta có 1 controller (MainCtrl) có 2 biến person và header gắn vào scope và ta cũng có directive (person) cũng có 2 biến tương tự gắn vào scope nhưng với nội dung khác nhau. Sau đây là đoạn code HTML sử dụng chúng:
Kì vọng của chúng ta ở đoạn code này là bởi chúng ta có directive person có biến person = Directive Joe và biến header = Directive’s header. Chúng ta đã sử dụng directive và truyền biến header vảo trong directive đó và ta cũng đã thay đổi nội dung header bên trong directive đó. Vậy nên, chúng ta sẽ thấy được header sẽ bind ra Directive’s header và person sẽ sử dụng của Directive Joe . Hay nói cách khác, nội dung transclude chắc chắn sẽ sử dụng scope hoàn toàn từ directive,
Ta hãy thử bằng DEMO JSBIN.
Thật bất ngờ, cái mà ta thấy hoàn toàn không như cách ta đã nghĩ, nội dung header đã bind đúng ra là Directive’s header nhưng biến person đã sử dụng từ biến lưu trong scope của controller. Sai lầm ở đây là chúng ta không biết là đoạn HTML được transclude đã truy cập vào scope cha của controller hay vào scope độc lập của directive? Thực tế, nội dung transclude sẽ truy cập vào scope của controller (chứ không phải từ directive) –> cái này mình cần hiểu nè
Hình dưới sẽ cho ta thấy bức tranh về scope của transclude (đường nét liền thể hiện quan hệ scope cha- con, nét đứt thẻ hiện scope độc lập)
Vậy cuối cùng, nội dung transclude mặc dù được nhúng vào directive nhưng nó vẫn chỉ thấy được trong ngữ cảnh controller. Còn về header, do ta đã sử dụng binding 2 chiều trong trường hợp này nên chắc kết quả mọi người tự tìm hiểu ^^.
Đến đây mình chợt nhớ đến ng-repeat – 1 cái transclude nè 😀

Tricky

Mặc định là transclude sẽ hoạt động như trên, thế nếu ta muốn transclude hiểu được scope từ trong directive thì sao? Và đây là giãi pháp
Link function của directive có tham số thứ 5 là transclude và đây là trick để ta thay đổi scope và nội dung HTML để transclude
Ta có chèn thêm đoạn code để thay đổi hành vi transclude, transclude là tham số thứ 5 của link function và là 1 hàm nhận vào đa dạng tham số. Nếu ta truyền dưới dạng transclude(callback) thì bạn xem document dừm nhé (do mình chưa coi đến). Về truyền dưới dạng transclude(scope, callback) thì nó sẽ sử dụng scope như là scope của transclude và callback sẽ có 2 tham số là: tham số thứ nhất trả về copy DOM của transclude và tham số thứ 2 là scope của DOM. Với đoạn code trên, thì do nó dùng scope.$parent nên kết quả ra tương tự, nếu muốn sử dụng scope của directive thì ta cần khai báo như sau:
Và kết quả là ta sẽ có được việc binding như ý 😀 (DEMO)

285 total views, 1 views today

Trả lời