DEV Community

Cover image for Make Your Angular App Look Better with SameWidthDirective
netsi1964 πŸ™πŸ»
netsi1964 πŸ™πŸ»

Posted on

Make Your Angular App Look Better with SameWidthDirective

TLDR

The SameWidthDirective is an Angular directive that helps you match the width of two or more elements on your page. You can use it to make your app look more professional and polished, and it's easy to use and customize.

Demo (on stackblitz.com)

Description

Have you ever noticed how some web pages have elements that match perfectly in width, while others have awkward gaps or misaligned items? It can be frustrating to try and fix these issues, especially if you don't have experience with CSS.

That's where the SameWidthDirective comes in. This directive lets you match the width of any element on your page with another element of your choice. You can use it to match the width of columns in a table, or to make sure that two or more divs have the same width.

Here's an example of how you can use the SameWidthDirective:

Example: Match Div to Table Row
Let's say you have a div that you want to match to the width of a table row. You can use the SameWidthDirective to accomplish this:

<table>
  <tbody>
    <tr>
      <td>Column 1</td>
      <td>Column 2</td>
      <td>Column 3</td>
    </tr>
  </tbody>
</table>

<div [sameWidth]="'table tr'">
  This div will have the same width as the table row.
</div>
Enter fullscreen mode Exit fullscreen mode

In this example, we're using the SameWidthDirective to match the width of the div to the width of the table row. By setting the selector input to "table tr", we're telling the directive to match the width of the table row to the width of the div.

Code

Here's the code for the SameWidthDirective:

import { AfterViewInit, Directive, ElementRef, Input, NgZone, OnChanges, Renderer2, SecurityContext, SimpleChanges } from '@angular/core';
import { debounceTime, Subject, Subscription } from 'rxjs';

import { DomSanitizer } from '@angular/platform-browser';

@Directive({
  selector: '[sameWidth]',
})
export class SameWidthDirective implements AfterViewInit, OnChanges {
  @Input('sameWidth') selector: string;
  private readonly updateSubject = new Subject<void>();
  private subscriptions = new Subscription();

  constructor(private el: ElementRef, private renderer: Renderer2, private readonly sanitizer: DomSanitizer, private ngZone: NgZone) {
    this.subscriptions.add(this.updateSubject.pipe(debounceTime(50)).subscribe(() => this.updateWidth()));
  }

  public ngAfterViewInit() {
    this.selector = this.sanitizeSelector(this.selector);
    this.updateSubject.next();
    const debouncedStable = this.ngZone.onStable.pipe(debounceTime(100));

    this.subscriptions.add(
      debouncedStable.subscribe(() => {
        this.updateSubject.next();
      }),
    );
  }
  public ngOnChanges(changes: SimpleChanges) {
    const selector = changes['selector'];
    if (selector) {
      this.selector = this.sanitizeSelector(selector.currentValue);
      this.updateSubject.next();
    }
  }

  private updateWidth() {
    const target = document.querySelector(this.selector) as HTMLElement;
    if (target) {
      const width = target.offsetWidth;
      if (width > 0) {
        this.renderer.setStyle(this.el.nativeElement, 'width', `${width}px`);
      }
    }
  }
  private sanitizeSelector(selector: string): string {
    // Sanitize the selector using DomSanitizer to prevent XSS attacks
    const sanitizedSelector = this.sanitizer.sanitize(SecurityContext.HTML, selector);
    return sanitizedSelector ? sanitizedSelector : '';
  }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

The SameWidthDirective is a simple but powerful way to match the width of elements on your page. It's easy to use and customize, and can help make your app look more professional and polished. By using the SameWidthDirective, you can avoid the frustration of misaligned elements and create a more cohesive and visually pleasing user experience.

So why not give the SameWidthDirective a try in your next Angular project? Your users will thank you for it!

This blog post was written by netsi1964 and ChatGPT 3.5.

Top comments (0)