DropdownList

Basic usage



DropdownList with search functionality in the dropdown popup. Can get data from an Url which must return a collection of KeyContent.

Cascade

Binding controls using Parent extension, one control can be bound to multiple others, works for all editor helpers.
Shared/Demos/Cascade.cshtml
@(Html.Awe().DropdownList(new DropdownListOpt
{
Name = "CatDd",
Url = Url.Action("GetCategories", "Data"),
AutoSelectFirst = true
}))

@(Html.Awe().DropdownList(new DropdownListOpt
{
Name = "MealsDd",
AutoSelectFirst = true,
Url = Url.Action("GetMeals", "Data")
}.Parent("CatDd", "categories")))
Awesome/DataController.cs
public IActionResult GetCategories()
{
return Json(mcx.Categories.Select(o => new KeyContent(o.Id, o.Name)));
}

public IActionResult GetMeals(int[] categories)
{
categories = categories ?? new int[] { };
var items = mcx.Meals.Where(o => categories.Contains(o.Category.Id))
.Select(o => new KeyContent(o.Id, o.Name));

return Json(items);
}

DropdownList with grouped items



DropdownList/Index.cshtml

@(Html.Awe().DropdownList(new DropdownListOpt { Name = "MealsGrouped", Url = Url.Action("GetAllMealsGrouped", "Data") }))
Awesome/DataController.cs
public IActionResult GetAllMealsGrouped()
{
var res = new List<Oitem>();
var meals = mcx.Meals.Include(m => m.Category)
.OrderBy(o => o.Id)
.ToArray();

var groups = meals.GroupBy(o => o.Category);

foreach (var g in groups)
{
res.Add(new Oitem
{
Content = g.Key.Name,
Class = "o-itm o-itmg",
NonVal = true,
Items = g.Select(meal => new Oitem(meal.Id, meal.Name)),
});
}

return Json(res);
}

Custom filter function



DropdownList with a custom filter function. The function will receive the query as parameter and must return a filter(content) function.
In this example we could search for "Nolan Bruce" or "Bruce Nolan" (we could also search for "no br"), and we would get the same result with both queries, because we are filtering by each word separately.
Using the default filtering the first query wouldn't return any results.

Tree DropdownList



DropdownList/Index.cshtml
@(Html.Awe().DropdownList(new DropdownListOpt
{
Name = "TreeDropdown1",
Url = Url.Action("GetMealsTreeImg", "Data"),
CollapseNodes = true,
PopupMinWidth = 350,
ClearBtn = true
}.ImgItem()))
Awesome/DataController.cs
public IActionResult GetMealsTreeImg()
{
var url = Url.Content(DemoUtils.MealsUrl);

var res = new List<MealOitem>();
var meals = mcx.Meals.Include(m => m.Category).ToArray();
var groups = meals.GroupBy(o => o.Category);
foreach (var g in groups)
{
res.Add(new MealOitem
{
Content = g.Key.Name,
Class = "o-itm",
NonVal = true,
Items = g.Select(meal => new MealOitem { Key = meal.Id, Content = meal.Name, url = url + meal.Name + ".jpg" })
});
}

return Json(res);
}

DropdownList with submenu



DropdownList/Index.cshtml
@(Html.Awe().DropdownList(new DropdownListOpt 
{
Name = "MealsSbm",
Url = Url.Action("GetMealsTreeImg", "Data"),
Submenu = true
}.ImgItem()))
Awesome/DataController.cs
public IActionResult GetMealsTreeImg()
{
var url = Url.Content(DemoUtils.MealsUrl);

var res = new List<MealOitem>();
var meals = mcx.Meals.Include(m => m.Category).ToArray();
var groups = meals.GroupBy(o => o.Category);
foreach (var g in groups)
{
res.Add(new MealOitem
{
Content = g.Key.Name,
Class = "o-itm",
NonVal = true,
Items = g.Select(meal => new MealOitem { Key = meal.Id, Content = meal.Name, url = url + meal.Name + ".jpg" })
});
}

return Json(res);
}

DropdownList with fav buttons





DropdownList/Index.cshtml
@(Html.Awe().DropdownList(new DropdownListOpt 
{
Name = "AllMealsFav",
Url = Url.Action("GetMealsImg", "Data"),
CssClass = "bigFavs"
}
.ImgItem()
.Favs()))
<br />
<br />
@(Html.Awe().DropdownList(new DropdownListOpt
{
Name = "AllMealsFav2",
Url = Url.Action("GetMealsImg", "Data"),
CssClass = "bigFavs" }
.ImgItem()
.Favs(3, new object[] { DemoCache.Meals[3].Id, DemoCache.Meals[15].Id }, new object[] { DemoCache.Meals[5].Id })))

DropdownList, tree data, lazy nodes, remote search



