Demo Output va EventEmitter - Child component gui event len Parent component khi click nut Delete
Demo Two-way binding với Toggle component và ngModel
State: {{ toggleState1 ? 'ON' : 'OFF' }}
State: {{ toggleState2 ? 'ON' : 'OFF' }}
State: {{ toggleState3 ? 'ON' : 'OFF' }}
1. Two-way binding syntax: [(checked)]="toggleState1"
2. Tương đương với: [checked]="toggleState1" (checkedChange)="toggleState1 = $event"
3. Component can: Input() checked va Output() checkedChange
4. Test: Click toggle hoặc button "Toggle from Parent" để xem sync
Demo ng-content với các loại selector: attribute, class, tag, và ngProjectAs
Code: <ng-content></ng-content>
- Nhận tất cả content không có selector
Please answer the following questions about your Angular experience.
Your responses help us improve our content.
Question 1: {{ surveyAnswers.question1 ? '✅ Yes' : '❌ No' }}
Question 2: {{ surveyAnswers.question2 ? '✅ Yes' : '❌ No' }}
Question 3: {{ surveyAnswers.question3 ? '✅ Yes' : '❌ No' }}
Selectors:
• select="[slot=header]"
- Attribute selector
• select=".card-footer-content"
- CSS Class selector
• select=".card-actions"
- Class selector cho actions
• select="button"
- Tag selector cho buttons
• <ng-content>
- Default slot (không có selector)
This is body content
Sử dụng ngProjectAs
để project content vào đúng slot ngay cả khi element không match selector trực tiếp.
Here are your current survey responses:
Note: Elements trên sử dụng ngProjectAs="modal-header"
và
ngProjectAs="modal-body"
để project vào đúng slots.
1. Single Slot: <ng-content></ng-content>
- Nhận tất cả content
2. Attribute Selector: <ng-content select="[slot=header]">
3. Class Selector: <ng-content select=".card-footer-content">
4. Tag Selector: <ng-content select="button">
5. ngProjectAs: <div ngProjectAs="modal-header">
- Project vào slot cụ thể
6. Multiple ng-content: Mỗi selector sẽ nhận content phù hợp
Demo các khái niệm về template rendering và reusable templates
ng-template
chỉ render khi được gọi (ở đây là khi *ngIf else)
#counterTemplate
được tái sử dụng 3 lần thay vì copy-paste code
ngTemplateOutletContext
:let-label="label"
- bind context.label vào variable labellet-implicitLabel
- bind context.$implicit vào variable implicitLabellet-onClick="onClick"
- truyền function callback
ng-container
không tạo DOM element, giúp HTML clean hơn và tránh ảnh hưởng CSS
Truyền template từ parent component vào child component để customize giao diện
This card uses the default styling and layout defined in the Card component.
với template được customize
{{ data.description }}
Demo Constructor Injection, Service Sharing, Provider Override và DI Concepts
✅ Constructor Injection: ProductService và CartService được inject vào components
✅ Service Sharing: Cùng CartService instance được share giữa ProductList và CartView
✅ Loose Coupling: Components không phụ thuộc vào concrete implementations
✅ Testability: Dễ dàng mock services cho unit testing
✅ Maintainability: Có thể thay đổi implementation mà không ảnh hưởng components