Carlos Cifuentes
AngularJS → Angular reference

jQuery / angular.element in directives in modern Angular

Most jQuery calls in a directive changed classes, styles or listeners. Those become bindings in the template and in the host object, driven by signals.

Before · AngularJS
app.directive('expandable', function () {
  return {
    restrict: 'A',
    link: function (scope, element) {
      var body = element.find('.body');
      var toggle = element.find('.toggle');
      toggle.on('click', function () {
        body.slideToggle();
        element.toggleClass('open');
      });
      scope.$on('$destroy', function () { toggle.off('click'); });
    }
  };
});
After · Angular
@Component({
  selector: 'app-expandable',
  host: { '[class.open]': 'open()' },
  template: `
    <button (click)="open.set(!open())">Toggle</button>
    <div #body [style.max-height.px]="open() ? height() : 0"><ng-content /></div>
  `,
})
export class ExpandableComponent {
  open = signal(false);
  height = signal(0);
  body = viewChild.required<ElementRef<HTMLElement>>('body');
  constructor() {
    afterNextRender(() => this.height.set(this.body().nativeElement.scrollHeight));
  }
}

What changes

  • find(...).on('click') becomes an event binding in the template, which Angular removes when the component is destroyed.
  • toggleClass, css and attr become class, style and attribute bindings; animations such as slideToggle become CSS transitions.
  • When the code needs the real element, to measure it or to hand it to a library, get it with viewChild and read it inside afterNextRender; use Renderer2 to change elements outside your template.

Migration tip. Classify every jQuery call before rewriting: state changes become bindings, measurements and focus use viewChild, and plugins need a decision each. The first group is the largest and it disappears into the template.

Related

Planning a migration or a micro-frontend platform?

In a 20-minute call you describe your situation and I tell you how I'd approach it. If it isn't worth doing yet, I'll say so.

Message me on LinkedIn