Carlos Cifuentes
AngularJS → Angular reference

$attrs.$observe in modern Angular

$attrs.$observe existed to follow an interpolated attribute. In Angular the attribute is an input signal, and host bindings write its value back to the element.

Before · AngularJS
app.directive('tooltip', function () {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      attrs.$observe('tooltip', function (text) {
        element.attr('title', text);
        element.attr('aria-label', text);
      });
    }
  };
});

<button tooltip="Delete {{ vm.user.name }}">x</button>
After · Angular
@Directive({
  selector: '[appTooltip]',
  host: {
    '[attr.title]': 'text()',
    '[attr.aria-label]': 'text()',
  },
})
export class TooltipDirective {
  text = input.required<string>({ alias: 'appTooltip' });
}

<button appTooltip="Delete {{ user().name }}">x</button>

What changes

  • The observed attribute becomes input(); an alias lets the input share the name of the directive selector.
  • element.attr and attrs.$set calls become '[attr.name]' entries in the host object.
  • Code that reacted inside the $observe callback becomes a computed or an effect that reads the input.

Migration tip. $observe callbacks often parsed strings such as 'true' or '10'. Move that parsing into the input transform (booleanAttribute, numberAttribute) so the rest of the class works with real types.

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