Issue
I have a problem in a edit form with PrimeNG Tree or TreeSelect component (I tried both). The thing is data are provided by an API in the form of entity with an ID, a project, a product and a version. In theory, a project can contains many products and a product can contains many versions (this is why I display in tree). So I transform datas from API in a node model. For the creation form, no problem, but for the edit form, impossible to display preselected datas efficiently. The best I can do is the last childrens (versions) are selected but not parents and parents are not expanded.
component.ts :
productSoftwareVersionsNodes: TreeNode[] = [];
productSoftwareVersionsSelected: TreeNode[] = [];
versionToTreeNode(version: IVersionForNode): TreeNode {
return {
label: version.version,
data: version.id,
key: version.id!.toString()
}
}
productToTreeNode(product: IProductForNode, project: IProjectForNode): TreeNode {
const versionsNodes: TreeNode[] = [];
if(product.versions !== undefined){
product.versions.forEach(version => versionsNodes.push(this.versionToTreeNode(version)));
}
return {
label: product.product,
key: project.project + "_" + product.product,
selectable: false,
data: product.product,
children: versionsNodes
}
}
projectToTreeNode(project: IProjectForNode): TreeNode {
const productsNodes: TreeNode[] = [];
if(project.products !== undefined){
project.products.forEach(product => productsNodes.push(this.productToTreeNode(product, project)));
}
return {
label: project.project,
data: project.project,
key: project.project,
selectable: false,
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
icon: 'flag-icon flag-icon-' + project.countryCode,
children: productsNodes
}
}
selectedVersionToTreeNode(project: IProjectForNode, product: IProductForNode,version: IVersionForNode): TreeNode {
const projectNode: TreeNode = {
label: project.project,
data: project.project,
key: project.project,
selectable: false,
expanded: true,
partialSelected: true,
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
icon: 'flag-icon flag-icon-' + project.countryCode
};
const productNode: TreeNode = {
label: product.product,
data: product.product,
key: project.project + "_" + product.product,
selectable: false,
expanded: true,
partialSelected: true,
parent: projectNode
};
return {
label: version.version,
data: version.id,
key: version.id!.toString(),
parent: productNode
}
}
setNodes(inputProductSoftwareVersions: IProjectForNode[]): void {
inputProductSoftwareVersions.forEach(productSoftwareVersion => this.productSoftwareVersionsNodes.push(this.projectToTreeNode(productSoftwareVersion)));
}
setProductSoftwareVersionsSelected(inputProductSoftwareVersions: IProjectForNode[]): void {
inputProductSoftwareVersions.forEach(project => {
project.products!.forEach(product => {
product.versions!.forEach(version => {
this.productSoftwareVersionsSelected.push(this.selectedVersionToTreeNode(project, product, version));
})
})
});
}
component.html :
<p-treeSelect [(ngModel)]="productSoftwareVersionsSelected" display="chip" [metaKeySelection]="false"
[ngModelOptions]="{standalone: true}" data-cy="productSoftwareVersion" name="productSoftwareVersion"
selectionMode="multiple" id="field_productSoftwareVersion" class="pl-0" type="productSoftwareVersion"
aria-describedby="productSoftwareVersion-help" [options]="productSoftwareVersionsNodes"
(onNodeUnselect)="nodeUnselected($event)" (onNodeSelect)="nodeSelected($event)">
</p-treeSelect>
The kind of node I build :
[{ data: "62bbf3bc16403b596805f6ff"
key: "62bbf3bc16403b596805f6ff"
label: "1.2.3"
parent: {
data: "TEST"
expanded: true
key: "TEST"
label: "TEST"
parent: {
data: "TEST2"
expanded: true
icon: "flag-icon flag-icon-gb"
key: "TEST2"
label: "TEST2"
partialSelected: true
}
selectable: false
partialSelected: true
selectable: false
}
}]
Data from a node selected on click:
[{ data: "62bbf3d816403b596805f701"
key: "62bbf3d816403b596805f701"
label: "1.2.4"
parent: {
children: (3) [{…}, {…}, {…}]
data: "TEST"
expanded: true
key: "TEST"
label: "TEST"
parent: {
children: (3) [{…}, {…}, {…}]
data: "TEST2"
expanded: true
icon: "flag-icon flag-icon-gb"
key: "TEST2"
label: "TEST2"
parent: undefined
selectable: false
}
selectable: false
}
}]
If someone has an idea... Thanks !
Solution
I found solution. The key is to work with nodes in options and filter them:
// Preselect nodes for the editForm
setProductSoftwareVersionsSelected(productSoftwareVersionsList: IProductSoftwareVersion[]): void {
// Get all productSoftwareVersions id from the editForm in an array
const productSoftwareVersionIdList: string[]= productSoftwareVersionsList.flatMap(p => p.id?.toString()) as string[];
// Set the selected nodes by filtering all nodes with the array of ids
this.productSoftwareVersionsSelected = this.productSoftwareVersionsNodes.flatMap(n => n.children).flatMap(c => c?.children).filter(v => v?.key !== undefined && productSoftwareVersionIdList.includes(v.key)) as TreeNode[];
}
Answered By - Collembole
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.