Blazor 自动完成标记

问题描述 投票:0回答:1

这个问题类似,我正在寻找一个组件来向对象添加标签,就像在stackoverflow中一样,这意味着标签的自动完成文本字段。我要么正在寻找原生组件,要么正在寻找一种包装 JS 解决方案的方法,以便它可以在 blazor 中使用。

另一个想法是带有复选框的多选组件,如here所讨论的, 但我不太喜欢这个主意。

理想情况下,我会提供所有标签的列表,并绑定到正在设置标签的项目上的列表。

javascript c# autocomplete tags blazor
1个回答
12
投票

通常,共享完整代码并不是正确的做法,因为 SO 不是代码共享网站,并且通常会询问到目前为止您尝试过什么?。然而,由于 Blazor 是一项新技术,因此初学者很难在网络上找到一个好的解决方案或插件来满足他们的要求,因此我认为这是一个例外。

现在回答您的问题创建一个用于添加标签的新组件。您可以使用我在我正在从事的项目之一中创建的以下解决方案。这不需要任何 JS,只需使用 C# 即可处理以创建标签。您还可以检查我在 fiddle 上为您准备的 Blazor Fiddle 解决方案。希望这就是您正在寻找的。

@using System;
@using System.Collections.Generic;
@using System.Linq;
@using System.Text.RegularExpressions;

<style>

.suggestion-container {
    position: relative;
}

.tagsinput, .tagsinput * {
    box-sizing: border-box
}

.tagsinput {
    display: -webkit-box;
    display: -webkit-flex;
    display: -ms-flexbox;
    display: flex;
    -webkit-flex-wrap: wrap;
    -ms-flex-wrap: wrap;
    flex-wrap: wrap;
    background: #fff;
    font-size: 14px;
    line-height: 20px;
    color: #556270;
    padding: 5px 5px 0;
    border: 1px solid #e6e6e6;
    border-radius: 2px
}

    .tagsinput.focus {
        border-color: #ccc
    }

    .tagsinput .tag {
        position: relative;
        background: #556270;
        display: block;
        max-width: 100%;
        word-wrap: break-word;
        color: #fff;
        padding: 5px 30px 5px 5px;
        border-radius: 2px;
        margin: 0 5px 5px 0
    }

        .tagsinput .tag .tag-remove {
            position: absolute;
            background: 0 0;
            display: block;
            width: 30px;
            height: 30px;
            top: 0;
            right: 0;
            cursor: pointer;
            text-decoration: none;
            text-align: center;
            color: #ff6b6b;
            line-height: 30px;
            padding: 0;
            border: 0
        }

            .tagsinput .tag .tag-remove:after, .tagsinput .tag .tag-remove:before {
                background: #ff6b6b;
                position: absolute;
                display: block;
                width: 10px;
                height: 2px;
                top: 14px;
                left: 10px;
                content: ''
            }

            .tagsinput .tag .tag-remove:before {
                -webkit-transform: rotateZ(45deg);
                transform: rotateZ(45deg)
            }

            .tagsinput .tag .tag-remove:after {
                -webkit-transform: rotateZ(-45deg);
                transform: rotateZ(-45deg)
            }

    .tagsinput div {
        -webkit-box-flex: 1;
        -webkit-flex-grow: 1;
        -ms-flex-positive: 1;
        flex-grow: 1
    }

        .tagsinput div input {
            background: 0 0;
            display: block;
            width: 100%;
            font-size: 14px;
            line-height: 20px;
            padding: 5px;
            border: 0;
            margin: 0 5px 5px 0
        }

            .tagsinput div input:focus {
                color: #495057;
                background-color: #fff;
                border-color: #80bdff;
                outline: 0;
                box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);
            }

            .tagsinput div input.error {
                color: #ff6b6b
            }

            .tagsinput div input::-ms-clear {
                display: none
            }

            .tagsinput div input::-webkit-input-placeholder {
                color: #ccc;
                opacity: 1
            }

            .tagsinput div input:-moz-placeholder {
                color: #ccc;
                opacity: 1
            }

            .tagsinput div input::-moz-placeholder {
                color: #ccc;
                opacity: 1
            }

            .tagsinput div input:-ms-input-placeholder {
                color: #ccc;
                opacity: 1
            }
</style>

<div class="suggestion-container w-75">
    <div id="@($"{Id}_tagsinput")" class="tagsinput">

        @if (Tags != null && Tags.Any())
        {
            @foreach (var tag in Tags)
            {
                <span class="tag">
                    <span class="tag-text">@tag</span>
                    <span class="tag-remove" @onclick="() => DeleteTag(tag)" />
                </span>
            }
        }

        <div id="@($"{Id}_addTag")">
            <div class="@(IsContainSpecialCharacter ? "tag-tooltip" : string.Empty)">
                <input id="@($"{Id}_tag")"
                       class="tag-input"
                       placeholder="Add tags"
                       autocomplete="off"
                       @bind-value="Value"
                       @bind-value:event="oninput"
                       @onkeyup="AddTags" />

                @if (IsContainSpecialCharacter)
                {
                    <div class="error-right d-inline-flex p-2">
                        <i class="oi oi-warning text-warning p-1"></i>
                        <p class="text-left m-0 p-1">Special characters not allowed.</p>
                        <i></i>
                    </div>
                }
            </div>
        </div>
    </div>
</div>

@code{

    private Guid Id => Guid.NewGuid();
    protected string Value { get; set; }
    protected bool MenuVisibility { get; set; }
    protected bool IsContainSpecialCharacter { get; set; }
    protected List<string> Tags { get; set; } = new List<string>();

        protected void AddTags(KeyboardEventArgs eventArgs)
        {
            IsContainSpecialCharacter = false;

            if (!String.IsNullOrEmpty(Value))
            {
                if (eventArgs.Key.Equals("Enter"))
                {
                    var regex = new Regex(@"[^a-zA-Z0-9\s]");
                    if (!regex.IsMatch(Value))
                    {
                        if (!Tags.Exists(t => t.Equals(Value, StringComparison.CurrentCultureIgnoreCase)))
                        {
                            Tags.Add(Value);
                        }

                        Value = string.Empty;
                    }
                    else
                    {
                        IsContainSpecialCharacter = true;
                    }
                }
            }       
        }
    
        protected void DeleteTag(string value)
        {
            if (String.IsNullOrEmpty(value)) return;

            var tag = Tags.FirstOrDefault(t => t == value);
            if (tag == null) return;

            Tags.Remove(tag);
        }
}

P.S. 我在这里分享的只是构建标签的代码片段,它不包含具有自动完成选项的标签,因为它需要时间来创建一个关于伪造数据的完整解决方案。因此,由于时间限制,我避免了这种情况。

© www.soinside.com 2019 - 2024. All rights reserved.