首页 > 解决方案 > 如何查看是否有兄弟投影内容?

问题描述

我正在投影两个组件。

<app-form-field>
   <component-one/>
   <component-two/>
</app-form-field>

因此,如果我想知道例如组件一是否投影在内部,app-form-field 我会这样做:

  @ContentChild(ComponentOne) componentOne;

ngAfterContentInit() {
   if(this.componentOne) {
      alert('it is projected');
   } else {
      alert('it is NOT projected');
   }
}

但我需要检查一下我的内部component-two是否投射了例如组件一

我需要以某种方式检查组件二是否具有兄弟内容投影 - component-one

我怎么能在角度做到这一点?

标签: angularangular-content-projection

解决方案


可以检查是否投影了兄弟组件,但是要走的路可能很老套。

首先,我们需要投影“子”组件的组件。

父组件

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css'],
  providers: [ParentService]
})
export class ParentComponent implements AfterContentInit {
  @ContentChildren(SelectorDirective) public refs: QueryList<SelectorDirective>;
  constructor(private p: ParentService) {}
  ngAfterContentInit(): void {
    this.p.selectorDirectives.next(this.refs.toArray());
    this.refs.changes.subscribe(x => {
      this.p.selectorDirectives.next(this.refs.toArray());
    });
  }

  ngOnInit() {}
}

笔记:

  • 我们在组件级别注入服务ParentService,因此子组件和投影组件可以接收此实例。

  • 对于不同类型的组件,我们需要一个统一的 Selector ( SelectorDirective) 来传递给 @ContentChildren

家长服务:

@Injectable()
export class ParentService {
  selectorDirectives: BehaviorSubject<
    SelectorDirective[]
  > = new BehaviorSubject([]);

  constructor() {}
}

选择器指令:

@Directive({
  selector: '[appSelector]'
})
export class SelectorDirective {
  constructor(public componentRef: Basecomp) {}
}

笔记:

  • 在构造函数中我们注入了Basecomp类型,所以这个指令附加到的每个元素都需要提供这个类型。

基础计算

export class Basecomp {}

笔记:

  • 这仅用作注入令牌

现在我们需要为统一令牌提供子组件的实例:

Comp1组件

@Component({
  selector: 'app-comp1',
  templateUrl: './comp1.component.html',
  styleUrls: ['./comp1.component.css'],
  providers: [
    { provide: Basecomp, useExisting: forwardRef(() => Comp1Component) }
  ]
})
export class Comp1Component implements OnInit {
  constructor() {}

  ngOnInit() {}
}

笔记:

  • 我们还为这个组件的实例提供了 Basecomp-Token。如果 selectorDirective 附加到提供此令牌的组件,我们可以访问指令内部的组件实例。

现在回头看看 ParentComponent 的 ngAfterContentInit:

  • 我们选择所有具有 SelectorDirective 的 ContentChildren
  • 我们将这些元素发送到 ParentService 中的主题上
  • 我们还寻找 QueryList 的变化,如果发生变化,我们会在 ParentService 的 Subject 上发出它们

不,我们可以在 comp2 中注入 ParentService 并可以访问所有兄弟姐妹:

Comp2组件

@Component({
  selector: 'app-comp2',
  templateUrl: './comp2.component.html',
  styleUrls: ['./comp2.component.css'],
  providers: [
    { provide: Basecomp, useExisting: forwardRef(() => Comp2Component) }
  ]
})
export class Comp2Component implements OnInit {
  constructor(private p: ParentService) {}
  c1 = false;
  ngOnInit() {
    this.p.selectorDirectives.pipe().subscribe(x => {
      this.c1 = !!x.find(a => {
        return a.componentRef instanceof Comp1Component;
      });
    });
  }
}

工作示例:https ://stackblitz.com/edit/angular-ivy-t3qes6?file=src/app/comp2/comp2.component.ts


推荐阅读