Skip to content

Commit cd4be24

Browse files
Merge pull request #3 from OsamaAlRashed/Fix-Gridazor-Dropdown-Issue
Fix #2
2 parents 8ec5ed2 + d14bac1 commit cd4be24

3 files changed

Lines changed: 76 additions & 29 deletions

File tree

Demo/Controllers/HomeController.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@ public IActionResult Index()
6060
new(2, "Category 2")
6161
};
6262

63+
var subCats = new List<SubCategory>()
64+
{
65+
new(1, "Sub Cat 1-1", 1),
66+
new(2, "Sub Cat 1-2", 1),
67+
new(3, "Sub Cat 2-1", 2),
68+
new(4, "Sub Cat 2-2", 2),
69+
};
70+
71+
ViewBag.SubCategories = subCats;
72+
6373
ViewBag.QualityList = Enum.GetValues<Quality>()
6474
.Select(x => new SelectDto((int)x, x.ToString()))
6575
.ToList();
@@ -102,7 +112,7 @@ public IActionResult GetCategories(string search)
102112
}
103113

104114
[HttpGet]
105-
public IActionResult GetSubCategories(string search, List<int> categoryIds)
115+
public IActionResult GetSubCategories(int categoryId, string search)
106116
{
107117
var subCats = new List<SubCategory>()
108118
{
@@ -112,8 +122,9 @@ public IActionResult GetSubCategories(string search, List<int> categoryIds)
112122
new(4, "Sub Cat 2-2", 2),
113123
};
114124

115-
return Json(subCats.Where(x => string.IsNullOrEmpty(search) || x.Name.Contains(search))
116-
.Where(x => categoryIds.Contains(x.CatId))
125+
return Json(subCats
126+
.Where(x => string.IsNullOrEmpty(search) || x.Name.Contains(search))
127+
.Where(x => x.CatId == categoryId)
117128
.Select(x =>
118129
new {
119130
text = x.Name,

Demo/Views/Home/Index.cshtml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
text: item.name
5858
}))
5959
},
60+
onCellValueChanged: (params) => gridazorDropdownHelper.resetDependentValue(params, 'subCatId'),
6061
valueFormatter: (params) => gridazorDropdownHelper.valueFormatter(params)
6162
},
6263
{
@@ -65,10 +66,10 @@
6566
cellEditorParams: params => {
6667
return {
6768
searchUrl: "Home/GetSubCategories?categoryId=" + params.data.catId,
68-
values: subCategories.map(item => ({
69+
values: subCategories.filter(item => item.catId === params.data.catId).map(item => ({
6970
value: item.id,
7071
text: item.name
71-
})) // for the first load
72+
})) // Initial values based on current selection
7273
};
7374
},
7475
valueFormatter: (params) => gridazorDropdownHelper.valueFormatter(params)

Demo/wwwroot/lib/gridazor/gridazor.js

Lines changed: 59 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -351,30 +351,26 @@ class GridazorDropdown {
351351
this.options = params.values || [];
352352
this.selectedValue = params.value;
353353
this.searchUrl = params.searchUrl;
354+
this.params = params;
354355

355-
// Create container and input
356356
this.eGui = document.createElement('div');
357357
this.eGui.classList.add('gridazor-select-wrapper');
358-
359358
this.eInput = document.createElement('input');
360359
this.eInput.classList.add('gridazor-select');
361360
this.eInput.value = this.getTextByValue(this.selectedValue);
362361
this.eGui.appendChild(this.eInput);
363362

364-
// Create dropdown
365363
this.eDropdown = document.createElement('div');
366364
this.eDropdown.classList.add('gridazor-dropdown');
367365
this.eDropdown.style.display = 'none';
368366
this.eGui.appendChild(this.eDropdown);
369367

370-
// Event listeners
371368
this.eInput.addEventListener('input', () => this.filterOptions(this.eInput.value));
372369
this.eInput.addEventListener('focus', () => this.showDropdown());
373370
document.addEventListener('click', (event) => {
374371
if (!this.eGui.contains(event.target)) this.hideDropdown();
375372
});
376373

377-
// Initial render
378374
this.renderDropdown(this.options);
379375
}
380376

@@ -404,50 +400,68 @@ class GridazorDropdown {
404400

405401
renderDropdown(options) {
406402
this.eDropdown.innerHTML = ''; // Clear dropdown content
403+
404+
if (options.length === 0) {
405+
const noResultsElement = document.createElement('div');
406+
noResultsElement.classList.add('gridazor-dropdown-item', 'no-results');
407+
noResultsElement.textContent = 'No options available';
408+
this.eDropdown.appendChild(noResultsElement);
409+
return;
410+
}
411+
407412
options.forEach(option => {
408413
const optionElement = document.createElement('div');
409414
optionElement.classList.add('gridazor-dropdown-item');
410415
optionElement.textContent = option.text;
411-
412416
if (option.value === this.selectedValue) {
413417
optionElement.classList.add('selected');
414418
}
415-
416419
optionElement.addEventListener('click', () => {
417420
this.selectedValue = option.value;
418421
this.eInput.value = option.text;
419422
this.hideDropdown();
420423
});
421-
422424
this.eDropdown.appendChild(optionElement);
423425
});
424426
}
425427

426428
filterOptions(query) {
427-
const localOptions = this.options.filter(option =>
428-
option.text.toLowerCase().includes(query.toLowerCase())
429-
);
430-
431-
if (localOptions.length || !this.searchUrl) {
432-
this.renderDropdown(localOptions);
429+
if (this.searchUrl) {
430+
this.fetchOptions(query).then(filteredOptions => {
431+
this.renderDropdown(filteredOptions);
432+
});
433433
} else {
434-
this.fetchOptions(query).then(filteredOptions => this.renderDropdown(filteredOptions));
434+
const localOptions = this.options.filter(option =>
435+
option.text.toLowerCase().includes(query.toLowerCase())
436+
);
437+
this.renderDropdown(localOptions);
435438
}
436439
}
437440

438441
fetchOptions(query) {
439-
return fetch(`${this.searchUrl}?search=${encodeURIComponent(query)}`)
442+
let url = this.searchUrl;
443+
444+
if (query) {
445+
url += url.includes('?') ? '&' : '?';
446+
url += `search=${encodeURIComponent(query)}`;
447+
}
448+
449+
return fetch(url)
440450
.then(response => response.ok ? response.json() : [])
441-
.catch(error => console.error('Error fetching options:', error));
451+
.catch(error => {
452+
console.error('Error fetching options:', error);
453+
return [];
454+
});
442455
}
443456

444457
getTextByValue(value) {
458+
if (value === null || value === undefined) return '';
459+
445460
const selectedOption = this.options.find(option => option.value === value);
446-
return selectedOption ? selectedOption.text : '';
461+
return selectedOption ? selectedOption.text : value.toString();
447462
}
448463
}
449464

450-
451465
// Helpers
452466
var gridazorDateInputHelper = {
453467
valueGetter: function (p) {
@@ -471,12 +485,33 @@ var gridazorFileInputHelper = {
471485
}
472486
};
473487

474-
var gridazorDropdownHelper = {
488+
const gridazorDropdownHelper = {
475489
valueFormatter: function (params) {
476-
console.log(params)
477-
const option = params.colDef.cellEditorParams.values
478-
.find(opt => opt.value === params.value);
490+
if (params.value === null || params.value === undefined) {
491+
return '';
492+
}
493+
494+
const editorParams = typeof params.colDef.cellEditorParams === 'function'
495+
? params.colDef.cellEditorParams(params)
496+
: params.colDef.cellEditorParams;
479497

480-
return option ? option.text : params.value;
498+
if (editorParams && Array.isArray(editorParams.values)) {
499+
const option = editorParams.values.find(opt => opt.value === params.value);
500+
if (option) {
501+
return option.text;
502+
}
503+
}
504+
505+
return params.value.toString();
506+
},
507+
resetDependentValue: function (params, childField) {
508+
if (params.oldValue !== params.newValue) {
509+
params.data[childField] = null;
510+
params.api.refreshCells({
511+
rowNodes: [params.node],
512+
columns: [childField],
513+
force: true
514+
});
515+
}
481516
}
482517
};

0 commit comments

Comments
 (0)