Angular 6循环依赖逻辑解决方案

时间:2018-09-15 22:50:02

标签: angular

我有逻辑上的问题。我需要将要导入服务内部的组件,并在需要该服务的组件内部并行。错误如下: 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代码的容器。

1 个答案:

答案 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