Wednesday, June 25, 2025

Angular: @Input @Output; React: Just JavaScript

Angular @Input @Output



Parent HTML:
<div style="border: 1px solid green; padding: 10px;">
  <h2>Home Component</h2>
  <p>Routing message: {{ (routeData$ | async)?.message }}</p>
  <button (click)="increase()">Increase</button>
  <app-contact-us [phoneNumber]="myPhone.toString()" mainOffice="something" [initialEmployeeCount]="homeEmployeeCount"
    (onEmployeeCountChanged)="handleEmployeeCountChanged($event)"></app-contact-us>
  <hr />
  Parent employee count: {{homeEmployeeCount}}
  <br/>
</div>
Parent TypeScript:
import { AsyncPipe, JsonPipe } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { map, Observable, tap } from 'rxjs';
import { ContactUs } from './contact-us/contact-us';
import { HomeResolverData } from '../../resolvers/home.resolver';

@Component({
  selector: 'app-home',
  imports: [AsyncPipe, ContactUs],
  templateUrl: './home.html',
  styles: ``,
})
export class Home implements OnInit {
  /**
   *
   */

  myPhone = 1314;
  homeEmployeeCount = 7;

  routeData$!: Observable<HomeResolverData>;

  constructor(private route: ActivatedRoute) {
    // console.log(JSON.stringify(this.route.data));
    // console.log(this.routeData$);
  }
  ngOnInit(): void {
    this.routeData$ = this.route.data.pipe(
      map((resolved) => resolved['homeResolver'] as HomeResolverData),
      tap((data) =>
        console.log(
          'RESOLVER_DATA_CONSUMED: Resolver data is now available in component:',
          data
        )
      )
    );
  }

  increase() {
    ++this.myPhone;
  }

  handleEmployeeCountChanged($event: number) {
    this.homeEmployeeCount = $event;
  }
}
Child HTML:
<div>

  <h4>Contact Us</h4>


  Phone: {{phoneNumber}}<br/>
  Main Office: {{primaryOffice}}<br/>

  <button (click)="welcomeEmployee()">Welcome employee</button>
</div>
Child TypeScript:
import { Component, EventEmitter, Input, Output } from '@angular/core';

@Component({
  selector: 'app-contact-us',
  imports: [],
  templateUrl: './contact-us.html',
  styles: ``
})
export class ContactUs {
    @Input() phoneNumber = '';
    @Input('mainOffice') primaryOffice!: string;

    @Input() initialEmployeeCount = 0;
    @Output() onEmployeeCountChanged = new EventEmitter<number>();

    welcomeEmployee() {
      ++this.initialEmployeeCount;
      this.onEmployeeCountChanged.emit(this.initialEmployeeCount);
    }


}


React



Parent HTML+TypeScript:
import { useLoaderData } from "react-router";
import { ContactUs } from "./Home/ContactUs";
import { useState } from "react";

export default function Home() {
    const homeData = useLoaderData();

    const [myPhone, setMyPhone] = useState(1314);
    const [homeEmployeeCount, setHomeEmployeeCount] = useState(7);

    return (
        <>
            <h2>Home Component</h2>
            <p>Routing message: {homeData.message}</p>
            <button onClick={increase}>Increase</button>
            <ContactUs
                phoneNumber={myPhone.toString()}
                mainOffice="something"
                initialEmployeeCount={homeEmployeeCount}
                onEmployeeCountChanged={handleEmployeeCountChanged}
            />
            <hr />
            <button onClick={batchIncreaseFlawed}>Batch Increase Flawed</button>
            <button onClick={batchIncreaseCorrect}>
                Batch Increase Correct
            </button>
            <hr />
            Parent employee count: {homeEmployeeCount}
        </>
    );

    function handleEmployeeCountChanged(newCount: number) {
        setHomeEmployeeCount(newCount);
    }

    function batchIncreaseFlawed() {
        setMyPhone(myPhone + 1);
        setMyPhone(myPhone + 1);
        setMyPhone(myPhone + 1);
    }

    function batchIncreaseCorrect() {
        setMyPhone((prev) => prev + 1);
        setMyPhone((prev) => prev + 1);
        setMyPhone((prev) => prev + 1);
    }

    function increase() {
        setMyPhone((prev) => prev + 1);
    }
}
Child HTML+TypeScript:
import { useState } from "react";

type Params = {
    phoneNumber: string;
    mainOffice: string;
    initialEmployeeCount: number;
    onEmployeeCountChanged: (newCount: number) => void;
};

export function ContactUs({
    phoneNumber,
    mainOffice: primaryOffice,
    initialEmployeeCount,
    onEmployeeCountChanged,
}: Params) {
    const [employeeCount, setEmployeeCount] = useState(initialEmployeeCount);

    return (
        <div>
            <h4>Contact Us</h4>
            Phone: {phoneNumber} <br />
            Main Office: {primaryOffice}<br />
            
            <button onClick={welcomeEmployee}>Welcome employee</button>
        </div>
    );

    function welcomeEmployee() {
        setEmployeeCount((prev) => prev + 1);
        onEmployeeCountChanged(employeeCount);
    }
}
Angular: @Input @OutputReact's Angular @Input @Output

