I am trying to ensure that only leaf (child) nodes can be selected in the Kendo DropDownTree for Angular. If a parent node is clicked, the selection should be cleared and the input should display as empty (no value/placeholder).
What I am experiencing:
After selecting a child node (leaf), the value is set correctly.
If I later click a parent node, I set
value = null
in thevalueChange
event handler.However, when I close and reopen the dialog containing the DropDownTree, the input always shows the last selected child (even though
value
isnull
).The value for the input box is not showing null; the last valid child selection keeps coming back after reopening.
Summary of what I have tried:
Handled
valueChange
to only accept leaf node selections and setvalue = null
for parents.Verified that
value
isnull
when closing the dialog.
Expected behavior:
When a parent node is clicked, any selection should be cleared, and upon reopening the dialog, the DropDownTree input should remain empty (showing no last selection).
Actual behavior:
After clicking a parent and setting value = null
, closing and reopening the dialog always shows the last selected child in the DropDownTree input.
<mnp-dialog
class="feedback-dialog-wrapper"
[width]="width"
[height]="height"
[isOpen]="isOpen"
[title]="confirmationTitle"
(close)="close()">
<div class="feedback">
<div>{{ confirmationMessage }}</div>
<div class="k-form-field-wrap">
<kendo-dropdowntree
kendoDropDownTreeExpandable
[kendoDropDownTreeHierarchyBinding]="data"
childrenField="items"
textField="text"
valueField="id"
[valuePrimitive]="true"
[(value)]="value"
[filterable]="true"
(valueChange)="onValueChange($event)"
(close)="closeEvent($event)"
>
<ng-template kendoDropDownTreeValueTemplate let-dataItem>
<ng-container *ngIf="!dataItem?.items || dataItem?.items.length === 0">
<span class="template">{{ dataItem?.text }}</span>
</ng-container>
</ng-template>
<ng-template kendoDropDownTreeNodeTemplate let-dataItem let-index="index">
<span
[ngClass]="{
'parent-node': dataItem.items?.length > 0,
'child-node': !dataItem.items || dataItem.items.length === 0
}">
{{ dataItem.text }}
</span>
</ng-template>
</kendo-dropdowntree>
</div>
</div>
<kendo-dialog-actions>
<mnp-button id="confirmaion-cancel-btn" fillMode="outline" (click)="close()">{{
confirmationCancelBtn
}}</mnp-button>
<mnp-button id="confirmaion-submit-btn" [disabled]="value === null" (click)="submit()">{{ confirmationSubmitBtn }}</mnp-button>
</kendo-dialog-actions>
</mnp-dialog>
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core';
import { TranslocoModule } from '@jsverse/transloco';
import { ActionsLayout, KENDO_DIALOGS } from '@progress/kendo-angular-dialog';
import { ButtonComponent, DialogComponent, LabelComponent } from '@mnp-firm-it/angular-ui-components';
import { KENDO_DROPDOWNS } from '@progress/kendo-angular-dropdowns';
import { KENDO_LABELS } from '@progress/kendo-angular-label';
import { HierarchicalItem } from '../../../models/contract-models';
@Component({
selector: 'app-manual-confirmation',
templateUrl: './manual-confirmation.component.html',
styleUrls: ['./manual-confirmation.component.scss'],
standalone: true,
encapsulation: ViewEncapsulation.None,
imports: [
CommonModule,
DialogComponent,
KENDO_DROPDOWNS,
KENDO_DIALOGS,
ButtonComponent,
TranslocoModule,
KENDO_LABELS
]
})
export class ManualConfirmationComponent {
@Input() actionsLayout: ActionsLayout = 'stretched';
@Input() isOpen = false;
@Input() confirmationTitle = 'title';
@Input() confirmationMessage = 'message';
@Input() confirmationCancelBtn = 'Cancel';
@Input() confirmationSubmitBtn = 'Submit';
@Input() data: HierarchicalItem[] = [];
@Input() width = '250';
@Input() height = '250';
@Output() closed = new EventEmitter<void>();
value: number | null = null;
@Output() submitted = new EventEmitter<boolean>();
close() {
this.value = null;
this.closed.emit();
this.submitted.emit(false);
}
submit() {
this.submitted.emit(true);
this.close();
}
onValueChange(selectedId: any) {
this.value = null;
const findItem = (items: any[]): any =>
items.reduce((acc, item) => {
if (item.id === selectedId) return item;
if (item.items) {
const found = findItem(item.items);
if (found) return found;
}
return acc;
}, null);
const selectedItem = findItem(this.data);
console.log('Selected Item:', selectedItem);
if (!selectedItem.items) {
this.value = selectedId;
} else {
console.log('iam here');
this.value = null;
}
}
closeEvent(event: any): void {
if (this.value === null) {
event.preventDefault();
}
}
}