Carlos Cifuentes
Referencia AngularJS → Angular

require (parent controllers) en Angular moderno

require: '^^parent' pasa a ser inject(ParentComponent). Angular busca al padre hacia arriba en el árbol de elementos, igual que lo hacía require.

Antes · AngularJS
app.component('tabPane', {
  require: { tabs: '^^tabGroup' },
  bindings: { title: '@' },
  transclude: true,
  template: '<div ng-show="$ctrl.active" ng-transclude></div>',
  controller: function () {
    this.$onInit = function () { this.tabs.addPane(this); };
    this.$onDestroy = function () { this.tabs.removePane(this); };
  }
});
Después · Angular
@Component({
  selector: 'app-tab-pane',
  template: `<div [hidden]="!active()"><ng-content /></div>`,
})
export class TabPaneComponent {
  private tabs = inject(TabGroupComponent);
  title = input.required<string>();
  active = computed(() => this.tabs.selected() === this);
}

// in TabGroupComponent: the parent finds its panes with a query
panes = contentChildren(TabPaneComponent);
selected = signal<TabPaneComponent | undefined>(undefined);

Qué cambia

  • Un require opcional ('?^^parent') pasa a ser inject(ParentComponent, { optional: true }).
  • Los hijos ya no se registran con addPane y removePane: el padre los lee con contentChildren o viewChildren.
  • Cuando los dos componentes no son ancestro y descendiente, usa un servicio declarado en los providers de su contenedor común.

Consejo de migración. Un padre y un hijo que referencian la clase del otro desde archivos separados crean un import circular. Deja el par en un solo archivo, o haz que el hijo inyecte un InjectionToken que el padre provee.

Relacionado

¿Planeas una migración o una plataforma de microfrontends?

En una llamada de 20 minutos me cuentas tu situación y te digo cómo la abordaría. Si todavía no vale la pena, también te lo digo.

Escríbeme por LinkedIn