Perhaps a little more than necessary, but consider the following:
You can set the top node (null will default to the entire hierachy)
You also can set a filter. This can be empty for no filter, a single ID, or a delimited string of IDs.
Declare @T table (id int,nameVal varchar(50),parentId int)
Insert into @T values
(1 ,'A', NULL),
(2 ,'B', NULL),
(3 ,'C', NULL),
(4 ,'D', NULL),
(5 ,'E', NULL),
(6 ,'A1', 1),
(7 ,'A2', 6),
(8 ,'A3', 1),
(9 ,'A4', 7),
(10 ,'B1', 2),
(11 ,'B2', 2)
Declare @Top int = null --<< Sets top of Hier Try 6
Declare @Nest varchar(25) = '|-----' --<< Optional: Added for readability
Declare @Filter varchar(25) = '7' --<< Empty for All or try '7,10'
;with cteP as (
Select Seq = cast(10000+Row_Number() over (Order by nameVal) as varchar(500))
,ID
,parentId
,Lvl=1
,nameVal
From @T
Where IsNull(@Top,-1) = case when @Top is null then isnull(parentId,-1) else ID end
Union All
Select Seq = cast(concat(p.Seq,'.',10000+Row_Number() over (Order by r.nameVal)) as varchar(500))
,r.ID
,r.parentId
,p.Lvl+1
,r.nameVal
From @T r
Join cteP p on r.parentId = p.ID)
,cteR1 as (Select *,R1=Row_Number() over (Order By Seq) From cteP)
,cteR2 as (Select A.Seq,A.ID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.ID )
,cte as (
Select A.R1
,B.R2
,A.ID
,A.parentId
,A.Lvl
,nameVal = Replicate(@Nest,A.Lvl-1) + A.nameVal
From cteR1 A
Join cteR2 B on A.ID=B.ID
)
Select Distinct A.*
From cte A
Join (
Select A.R1,A.R2
From cte A
Join (Select R1 from cte Where IIF(@Filter='',1,0)+CharIndex(concat(',',ID,','),concat(',',@Filter+','))>0) B
on B.R1 between A.R1 and A.R2
) B on A.R1 between B.R1 and B.R2
Order By A.R1
Returns

Now, if you set @Filter = '7,10'
, you'll get

If you set @Filter = ''
, you'll get
