Bird
Raised Fist0
Angularframework~20 mins

Custom structural directives in Angular - Practice Problems & Coding Challenges

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Challenge - 5 Problems
🎖️
Structural Directive Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
component_behavior
intermediate
2:00remaining
What does this custom structural directive render?
Given the following Angular structural directive usage, what will be rendered in the browser?
Angular
/* Directive code omitted for brevity */
@Component({
  selector: 'app-root',
  template: `
    <div *appUnless="condition">Show this if condition is false</div>
  `
})
export class AppComponent {
  condition = false;
}
AThe text 'Show this if condition is false' is displayed
BNothing is displayed
CAn error occurs because 'appUnless' is not a built-in directive
DThe text 'Show this if condition is false' is displayed only if condition is true
Attempts:
2 left
💡 Hint
Think about what the directive name 'appUnless' suggests about when it shows content.
📝 Syntax
intermediate
1:30remaining
Which option correctly defines a custom structural directive selector?
You want to create a custom structural directive named 'appShowIf'. Which selector syntax is correct?
A"*appShowIf"
B"[appShowIf]"
C"appShowIf"
D"[appShowIf]" and use *appShowIf in template
Attempts:
2 left
💡 Hint
Structural directives use a special syntax in templates but their selectors are attribute selectors.
lifecycle
advanced
2:00remaining
When is the ngOnChanges lifecycle hook called in a custom structural directive?
Consider a custom structural directive with an @Input() property. When will Angular call ngOnChanges in this directive?
AOnly when the input property changes after initialization
BOnly once when the directive is created
CWhenever the input property value changes, including the first time it is set
DngOnChanges is not called in structural directives
Attempts:
2 left
💡 Hint
Think about how Angular detects changes to input properties.
🔧 Debug
advanced
2:30remaining
Why does this custom structural directive cause a runtime error?
This directive tries to create an embedded view but causes an error. What is the likely cause? ```typescript @Directive({ selector: '[appShow]' }) export class ShowDirective { constructor(private templateRef: TemplateRef) {} ngOnInit() { this.templateRef.createEmbeddedView(); } } ```
AMissing @Input property to control rendering
BcreateEmbeddedView is a method of ViewContainerRef, not TemplateRef
CThe selector should be '*appShow' instead of '[appShow]'
DThe directive must inject ChangeDetectorRef to create views
Attempts:
2 left
💡 Hint
Check which Angular class has the createEmbeddedView method.
state_output
expert
3:00remaining
What is the output count of items rendered by this custom structural directive?
Given this directive and component, how many
  • elements will be rendered? ```typescript @Directive({ selector: '[appRepeat]' }) export class RepeatDirective { @Input() set appRepeat(times: number) { this.viewContainer.clear(); for (let i = 0; i < times; i++) { this.viewContainer.createEmbeddedView(this.templateRef, { index: i }); } } constructor(private templateRef: TemplateRef, private viewContainer: ViewContainerRef) {} } @Component({ selector: 'app-root', template: `
    • Item {{index}}
    ` }) export class AppComponent {} ```
  • A3 <li> elements with text 'Item 0', 'Item 1', and 'Item 2'
    B1 <li> element with text 'Item 3'
    C3 <li> elements all showing 'Item undefined'
    DNo <li> elements rendered because of missing context
    Attempts:
    2 left
    💡 Hint
    Look at how many times the view is created and what context is passed.

    Practice

    (1/5)
    1. What is the main purpose of a custom structural directive in Angular?
    easy
    A. To style elements with CSS classes
    B. To fetch data from a server
    C. To handle user input events
    D. To add or remove HTML elements dynamically based on conditions

    Solution

    1. Step 1: Understand structural directives role

      Structural directives change the structure of the DOM by adding or removing elements.
    2. Step 2: Identify the main use case

      Custom structural directives let you control when parts of the page appear or disappear dynamically.
    3. Final Answer:

      To add or remove HTML elements dynamically based on conditions -> Option D
    4. Quick Check:

      Structural directives = dynamic HTML blocks [OK]
    Hint: Structural directives control HTML blocks, not styles or events [OK]
    Common Mistakes:
    • Confusing structural directives with attribute directives
    • Thinking they handle styling or events
    • Assuming they fetch data
    2. Which of the following is the correct way to inject dependencies in a custom structural directive constructor?
    easy
    A. constructor(private http: HttpClient) {}
    B. constructor(private elementRef: ElementRef, private renderer: Renderer2) {}
    C. constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) {}
    D. constructor(private router: Router) {}

    Solution

    1. Step 1: Identify dependencies for structural directives

      Structural directives need TemplateRef to access the template and ViewContainerRef to insert or remove views.
    2. Step 2: Match constructor parameters

      constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) {} correctly injects TemplateRef and ViewContainerRef, which are essential for custom structural directives.
    3. Final Answer:

      constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) {} -> Option C
    4. Quick Check:

      TemplateRef + ViewContainerRef = constructor params [OK]
    Hint: Use TemplateRef and ViewContainerRef in constructor for structural directives [OK]
    Common Mistakes:
    • Injecting ElementRef or Renderer2 which are for attribute directives
    • Injecting unrelated services like HttpClient or Router
    • Missing TemplateRef or ViewContainerRef
    3. Given this directive code snippet, what will be the rendered output if appShowIf input is false?
    @Directive({ selector: '[appShowIf]' })
    export class ShowIfDirective {
      constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) {}
      @Input() set appShowIf(condition: boolean) {
        if (condition) {
          this.viewContainer.createEmbeddedView(this.templateRef);
        } else {
          this.viewContainer.clear();
        }
      }
    }

    Usage:
    <div *appShowIf="false">Hello World</div>
    medium
    A. Nothing will be rendered inside the div
    B. The text 'Hello World' will be displayed
    C. An error will occur because of wrong syntax
    D. The div will be rendered but empty

    Solution

    1. Step 1: Analyze the directive behavior when condition is false

      When appShowIf is false, viewContainer.clear() removes any embedded views, so nothing is rendered.
    2. Step 2: Understand the usage effect

      The <div> with 'Hello World' is inside the template controlled by the directive, so it won't appear if condition is false.
    3. Final Answer:

      Nothing will be rendered inside the div -> Option A
    4. Quick Check:

      False condition = no content shown [OK]
    Hint: False input clears view container, so no content appears [OK]
    Common Mistakes:
    • Thinking the div still renders empty
    • Assuming an error occurs
    • Confusing attribute directives with structural directives
    4. Identify the error in this custom structural directive code:
    @Directive({ selector: '[appIf]' })
    export class IfDirective {
      constructor(private templateRef: TemplateRef<any>) {}
      @Input() set appIf(condition: boolean) {
        if (condition) {
          this.templateRef.createEmbeddedView();
        }
      }
    }
    medium
    A. Incorrect selector syntax in @Directive decorator
    B. Missing ViewContainerRef injection and usage to insert the view
    C. Wrong input property name, should be 'appIfCondition'
    D. No error, code is correct

    Solution

    1. Step 1: Check constructor dependencies

      The directive injects only TemplateRef but misses ViewContainerRef, which is needed to insert or clear views.
    2. Step 2: Analyze method usage

      Calling createEmbeddedView() on TemplateRef alone is invalid; it should be called on ViewContainerRef with TemplateRef as argument.
    3. Final Answer:

      Missing ViewContainerRef injection and usage to insert the view -> Option B
    4. Quick Check:

      ViewContainerRef required to add views [OK]
    Hint: Always inject ViewContainerRef to add or remove views [OK]
    Common Mistakes:
    • Trying to create views directly from TemplateRef
    • Forgetting to inject ViewContainerRef
    • Misnaming input properties
    5. You want to create a custom structural directive *appUnless that shows content only when a condition is false. Which implementation correctly achieves this behavior?
    hard
    A. Use if (!condition) to create the embedded view, else clear it
    B. Use if (condition) to create the embedded view, else clear it
    C. Always create the embedded view regardless of condition
    D. Clear the view only when condition is false

    Solution

    1. Step 1: Understand the directive goal

      *appUnless should show content only when the condition is false, so the view is created when !condition.
    2. Step 2: Match logic to code

      Using if (!condition) to create the embedded view and clearing it otherwise matches the requirement.
    3. Final Answer:

      Use if (!condition) to create the embedded view, else clear it -> Option A
    4. Quick Check:

      Show content when false = if (!condition) create view [OK]
    Hint: Invert condition logic to show content only when false [OK]
    Common Mistakes:
    • Using if (condition) instead of if (!condition)
    • Not clearing the view when condition is true
    • Creating view unconditionally