Sunday, June 22, 2025

.NET Middleware

Inline
app.Use(async (context, next) =>
{
    var logger = app.Services.GetRequiredService<ILoggerFactory>()
        .CreateLogger("RequestLogger");

    logger.LogInformation("inline HTTP {Method} {Path}{Query}",
        context.Request.Method,
        context.Request.Path,
        context.Request.QueryString);
    
    await next();
});
Function
app.Use(MyFuncMiddleware);
async Task MyFuncMiddleware(HttpContext context, Func<Task> next)
{
    var logger = app.Services.GetRequiredService<ILoggerFactory>()
        .CreateLogger("RequestLogger");

    logger.LogInformation("func HTTP {Method} {Path}{Query}",
        context.Request.Method,
        context.Request.Path,
        context.Request.QueryString);
    
    await next();
}
HOC
app.Use(MyHocMiddleware());
Func<HttpContext, Func<Task>, Task> MyHocMiddleware()
{
     var logger = app.Services.GetRequiredService<ILoggerFactory>()
         .CreateLogger("RequestLogger");
     
    return async (context, next) =>
    {
        logger.LogInformation("hoc HTTP {Method} {Path}{Query}",
            context.Request.Method,
            context.Request.Path,
            context.Request.QueryString);
    
        await next();
    };
}
Fluent HOC
app.UseMyFluentHocMiddleware();

public static class MyFluentHocMiddlewareExtensions
{
    // Extension method for IApplicationBuilder to register our custom middleware
    public static IApplicationBuilder UseMyFluentHocMiddleware(this IApplicationBuilder builder)
    {
        var logger = builder.ApplicationServices.GetRequiredService<ILoggerFactory>()
          .CreateLogger("RequestLogger");
        
        return builder.Use(async (context, next) => 
        {
            logger.LogInformation("fluent HTTP {Method} {Path}{Query}",
                 context.Request.Method,
                 context.Request.Path,
                 context.Request.QueryString);

             await next();
        });
    }
}
Fluent Class
app.UseMyFluentClassMiddleware();

// Constructor: The RequestDelegate representing the next middleware MUST be the first parameter.
// Other dependencies (like ILogger) are injected by the DI container.

public class MyClassMiddleware(RequestDelegate next, ILogger<MyClassMiddleware> logger)
{
    // Invoke or InvokeAsync method: This is where the actual middleware logic resides.
    // It must return Task and take HttpContext as the first parameter.
    public async Task InvokeAsync(HttpContext context)
    {
        logger.LogInformation("myClass HTTP {Method} {Path}{Query}",
            context.Request.Method,
            context.Request.Path,
            context.Request.QueryString);
        
        await next(context);

        // logger.LogInformation($"[Class Middleware] Outgoing response status: {context.Response.StatusCode}");
    }
}

// Optional: An extension method to make registering the class middleware more fluent
public static class MyClassMiddlewareExtensions
{
    public static IApplicationBuilder UseMyFluentClassMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<MyClassMiddleware>();
    }
}

Monday, April 5, 2021

Leetcode Everyday: 1748. Sum of Unique Elements. Easy

public class Solution {
    public int SumOfUnique(int[] nums) {
        var hs = 
            from n in nums
            group n by n into g
            where g.Count() == 1
            select g.Key;
        
        return hs.Sum();
    }
}
Source: https://leetcode.com/problems/sum-of-unique-elements/submissions/

Monday, March 29, 2021

Leetcode Everyday: 617. Merge Two Binary Trees. Easy

public class Solution {
    public TreeNode MergeTrees(TreeNode root1, TreeNode root2) =>
        root1 != null || root2 != null ? 
            new TreeNode(
                (root1?.val ?? 0) + (root2?.val ?? 0),
                MergeTrees(root1?.left, root2?.left),
                MergeTrees(root1?.right, root2?.right)            
            )
        : 
            null;                        
}

// TODO: optimize without allocating
Source: https://leetcode.com/problems/merge-two-binary-trees/

Saturday, March 20, 2021

Leetcode Everyday: 728. Self Dividing Numbers. Easy

public class Solution {
    public IList<int> SelfDividingNumbers(int left, int right) {
        var list = new List<int>();
        for (var i = left; i <= right; ++i) {
            for (var n = i; n > 0; n /= 10) {
                var toDivide = n % 10;
                if (toDivide == 0 || i % toDivide != 0) {
                    goto goNextNumber;
                }                
            }
            list.Add(i);
            
goNextNumber:;
        }
        return list;
    }
}
Source: https://leetcode.com/problems/self-dividing-numbers/