<?xml version="1.0" encoding="UTF-8"?>
<mxfile host="Electron" modified="2026-02-23T08:00:00.000Z" agent="draw.io" version="24.0.0">
  <diagram name=".NET to Angular Mental Model" id="dotnet-training">
    <mxGraphModel dx="1400" dy="800" grid="1" gridSize="10">
      <root>
        <mxCell id="0" />
        <mxCell id="1" parent="0" />

        <!-- Title -->
        <mxCell id="title" value=".NET → Angular Mental Model Map (Part 3)" style="text;html=1;strokeColor=none;fillColor=none;align=center;fontSize=17;fontStyle=1;" vertex="1" parent="1">
          <mxGeometry x="100" y="20" width="1000" height="40" as="geometry" />
        </mxCell>

        <!-- Headers -->
        <mxCell id="h1" value=".NET Concept" style="text;html=1;align=center;fontSize=14;fontStyle=1;fillColor=#1565C0;fontColor=#ffffff;rounded=1;" vertex="1" parent="1">
          <mxGeometry x="80" y="80" width="360" height="40" as="geometry" />
        </mxCell>
        <mxCell id="h2" value="Angular 21 Equivalent" style="text;html=1;align=center;fontSize=14;fontStyle=1;fillColor=#2E7D32;fontColor=#ffffff;rounded=1;" vertex="1" parent="1">
          <mxGeometry x="560" y="80" width="380" height="40" as="geometry" />
        </mxCell>

        <!-- Row 1: DI -->
        <mxCell id="r1a" value="&lt;b&gt;Constructor Injection&lt;/b&gt;&lt;br/&gt;public MyClass(ICartSvc svc)" style="rounded=1;fillColor=#E3F2FD;strokeColor=#1565C0;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="80" y="150" width="360" height="55" as="geometry" />
        </mxCell>
        <mxCell id="r1b" value="&lt;b&gt;inject() function&lt;/b&gt;&lt;br/&gt;readonly svc = inject(CartService)" style="rounded=1;fillColor=#E8F5E9;strokeColor=#2E7D32;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="560" y="150" width="380" height="55" as="geometry" />
        </mxCell>
        <mxCell id="arr1" edge="1" source="r1a" target="r1b" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#666;strokeWidth=2;" parent="1"><mxGeometry relative="1" as="geometry"/></mxCell>

        <!-- Row 2: INotifyPropertyChanged -->
        <mxCell id="r2a" value="&lt;b&gt;INotifyPropertyChanged&lt;/b&gt;&lt;br/&gt;+ computed property (get)" style="rounded=1;fillColor=#E3F2FD;strokeColor=#1565C0;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="80" y="230" width="360" height="55" as="geometry" />
        </mxCell>
        <mxCell id="r2b" value="&lt;b&gt;signal() + computed()&lt;/b&gt;&lt;br/&gt;signal(0); computed(() =&gt; val() * 2)" style="rounded=1;fillColor=#E8F5E9;strokeColor=#2E7D32;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="560" y="230" width="380" height="55" as="geometry" />
        </mxCell>
        <mxCell id="arr2" edge="1" source="r2a" target="r2b" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#666;strokeWidth=2;" parent="1"><mxGeometry relative="1" as="geometry"/></mxCell>

        <!-- Row 3: Interface / InjectionToken -->
        <mxCell id="r3a" value="&lt;b&gt;Interface + DI binding&lt;/b&gt;&lt;br/&gt;services.AddScoped&lt;IRepo, Repo&gt;()" style="rounded=1;fillColor=#E3F2FD;strokeColor=#1565C0;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="80" y="310" width="360" height="55" as="geometry" />
        </mxCell>
        <mxCell id="r3b" value="&lt;b&gt;InjectionToken&lt;T&gt; + provide&lt;/b&gt;&lt;br/&gt;{ provide: REPO_TOKEN, useClass: ApiRepo }" style="rounded=1;fillColor=#E8F5E9;strokeColor=#2E7D32;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="560" y="310" width="380" height="55" as="geometry" />
        </mxCell>
        <mxCell id="arr3" edge="1" source="r3a" target="r3b" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#666;strokeWidth=2;" parent="1"><mxGeometry relative="1" as="geometry"/></mxCell>

        <!-- Row 4: ViewModel -->
        <mxCell id="r4a" value="&lt;b&gt;ViewModel + View (.cshtml)&lt;/b&gt;&lt;br/&gt;Class + Razor/XAML — separate files" style="rounded=1;fillColor=#E3F2FD;strokeColor=#1565C0;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="80" y="390" width="360" height="55" as="geometry" />
        </mxCell>
        <mxCell id="r4b" value="&lt;b&gt;@Component&lt;/b&gt;&lt;br/&gt;Class + template — co-located in one file" style="rounded=1;fillColor=#E8F5E9;strokeColor=#2E7D32;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="560" y="390" width="380" height="55" as="geometry" />
        </mxCell>
        <mxCell id="arr4" edge="1" source="r4a" target="r4b" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#666;strokeWidth=2;" parent="1"><mxGeometry relative="1" as="geometry"/></mxCell>

        <!-- Row 5: async / Observable -->
        <mxCell id="r5a" value="&lt;b&gt;Reactive Extensions (Rx.NET)&lt;/b&gt;&lt;br/&gt;Observable&lt;T&gt;, IObservable, Subject" style="rounded=1;fillColor=#E3F2FD;strokeColor=#1565C0;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="80" y="470" width="360" height="55" as="geometry" />
        </mxCell>
        <mxCell id="r5b" value="&lt;b&gt;RxJS + resource()&lt;/b&gt;&lt;br/&gt;Use resource() for HTTP, RxJS for streams" style="rounded=1;fillColor=#E8F5E9;strokeColor=#2E7D32;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="560" y="470" width="380" height="55" as="geometry" />
        </mxCell>
        <mxCell id="arr5" edge="1" source="r5a" target="r5b" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#666;strokeWidth=2;" parent="1"><mxGeometry relative="1" as="geometry"/></mxCell>

        <!-- Row 6: Authorization -->
        <mxCell id="r6a" value="&lt;b&gt;[Authorize] / IMiddleware&lt;/b&gt;&lt;br/&gt;ASP.NET Core auth middleware" style="rounded=1;fillColor=#E3F2FD;strokeColor=#1565C0;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="80" y="550" width="360" height="55" as="geometry" />
        </mxCell>
        <mxCell id="r6b" value="&lt;b&gt;CanActivateFn (Route Guard)&lt;/b&gt;&lt;br/&gt;Functional guard — checks auth before navigation" style="rounded=1;fillColor=#E8F5E9;strokeColor=#2E7D32;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="560" y="550" width="380" height="55" as="geometry" />
        </mxCell>
        <mxCell id="arr6" edge="1" source="r6a" target="r6b" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#666;strokeWidth=2;" parent="1"><mxGeometry relative="1" as="geometry"/></mxCell>

        <!-- Row 7: Composition Root -->
        <mxCell id="r7a" value="&lt;b&gt;Program.cs (Composition Root)&lt;/b&gt;&lt;br/&gt;builder.Services.Add...()" style="rounded=1;fillColor=#E3F2FD;strokeColor=#1565C0;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="80" y="630" width="360" height="55" as="geometry" />
        </mxCell>
        <mxCell id="r7b" value="&lt;b&gt;app.config.ts (ApplicationConfig)&lt;/b&gt;&lt;br/&gt;providers: [ provideZonelessChangeDetection(), ... ]" style="rounded=1;fillColor=#E8F5E9;strokeColor=#2E7D32;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="1">
          <mxGeometry x="560" y="630" width="380" height="55" as="geometry" />
        </mxCell>
        <mxCell id="arr7" edge="1" source="r7a" target="r7b" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#666;strokeWidth=2;" parent="1"><mxGeometry relative="1" as="geometry"/></mxCell>

        <!-- 4-week ladder -->
        <mxCell id="weeks-bg" value="4-Week Training Ladder" style="swimlane;startSize=30;fillColor=#FFF8E1;strokeColor=#F9A825;fontStyle=1;fontSize=13;" vertex="1" parent="1">
          <mxGeometry x="80" y="720" width="860" height="80" as="geometry" />
        </mxCell>
        <mxCell id="w1" value="Week 1&lt;br/&gt;DI, Components&lt;br/&gt;Template Syntax" style="rounded=1;fillColor=#FFFDE7;strokeColor=#F9A825;fontSize=11;whiteSpace=wrap;" vertex="1" parent="weeks-bg">
          <mxGeometry x="20" y="35" width="180" height="35" as="geometry" />
        </mxCell>
        <mxCell id="w2" value="Week 2&lt;br/&gt;Signals, resource()&lt;br/&gt;RxJS basics" style="rounded=1;fillColor=#FFFDE7;strokeColor=#F9A825;fontSize=11;whiteSpace=wrap;" vertex="1" parent="weeks-bg">
          <mxGeometry x="220" y="35" width="180" height="35" as="geometry" />
        </mxCell>
        <mxCell id="w3" value="Week 3&lt;br/&gt;Forms, Guards&lt;br/&gt;Routing" style="rounded=1;fillColor=#FFFDE7;strokeColor=#F9A825;fontSize=11;whiteSpace=wrap;" vertex="1" parent="weeks-bg">
          <mxGeometry x="420" y="35" width="180" height="35" as="geometry" />
        </mxCell>
        <mxCell id="w4" value="Week 4&lt;br/&gt;Vitest + Playwright&lt;br/&gt;80% coverage" style="rounded=1;fillColor=#FFFDE7;strokeColor=#F9A825;fontSize=11;whiteSpace=wrap;" vertex="1" parent="weeks-bg">
          <mxGeometry x="620" y="35" width="210" height="35" as="geometry" />
        </mxCell>

      </root>
    </mxGraphModel>
  </diagram>
</mxfile>
