I'm enhancing the Admin Category List page to include Search capability. I've modeled the enhancements based on the product search page. However, I must be missing some Telerik magic, because the page is returning JSON rather than HTML - it looks like this:
{"Data":[],"Total":24,"Aggregates":null}
The only real change I've made to the List.cshtml section Html.Telerik().Grid<CategoryModel> is to add .ClientEvents(events => events.OnDataBinding("onDataBinding"))
I'm sure I'm missing something else. I haven't worked much with Telerik. Maybe someone can also explain how the non-HttpPost ActionResult List() can return View(...), whereby the HttpPost List can "return new JsonResult {...} "
CategoryController.cs This is a work in progress, but in brief, the original code is in the 'then' part of if-then-else, and new code is in the 'else' part - depending on if a search string is passed in from form submit. Doing my own "PagedList" via skip/take, because of desired sort.
...
[HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult List(GridCommand command, CategoryListModel categoryListModel) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView();
if (String.IsNullOrWhiteSpace(categoryListModel.SearchCategoryName)) { var categories = _categoryService.GetAllCategories(command.Page - 1, command.PageSize, true); var gridModel = new GridModel<CategoryModel> { Data = categories.Select(x => { var model = x.ToModel(); model.Breadcrumb = x.GetCategoryBreadCrumb(_categoryService); return model; }), Total = categories.TotalCount }; return new JsonResult { Data = gridModel }; } else { var categories = _categoryService.SearchCategories(categoryListModel.SearchCategoryName, true); var data = categories.Select(x => { var model = x.ToModel(); model.Breadcrumb = x.GetCategoryBreadCrumb(_categoryService); return model; }) .OrderBy(m => m.Breadcrumb) .Skip((command.Page - 1) * command.PageSize).Take(command.PageSize);
var gridModel = new GridModel<CategoryModel> { Data = data, Total = categories.Count() }; return new JsonResult { Data = gridModel }; } }
and here's my SearchCategories which is in CategoryService
public virtual IList<Category> SearchCategories(string name, bool showHidden = false)
and I should mention everything worked fine in my first round of refactoring - i.e. prior to changing from CategoryModel to CategoryListModel - search results were returned in the HttpPost List(), when I hard coded a search string in the controller
public ActionResult List() { if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView();
var categories = _categoryService.GetAllCategories(0, _adminAreaSettings.GridPageSize, true); var model = new CategoryListModel(); model.Categories = new GridModel<CategoryModel> { Data = categories.Select(x => { var categoryModel = x.ToModel(); categoryModel.Breadcrumb = x.GetCategoryBreadCrumb(_categoryService); return categoryModel; }), Total = categories.TotalCount }; return View(model); }
To summarize my changed: 1. Modified List() method (non-POST) in CategoryController 2. Replaced $('#search-products').click(function () { with $('#search-categories').click(function () { 3. onDataBinding java-script function should not be inside $(document).ready handler P.S. Tested. Everything works fine
Thanks so much Andrei. The cut/paste anti pattern strikes again! And especially I thought I'd carefully replaced all "products" with "categories". (P.S. Sorry I forgot to also send you the non-post List() ; I'd already made those adjustments).
All is working nicely now. Soon ready to release to you for possible inclusion in the core; some nice features I hope you'll want to include:
1) Search categories by name (contains text) 2) Export categories to Excel 3) Import categories from Excel And maybe if I have time... Additional "tree" Import/Export capability that would allow Excel sheet to look like cat1 cat2a cat2b cat3 cat2c ... (would handle any # of levels)
Any thoughts on my if-then-else, and OrderBy breadcrumb. I think it's correct that when searching, that the results return sorted alphabetically.
Actually, I do note that the existing GetAllCategories may not be quite right in regard to the orderby. It uses ParentCategoryId, not the Parent's DisplayOrder. Is that by design?
public virtual IList<Category> GetAllCategories(bool showHidden = false) { var query = from c in _categoryRepository.Table orderby c.ParentCategoryId, c.DisplayOrder where (showHidden || c.Published) && !c.Deleted select c; ...
In any case, when it's all sorted out (no pun intended) :), there are several files changed - what would be the best way for me to get them to you?: