Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
@rign/angular2-tree
Advanced tools
Simple component to display tree structure
npm i @rign/angular2-tree --save
It also require to install dependencies:
You can install them using below command:
npm i @angular/cdk @angular/common @angular/core @angular/forms @angular/http @ngrx/core @ngrx/effects @ngrx/store angular2-uuid bootstrap core-js font-awesome lodash.isequal ng2-dnd ngx-contextmenu rxjs zone.js --save
First you have to create your own loader service
@Injectable()
export class AppNodeService extends NodeService {
public get treeId(): string {
return 'tree3';
}
protected apiConfig = {
addUrl: '/api/nodes',
getUrl: '/api/nodes',
updateUrl: '/api/nodes',
removeUrl: '/api/nodes',
}
}
and use it to load/save/delete/etc. your node data. Or you can extend and rewrite all methods of that service to store your data wherever you want. See example localStorage.service.ts
Include TreeModule in your application module and create Store with empty state and initialize Effects. Do not forget to pass yours AppNodesService as a parameter of TreeModule.
import {TreeModule} from '@rign/angular2-tree';
@NgModule({
declarations: [
...
],
imports: [
...
TreeModule.forRoot(AppNodeService),
EffectsModule.forRoot([]),
StoreModule.forRoot({})
]
})
You need also init animations module, because Tree needs it to animate expanding and collapsing node.
@NgModule({
declarations: [
...
],
imports: [
...
BrowserAnimationsModule,
TreeModule.forRoot()
]
})
In any html file put
<ri-tree [treeModel]="treeModel"></ri-tree>
In component where you create tree, you should create TreeModel passing configuration and AppNodeService.
export class MyTreeComponent implements OnInit {
public folders: Observable<ITreeData>;
public contextMenu: IContextMenu[] = [];
public treeConfiguration: IConfiguration = {
showAddButton: true,
disableMoveNodes: false,
treeId: 'tree3',
dragZone: 'tree3',
dropZone: ['tree3'],
isAnimation: true // add animation to action "expand" and "collapse"
};
public treeModel: TreeModel;
public constructor(private treeInitializerService: TreeInitializerService,
private appNodeService: AppNodeService) {
}
public ngOnInit(): void {
const nodes: IOuterNode[] = JSON.parse(localStorage.getItem('treeOne')) || [];
this.treeModel = this.treeInitializerService.init(this.treeConfiguration, this.appNodeService, nodes);
}
}
If function init has got third parameter - array of nodes, then the tree will be marked as fully loaded. It will not use load API function to get new subnodes it will use only passed nodes.
To load default CSS styles and makes our tree looks nice you have to add 2 CSS files to your angular-cli.json file:
...
"styles": [
"../node_modules/bootstrap/dist/css/bootstrap.css",
"../node_modules/font-awesome/css/font-awesome.css",
"styles.css"
],
Also you can use your own template to display items. You can do that when you extend ItemComponent
@Component({
selector: 'new-tree-item',
templateUrl: './newItem.component.html',
styleUrls: ['./newItem.component.scss']
})
export class NewItemComponent extends ItemComponent {
}
and newItem.component.html
<div class="tree-item row"
[ngClass]="{'tree-item-selected': isSelected}"
riDroppable
riDraggable
[dragZone]="treeModel.configuration.dragZone"
[dropConfig]="{dropAllowedCssClass: 'drop-enabled', dropZone: treeModel.configuration.dropZone}"
[data]="node"
id="node-{{node-id}}"
>
<div class="col-sm-8">
<i *ngIf="!isExpanded" (click)="expand()" class="fa fa-plus pointer"></i>
<i *ngIf="isExpanded" (click)="collapse()" class="fa fa-minus pointer"></i>
<span *ngIf="!isEditMode" class="tree-item-name" (click)="onSelect()">{{node.name}}</span>
<form name="form">
<input #inputElement type="text" class="form-control" *ngIf="isEditMode" [formControl]="nameField"
name="name" (keydown)="onChange($event)" (blur)="onBlur($event)"/>
</form>
</div>
<div class="col-sm-4 text-right">
<span class="btn-group btn-group-sm">
<button class="btn btn-primary" (click)="onEdit($event)" [disabled]="isEditMode">
<i class="fa fa-edit"></i>
</button>
<button class="btn btn-danger" (click)="onDelete()" [disabled]="isEditMode">
<i class="fa fa-trash"></i>
</button>
</span>
</div>
</div>
<div class="tree" *ngIf="isExpanded" [@expand]>
<ri-tree-item *ngFor="let child of children$ | async" [node]="child; trackBy: trackByFn"
[treeModel]="treeModel"
[isExpanded]="treeModel.isExpanded(child)"
[isSelected]="treeModel.isSelected(child)"
[contextMenu]="contextMenu"></ri-tree-item>
</div>
Then when you create tree component in your application use such construction
<rign-tree [treeModel]="treeModel">
<new-tree-item *ngFor="let node of treeModel.getRootNodes() | async; trackBy: trackByFn"
[node]="node"
[treeModel]="treeModel"
[isSelected]="treeModel.isSelected(node)"
[isExpanded]="treeModel.isExpanded(node)"
[contextMenu]="contextMenu"></new-tree-item>
</rign-tree>
and that is all. Please see Demo where is such example.
If you would like to open some path at the begin you can do that invoking such method after creating TreeModel.
this.treeModel.initPath([
// list of node ids sorted by level of node (grandparent id, parent id, child id)
]);
From version 3.0.1 there is possibility to display current selected node path. To do that place in your component html file such code:
<ri-tree-parents-list [treeModel]="treeModel"></ri-tree-parents-list>
The treeModel value is the same object that is used in ri-tree.
Using ngrx/store you can listen on below actions and do whatever you want:
TreeActionTypes.TREE_SAVE_NODE
TreeActionTypes.TREE_SAVE_NODE_ERROR
TreeActionTypes.TREE_SAVE_NODE_SUCCESS
TreeActionTypes.TREE_DELETE_NODE
TreeActionTypes.TREE_DELETE_NODE_ERROR
TreeActionTypes.TREE_DELETE_NODE_SUCCESS
TreeActionTypes.TREE_EDIT_NODE_START
TreeActionTypes.TREE_EXPAND_NODE
TreeActionTypes.TREE_LOAD
TreeActionTypes.TREE_LOAD_ERROR
TreeActionTypes.TREE_LOAD_SUCCESS
TreeActionTypes.TREE_LOAD_PATH
TreeActionTypes.TREE_MOVE_NODE
TreeActionTypes.TREE_MOVE_NODE_ERROR
TreeActionTypes.TREE_MOVE_NODE_SUCCESS
TreeActionTypes.TREE_REGISTER
TreeActionTypes.TREE_SET_ALL_NODES
TreeActionTypes.TREE_SELECT_NODE
From version 5.0.0 translation dependency is removed from @rign/angular2-tree. Now you have to create service which implements ITreeTranslation interface:
import {ITreeTranslations} from '@rign/angular2-tree';
export class TreeTranslationService implements ITreeTranslations {
readonly RI_TREE_LBL_ADD_NODE = 'Add data';
readonly RI_TREE_LBL_EDIT_NODE = 'Edit data';
readonly RI_TREE_LBL_REMOVE_NODE = 'Delete data';
readonly RI_TREE_LBL_DROP_ZONE = 'Drop here to move data to root level';
}
and set is as provider in module which use TreeModule
providers: [
TreeOneNodeService,
{provide: TREE_TRANSLATION_TOKEN, useClass: TreeTranslationService},
]
In such case you can use your own translation module and its implementation or even if you don't use translations in your app, you don't have to import additional dependency.
Now you have new possibilities to move different elements to the tree (files or other data). To do that, you have to use riDraggable directive in following way
<div ri-draggable [dragZone]="treeModel.configuration.dragZone" [data]="your_data" [sourceType]="'YOUR_SOURCE_TYPE'">Drag element</div>
where:
Then you have to create @Effects similar to that one in _treeEffects.service_or create only Observable and subscribe to it.
@Effect() move$ = this.actions$
.pipe(
ofType(TreeActionTypes.TREE_MOVE_NODE),
filter((action: ITreeAction) => {
return action.payload.sourceOfDroppedData === DragAndDrop.DROP_DATA_TYPE;
})
)
...
but you have to replace
ofType(TreeActionTypes.TREE_MOVE_NODE)
to
ofType('YOUR_SOURCE_TYPE')
At the end do not forget to add this effects to your app.
Working demo with local storage you can find here. To run Demo locally clone this repository and run
ng start --project=tree-example
Licensed under MIT.
FAQs
Tree component display tree structure
We found that @rign/angular2-tree demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.