I am creating this nested tree view component in Angular. All the stylings are working fine but for the nested tree first element extra space is getting added before the text which i am not able to figure out. Here is the stackblitz for the project that i am working on Stackblitz
tree.component.css
.open-btn {
float: left;
transform: rotate(90deg);
position: relative;
left: -30px;
z-index: 10;
}
.close-btn {
float: left;
left: -30px;
position: relative;
z-index: 10;
}
.tree li {
list-style-type: none;
margin: 10px;
position: relative;
}
.arrow-btn {
width: 18px;
height: 18px;
}
.tree li::before {
content: '';
position: absolute;
top: -7px;
left: -20px;
border-left: 1px solid #ccc;
border-bottom: 1px solid #ccc;
border-radius: 0 0 0 0px;
width: 20px;
height: 15px;
}
.tree li::after {
position: absolute;
content: '';
top: 8px;
left: -20px;
border-left: 1px solid #ccc;
border-top: 1px solid #ccc;
border-radius: 0px 0 0 0;
width: 20px;
height: 100%;
}
.tree li:last-child::after {
display: none;
}
.tree li:last-child:before {
border-radius: 0 0 0 5px;
}
ul.tree > li:first-child::before {
border-left: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.label-container {
display: inline-block;
/* background-color: rgb(123, 212, 239); */
}
tree.component.ts
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { TreeNode } from './tree-mock';
@Component({
selector: 'app-tree',
templateUrl: './tree.component.html',
styleUrls: ['./tree.component.css'],
})
export class TreeComponent {
@Input() tree: any;
@Output() selectedValue = new EventEmitter<any>();
toggleChild(node) {
this.selectedValue.emit(node);
node.showChildren = !node.showChildren;
node.isOpen = !node.isOpen;
}
/* Events are not bubbled up so emitting the parent event on <app-tree>
* when one of the child emits an event - this will create a new EventEmitter per child.
*/
emitOnChildClicked(node) {
this.selectedValue.emit(node);
}
}
tree.component.html
<ul *ngIf="tree" class="tree">
<li *ngFor="let node of tree">
<div class="label-container" (click)="toggleChild(node)">
<span *ngIf="node.children != 0">
<img
src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/9d/Icons8_flat_document.svg/512px-Icons8_flat_document.svg.png"
class="arrow-btn"
[ngClass]="
!node.children ? 'doc' : node.isOpen ? 'open-btn' : 'close-btn'
"
/>
</span>
<span> {{ node.name }} </span>
</div>
<app-tree
*ngIf="node.showChildren"
(selectedValue)="emitOnChildClicked($event)"
[tree]="node.children"
></app-tree>
</li>
</ul>
tree-mock.ts
export interface TreeNode {
name: string;
showChildren: boolean;
children: any[];
}
export const NODES: TreeNode[] = [
{
name: 'Africa',
showChildren: false,
children:[
{
name : 'Algeria',
showChildren: false,
children:[
{
name : 'Algeris',
showChildren: false,
children:[]
},
{
name : 'Algeria child 2',
showChildren: false,
children:[
]
},
]
},
{
name : 'Angola',
showChildren: false,
children:[]
},
{
name : 'Benin',
showChildren: false,
children:[]
},
]
},
{
name: 'Asia',
showChildren: false,
children:[
{
name : 'Afghanistan',
showChildren: false,
children:[
{
name : 'Kabul',
showChildren: false,
children:[]
}
]
},
{
name : 'Armenia',
showChildren: false,
children:[]
},
{
name : 'Azerbaijan',
showChildren: false,
children:[]
},
]
},
{
name: 'Europe',
showChildren: false,
children:[
{
name : 'Romania',
showChildren: false,
children:[
{
name : 'Bucuresti',
showChildren: false,
children:[]
}
]
},
{
name : 'Hungary',
showChildren: false,
children:[]
},
{
name : 'Benin',
showChildren: false,
children:[]
},
]
},
{
name: 'North America',
showChildren: false,
children: []
}
]
The space is from the arrow/close button. Change its position from relative to absolute.
.close-btn {
float: left;
left: -30px;
/* position: relative; */
position: absolute;
z-index: 10;
}
Additionally, the float: left
declaration is unneeded with position: absolute
.