前言
若是想要完成在A.component中打開一個B.component(popup),比較直覺的做法就是在A.html中加入B的selector,並用一個boolean控制是否打開,也就是
<!-- A.html --><app-b
*ngIf = "openB"
>
</app-b>
想一下如果B這個元件想要有其他功能例如:自定義標題與內文、事件監聽,那這時需要的變數不只有openB,還需要加上title與content這些變數以及接收B的事件接收方法,程式碼就會像
<app-b
*ngIf = "openB"
title = "標題"
content = "內文"
(emiter) = "getEmit($event)"
>
</app-b>
若B只單純提供給A使用的話這樣沒什麼問題,但現在有一個情境是:C、D、E、F…等更多的Component中都需要引入B這個popup元件
則用上面的方法就是在C、D、E、F…每個元件中的html寫入,並且在每個元件中的ts也加上openB、title、content、emit,這樣很容易使得程式碼變複雜。
例如:
<!-- B.html -->
<app-b
*ngIf = "openB"
title = "標題"
content = "內文"
(emiter) = "getEmit($event)"
>
</app-b><!-- C.html -->
<app-b
*ngIf = "openB"
title = "標題"
content = "內文"
(emiter) = "getEmit($event)"
>
</app-b> ...<!-- F.html -->
<app-b
*ngIf = "openB"
title = "標題"
content = "內文"
(emiter) = "getEmit($event)"
>
</app-b>
為使每個需要使用B的元件不再需要在各自的html中加上的tag,我們需要建立一個Service來管控這個popup元件(B.component),改成僅需注入Service並呼叫Open()這個Function取代原先的引入行為。
概念
目標:不在負責控制的元件.html中引入被控制的元件,僅使用Service完成打開與關閉的功能
方法:被控制的元件需要一個component及一個Service(也就是B.component與B.service),Service提供給負責控制的元件操作。
負責控制的元件(A.Component)
被控制的元件(B.component)
放個Btn就行了,主要只是看有沒有被Service控製出來
核心操作管道(B.service)
說明:把要被控制的元件(B.component)透過componentFactoryResolver創建出一個元件實體,接著append到畫面上
到這邊就可以完成用Service控制Component是否打開而不需要注入到當前操控的HTML中
傳入參數與監聽事件
例如想將”B元件”三字修改為傳入的參數,以及當B元件被點擊時想讓A元件取得事件觸發該如何處理?
需要在Service的Open的方法中回傳實例對象,則可以透過修改實例對象來達到傳入參數的效果,也可以透過訂閱實例對象達到取得事件觸發
確定目標是要可以傳入跟取得事件觸發後,開始對於負責控制的元件、被控制元件、被控制元件的Service進行修改。
a.component
b.component
b.service