angular - 如何查看是否有兄弟投影内容?
问题描述
我正在投影两个组件。
<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
。
我怎么能在角度做到这一点?
解决方案
可以检查是否投影了兄弟组件,但是要走的路可能很老套。
首先,我们需要投影“子”组件的组件。
父组件
@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
推荐阅读
- couchbase - Couchbase 集群创建问题
- file - 用于更改打印参数的 Postscript 文件编辑
- java - CORS 策略:请求的资源 Spring Boot Rest API 上不存在“Access-Control-Allow-Origin”标头
- visual-studio-code - 格式化代码时如何在新行上停止大括号
- ios - 如何根据其内容高度设置 UITableView 高度?
- activemq-artemis - JBoss AMQ / ActiveMQ Artemis:预配置持久订阅者
- mapbox-gl-js - uber/react-map-gl getMap & 暴露的 Mapbox API
- algorithm - 将一个列表转换为另一个列表
- xcode - 文件是为 x86_64 构建的,它不是被链接的架构(arm64):
- background-image - 如果我在页面上有选择语句,我的背景图片不会加载