DropdownList/Index.cshtml
@(Html.Awe().DropdownList(new DropdownListOpt
{
Name = "RmtLazyTree",
Url = Url.Action("GetTreeNodesLazy", "Data"),
ClearBtn = true,
CollapseNodes = true,
PopupMinWidth = 350,
}
.RemoteSearch(Url.Action("SearchTree", "Data"))))
Awesome/DataController.cs
public IActionResult GetTreeNodesLazy(int? key)
{
IEnumerable<Oitem> nodes;

// key has value, lazy request
if (key.HasValue)
{
nodes = buildItemTrees(mcx.TreeNodes.Where(o => o.Id == key));
}
else
{
// initial load, return roots (parent is null)
var roots = mcx.TreeNodes.Where(o => o.Parent == null).OrderBy(o => o.Id).Take(10);
nodes = buildItemTrees(roots, setLazyChild: true);
}

return Json(nodes);
}

/// <summary>
/// builds oitem tree collection from treeNodes collection
/// </summary>
private IEnumerable<Oitem> buildItemTrees(IEnumerable<TreeNode> nodes, int lvl = 0, bool setLazyChild = false)
{
var list = new List<Oitem>();
foreach (var node in nodes)
{
var oitem = new Oitem { Key = node.Id.ToString(), Content = node.Name };
list.Add(oitem);
var children = mcx.TreeNodes.Where(o => o.Parent == node);

if (!children.Any()) continue;

// set node as lazy after lvl 0
if (setLazyChild && lvl > 0)
{
oitem.Lazy = true;
}
else
{
oitem.Items = buildItemTrees(children, lvl + 1, setLazyChild);
}
}

return list;
}

public async Task<IActionResult> SearchTree(string term)
{
term = (term ?? string.Empty);
var result = await mcx.TreeNodes.Where(o => o.Name.Contains(term)).Take(1).ToListAsync();
var roots = new List<TreeNode>();

foreach (var treeNode in result)
{
roots.Add(getRoot(treeNode));
}

roots = roots.Distinct().ToList();

var nodes = buildItemTrees(roots);
return Json(nodes);
}

private TreeNode getRoot(TreeNode node)
{
return node.Parent == null ? node : getRoot(node.Parent);
}

DropdownList with remote search



Only a few items + the selected one are loaded initially using the url specified in .Url, but when the user types something in the searchbox more items are loaded by executing the specified .SearchFunc; the new loaded items will be stored/cached until a load will occur, e.g. when a parent changes it's value the component will load.
DropdownList/Index.cshtml
 @(Html.Awe().DropdownList(new DropdownListOpt
{
Name = "RemoteSearchDd",
Url = Url.Action("GetMealsInit", "Data"),
ClearBtn = true,
Value = DemoCache.Meals.First().Id
}
.RemoteSearch(Url.Action("SearchMeals", "Data"))))
Awesome/DataController.cs
public IActionResult GetMealsInit(int? v)
{
var items = mcx.Meals.Take(3).ToList();
var selected = mcx.Meals.SingleOrDefault(o => o.Id == v);

if (selected != null && !items.Contains(selected))
{
items.Add(selected);
}

return Json(items.Select(o => new KeyContent(o.Id, o.Name)));
}

public async Task<IActionResult> SearchMeals(string term)
{
var items = (await mcx.Meals
.Filter(term, o => o.Name)
.Take(10)
.ToArrayAsync())
.Select(o => new KeyContent(o.Id, o.Name));

return Json(items);
}

DropdownList with custom item and caption rendering



Custom js functions are defined for rendering the items and caption of the DropdownList.
DropdownList/Index.cshtml
@(Html.Awe().DropdownList(new DropdownListOpt 
{
Name = "CustomItemOdd",
Value = DemoCache.Meals[1].Id,
Url = Url.Action("GetMealsImg", "Data"),
ItemFunc = "imgItem",
CaptionFunc = "imgCaption"
}))
<script>
function imgItem(o) {
return '<div class="o-igit"><img src="' + o.url + '" />' + o.c + '</div>';
}

function imgCaption(o) {
return '<img class="cthumb" src="' + o.url + '" />' + o.c;
}
</script>
Awesome/DataController.cs
public IActionResult GetMealsImg()
{
var url = Url.Content(DemoUtils.MealsUrl);
var items = mcx.Meals.Include(m => m.Category).OrderBy(m => m.Id).ToArray()
.Select(o => new MealDisplay(o.Id, o.Name, url + o.Name + ".jpg", o.Category.Id));

return Json(items);
}

Remote search, external api





Getting data from the git api on search using the SearchFunc. ItemFunc and CaptionFunc are used to specify custom rendering functions for the items and the caption.
Using the same cache key "g1", so searching in one control will populate the other one with data as well.
Shared/Demos/RmtSrcGit.cshtml
@(Html.Awe().DropdownList(new DropdownListOpt
{
Name = "GitRepoOdropdown",
Load = false,
ItemFunc = "site.gitItem",
CaptionFunc = "site.gitCaption",
Caption = "select a git repo",
SearchFunc = new SearchFuncOpt { Name = "site.gitRepoSearch", Key = "g1" }
}
))
<br />
<br />
@(Html.Awe().Multiselect(new MultiselectOpt
{
Name = "GitRepoMultiselect",
Load = false,
ItemFunc = "site.gitItem",
CaptionFunc = "site.gitCaption",
Caption = "select a git repo",
SearchFunc = new SearchFuncOpt { Name = "site.gitRepoSearch", Key = "g1" }
}
))

