我有逻辑上的问题。我需要将要导入服务内部的组件,并在需要该服务的组件内部并行。错误如下:
Circular dependency: dist\services\modal.service.js -> dist\components\modal\modal.component.js -> dist\services\modal.service.js
这是解决这种情况的最佳方法。我最好的解决方案是使用第三种服务,它将以某种方式注入这两个文件。在服务中包含组件的原因是要在其他组件中使用它。
service.ts
import { ComponentFactoryResolver, EmbeddedViewRef, ApplicationRef, ComponentRef, Injectable, Injector
} from '@angular/core';
import { ModalComponent } from '../components/modal/modal.component';
@Injectable({
providedIn: 'root'
})
export class ModalService {
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
private appRef: ApplicationRef,
private injector: Injector
){}
private data = {};
private last;
open(component: any, obj:any = {}) {
if(!obj.id) obj.id = new Date().getTime();
// Create a component reference from the component
const componentRef = this.componentFactoryResolver
.resolveComponentFactory(component)
.create(this.injector);
// Attach component to the appRef so that it's inside the ng component tree
this.appRef.attachView(componentRef.hostView)
// Get DOM element from component
const contentElem = (componentRef.hostView as EmbeddedViewRef<any>)
.rootNodes[0] as HTMLElement;
// Create a component reference from the component
let componentRefer = this.componentFactoryResolver
.resolveComponentFactory(ModalComponent)
.create(this.injector);
// Attach component to the appRef so that it's inside the ng component tree
this.appRef.attachView(componentRefer.hostView);
// Get DOM element from component
const domElem = (componentRefer.hostView as EmbeddedViewRef<any>)
.rootNodes[0] as HTMLElement;
// Append DOM element to the body
document.body.appendChild(domElem);
// Append DcontentElemOM element to the body
domElem.querySelector("#modalHoster").appendChild(contentElem);
// Wait some time and remove it from the component tree and from the DOM
this.data[obj.id]={
componentRefer: componentRefer,
appRef: this.appRef
}
this.last=obj;
return obj.id;
}
pull(){
return this.last;
}
close(id){
this.data[id].appRef.detachView(this.data[id].componentRefer.hostView);
}
}
component.ts
import { Component, OnInit } from '@angular/core';
import { ModalService } from '../../services/modal.service';
@Component({
selector: 'modal',
templateUrl: './modal.component.html',
styleUrls: ['./modal.component.scss']
})
export class ModalComponent implements OnInit {
close(){
this.mod.close(this.id);
}
constructor(private mod: ModalService){}
ngOnInit() {
let obj=this.mod.pull();
for(let key in obj){
this[key]=obj[key];
}
}
}
可能是我的逻辑是错误的,这就是我要问的。这两个服务和组件位于模块内部,而不是应用程序中。仅使用该服务的应用,无法访问该组件。服务需要一段html / css / ts代码作为应用程序提供的那段html / css / ts代码的容器。
答案 0 :(得分:3)
您的逻辑在这里并没有错,但是您可以轻松避免循环依赖。
您确定需要服务中的组件才能创建新实例。但是,您实际上并不需要模态内部的服务。
您可以做的是在模态中添加一个可观察的主题。当您实例化模态时,您可以在服务中订阅该主题以从容器中删除对话框。
这是一个简单的代码示例:)
在您的模式组件中:
private modalClose: Subject<any> = new Subject();
onModalClose(): Observable<any> {
return this.modalClose.asObservable();
}
close() { // Will be generally called from the UI (close button for example)
this.modalClose.next();
this.modalClose.complete();
}
为您服务:
componentRefer.instance.onModalClose().subscribe( () => {
// Here you close your modal :D
});
有关更多信息:
在这里您可以找到我自己的“模态/对话框”。
https://github.com/xrobert35/asi-ngtools/tree/master/src/components/asi-dialog
要实例化对话框,必须使用该服务。该服务管理一个“容器”,该容器可以具有“许多”对话框。使用相同的技术,我没有循环依赖。
在这里您可以找到该组件的有效示例:https://ng-tools.asi.fr/views/showroom/asi-ngtools/components/asi-dialog