diff --git a/Oqtane.Client/Modules/Controls/AutoComplete.razor b/Oqtane.Client/Modules/Controls/AutoComplete.razor new file mode 100644 index 00000000..b464fd20 --- /dev/null +++ b/Oqtane.Client/Modules/Controls/AutoComplete.razor @@ -0,0 +1,153 @@ +@namespace Oqtane.Modules.Controls +@inherits LocalizableComponent + +
+ + @if (_results != null) + { + + } +
+ +@code { + Dictionary _results; + + [Parameter] + public Func>> OnSearch { get; set; } // required - an async delegate method which accepts a filter string parameter and returns a dictionary + + [Parameter] + public int Characters { get; set; } = 3; // optional - number of characters before search is initiated + + [Parameter] + public int Rows { get; set; } = 3; // optional - number of result rows to display + + [Parameter] + public string Placeholder { get; set; } // optional - placeholder input text + + [Parameter] + public string Value { get; set; } // value of item selected + + [Parameter] + public string Key { get; set; } // key of item selected + + private async Task OnInput(ChangeEventArgs e) + { + Value = e.Value?.ToString(); + if (Value?.Length >= Characters) + { + _results = await OnSearch?.Invoke(Value); + } + else + { + _results = null; + } + SetKey(); + } + + private async Task OnKeyUp(KeyboardEventArgs e) + { + var index = -1; + switch (e.Key) + { + case "ArrowDown": + if (_results == null) + { + if (Value?.Length >= Characters) + { + _results = await OnSearch?.Invoke(Value); + } + } + else + { + index = GetIndex(); + if (index < _results.Count - 1) + { + Value = _results.ElementAt(index + 1).Value; + Key = _results.ElementAt(index + 1).Key; + } + } + break; + case "ArrowUp": + index = GetIndex(); + if (index > 0) + { + Value = _results.ElementAt(index - 1).Value; + Key = _results.ElementAt(index - 1).Key; + } + break; + case "ArrowRight": + case "Tab": + _results = null; + break; + case "Enter": // note within a form the enter key submits the entire form + case "NumpadEnter": + _results = null; + break; + case "Escape": + Value = ""; + _results = null; + break; + } + } + + private void OnChange(ChangeEventArgs e) + { + Value = (string)e.Value; + SetKey(); + _results = null; + } + + private int GetIndex() + { + if (_results != null) + { + for (int index = 0; index < _results.Count; index++) + { + if (_results.ElementAt(index).Value == Value) + { + return index; + } + } + } + return -1; + } + + private void SetKey() + { + var index = GetIndex(); + if (index != -1) + { + Key = _results.ElementAt(index).Key; + } + else + { + Key = ""; + } + } + + public void Clear() + { + Value = ""; + Key = ""; + _results = null; + } +} diff --git a/Oqtane.Client/Modules/Controls/Pager.razor b/Oqtane.Client/Modules/Controls/Pager.razor index e30a7c0e..bf735801 100644 --- a/Oqtane.Client/Modules/Controls/Pager.razor +++ b/Oqtane.Client/Modules/Controls/Pager.razor @@ -8,16 +8,16 @@ @if ((Toolbar == "Top" || Toolbar == "Both") && _pages > 0 && Items.Count() > _maxItems) {