Events and Api






Showing commonly used client side api methods.
To change the value you simply call jquery .val(newvalue).trigger('change').
aweload event is handled to flash the #log div whenever the dropdown loads.
The same api methods can be used for the AjaxDropdown, AjaxCheckboxList controls and their mods.
DropdownList/Index.cshtml
@{
var meal1 = DemoCache.Meals[3];
var meal2 = DemoCache.Meals[4];
}

@(Html.Awe().DropdownList(
new DropdownListOpt
{
Name = "ddApi",
Url = Url.Action("ApiGetMeals", "Data")
}))

<br />
<br />
@Html.Awe().Button().Text("Change value to " + meal1.Name).OnClick("app1.changeval(" + meal1.Id + ")")
@Html.Awe().Button().Text("Change value to " + meal2.Name).OnClick("app1.changeval(" + meal2.Id + ")")
@Html.Awe().Button().Text("Get value").OnClick("app1.getVal()")
@Html.Awe().Button().Text("Clear Value").OnClick("app1.changeval('')")

@Html.Awe().Button().Text("Load only first category").OnClick("app1.loadFirstCat()")
@Html.Awe().Button().Text("Reload").OnClick("app1.reload()")
@Html.Awe().Button().Text("Toggle Enable").OnClick("app1.toggleEnable()")

<br />
<br />

<div id="log">
</div>

<script>
var app1;

$(function () {
var dd = $('#ddApi');
var api = dd.data('api');
app1 = {
getVal: function () {
var val = dd.val();
$('#log').html('val = ' + val);
},

changeval: function (newVal) {
dd.val(newVal).change();
},

reload: function () {
api.load();
},

loadFirstCat: function () {
api.load({ oparams: { cat1: true } });
// oparams sets cat1 just for this call (same as for the grid api)
// params sets persistent parameters
},

toggleEnable: function () {
api.enable(!dd.data('o').enb);
}
};

dd.on('aweload', function (e, data) {
awe.flash($('#log').html('loaded ' + data.length + ' items'));
});
});
</script>
Awesome/DataController.cs
public IActionResult ApiGetMeals(int? v, bool? cat1)
{
var items = (cat1 == true) ?
mcx.Meals.Where(o => o.Category == mcx.Categories.First()).ToArray() :
mcx.Meals.ToArray();

return Json(items.Select(o => new KeyContent(o.Id, o.Name)));
}

Predefined parameters

Setting a predefined parameters with values for the data request. We can also set ParameterFunc to a js function that will return an object with parameters. Parameters with the same name will merge into a collection.
Shared/Demos/ParamParent.cshtml
@(Html.Awe().DropdownList(new DropdownListOpt
{
Name = "MealsParamDd",
AutoSelectFirst = true,
Url = Url.Action("GetMealsParamsExample", "Data"),
ParameterFunc = "getFuncData"
}
.Parameter("categories", DemoCache.Categories[1].Id)))
<script>
function getFuncData() {
return { customItem: "my item from js func", categories: @DemoCache.Categories[2].Id };
}
</script>
Awesome/DataController.cs
public IActionResult GetMealsParamsExample(int[] categories, string customItem)
{
categories = categories ?? new int[] { };
var items = mcx.Meals.Where(o => categories.Contains(o.Category.Id))
.Select(o => new KeyContent(o.Id, o.Name));

var result = new List<KeyContent>();

if (customItem != null)
{
result.Add(new KeyContent(customItem, customItem));
}

result.AddRange(items);

return Json(result);
}

Binding to parents

parent txt:
categories:
We can bind to one or multiple parents, by specifying the client parent control id and parameter name to be attached to the child's data request.
We could do that using the Parent(parentId, paramName = "parent", loadOnChange = true) extension.
Shared/Demos/ParamParent.cshtml
parent txt:
@(Html.Awe().TextBox(new TextBoxOpt
{
Name = "CustomItemName",
Value = "added as first item"
}))

categories:
@(Html.Awe().Multiselect(new MultiselectOpt
{
Name = "ParentCats",
Url = Url.Action("GetCategories", "Data")
}))

@(Html.Awe().DropdownList(new DropdownListOpt
{
Name = "MealsChildDd",
AutoSelectFirst = true,
Url = Url.Action("GetMealsParamsExample", "Data"),
}
.Parent("CustomItemName", "customItem")
.Parent("ParentCats", "categories")
))
Awesome/DataController.cs
public IActionResult GetMealsParamsExample(int[] categories, string customItem)
{
categories = categories ?? new int[] { };
var items = mcx.Meals.Where(o => categories.Contains(o.Category.Id))
.Select(o => new KeyContent(o.Id, o.Name));

var result = new List<KeyContent>();

if (customItem != null)
{
result.Add(new KeyContent(customItem, customItem));
}

result.AddRange(items);

return Json(result);
}
Note: all awesome data select editors and the Grid, AjaxList can have parents and predefined parameters.



Comments