HTML5 Заполнители с .NET MVC 3 Razor Editor для расширения? - PullRequest
91 голосов
/ 28 апреля 2011

Есть ли способ написать заполнитель Html5 , используя @ Html.EditorFor, или я должен просто использовать расширение TextBoxFor, т.е.

@Html.TextBoxFor(model => model.Title, new { @placeholder = "Enter title here"})

Или было бы целесообразно написать нашесвое собственное расширение, которое может использовать атрибут отображения «Description» через DataAnnotations (аналогично this )?

Конечно, тогда тот же вопрос относится и к «автофокусировке».

Ответы [ 8 ]

120 голосов
/ 05 июля 2011

Как отмечает smnbss в ответе Дарина Димитрова, Prompt существует именно для этой цели, поэтому не нужно создавать пользовательский атрибут . Из документации:

Получает или задает значение, которое будет использоваться установить водяной знак для подсказок в пользовательский интерфейс.

Чтобы использовать его, просто украсьте свойство вашей модели вида следующим образом:

[Display(Prompt = "numbers only")]
public int Age { get; set; }

Этот текст затем удобно помещается в ModelMetadata.Watermark. В стандартном шаблоне MVC 3 по умолчанию игнорируется свойство Watermark, но заставить его работать действительно просто. Все, что вам нужно сделать, это настроить шаблон строки по умолчанию, чтобы сообщить MVC, как его визуализировать. Просто отредактируйте String.cshtml, как это делает Дарин, за исключением того, что вместо получения водяного знака от ModelMetadata.AdditionalValues вы получите его прямо из ModelMetadata.Watermark:

~ / Views / Shared / EditorTemplates / String.cshtml:

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line", placeholder = ViewData.ModelMetadata.Watermark })

И это все.

Как видите, ключом к тому, чтобы все работало, является placeholder = ViewData.ModelMetadata.Watermark бит.

Если вы также хотите включить водяные знаки для многострочных текстовых полей (textareas), вы сделаете то же самое для MultilineText.cshtml:

~ / Views / Shared / EditorTemplates / MultilineText.cshtml:

@Html.TextArea("", ViewData.TemplateInfo.FormattedModelValue.ToString(), 0, 0, new { @class = "text-box multi-line", placeholder = ViewData.ModelMetadata.Watermark })
68 голосов
/ 28 апреля 2011

Вы можете взглянуть на следующую статью для написания пользовательского DataAnnotationsModelMetadataProvider.

А вот еще один, более ASP.NET MVC 3-й способ продолжения работы с использованием недавно представленного интерфейса IMetadataAware .

Начните с создания пользовательского атрибута, реализующего этот интерфейс:

public class PlaceHolderAttribute : Attribute, IMetadataAware
{
    private readonly string _placeholder;
    public PlaceHolderAttribute(string placeholder)
    {
        _placeholder = placeholder;
    }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues["placeholder"] = _placeholder;
    }
}

А затем украсьте вашу модель им:

public class MyViewModel
{
    [PlaceHolder("Enter title here")]
    public string Title { get; set; }
}

Далее определите контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel());
    }
}

Соответствующее представление:

@model MyViewModel
@using (Html.BeginForm())
{
    @Html.EditorFor(x => x.Title)
    <input type="submit" value="OK" />
}
* 1021И наконец шаблон редактора (~/Views/Shared/EditorTemplates/string.cshtml):
@{
    var placeholder = string.Empty;
    if (ViewData.ModelMetadata.AdditionalValues.ContainsKey("placeholder"))
    {
        placeholder = ViewData.ModelMetadata.AdditionalValues["placeholder"] as string;
    }
}
<span>
    @Html.Label(ViewData.ModelMetadata.PropertyName)
    @Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { placeholder = placeholder })
</span>
22 голосов
/ 18 июля 2014

Я на самом деле предпочитаю использовать отображаемое имя для текста заполнителя большую часть времени.Вот пример использования DisplayName:

  @Html.TextBoxFor(x => x.FirstName, true, null, new { @class = "form-control", placeholder = Html.DisplayNameFor(x => x.FirstName) })
4 голосов
/ 30 декабря 2014

Я использую этот способ с файлом ресурсов (больше не требуется подсказка!)

@Html.TextBoxFor(m => m.Name, new 
{
     @class = "form-control",
     placeholder = @Html.DisplayName(@Resource.PleaseTypeName),
     autofocus = "autofocus",
     required = "required"
})
3 голосов
/ 24 октября 2014

Я написал такой простой класс:

public static class WatermarkExtension
{
    public static MvcHtmlString WatermarkFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
    {
        var watermark = ModelMetadata.FromLambdaExpression(expression, html.ViewData).Watermark;
        var htmlEncoded = HttpUtility.HtmlEncode(watermark);
        return new MvcHtmlString(htmlEncoded);
    }
}

Использование как таковое:

@Html.TextBoxFor(model => model.AddressSuffix, new {placeholder = Html.WatermarkFor(model => model.AddressSuffix)})

И свойство в viewmodel:

[Display(ResourceType = typeof (Resources), Name = "AddressSuffixLabel", Prompt = "AddressSuffixPlaceholder")]
public string AddressSuffix
{
    get { return _album.AddressSuffix; }
    set { _album.AddressSuffix = value; }
}

Параметр запроса уведомления. В этом случае я использую строки из ресурсов для локализации, но вы можете использовать только строки, просто избегайте параметра ResourceType.

1 голос
/ 22 мая 2015

Вот решение, которое я сделал, используя вышеупомянутые идеи, которые могут быть использованы для TextBoxFor и PasswordFor:

public static class HtmlHelperEx
{
    public static MvcHtmlString TextBoxWithPlaceholderFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        return htmlHelper.TextBoxFor(expression, htmlAttributes.AddAttribute("placeholder", metadata.Watermark));

    }

    public static MvcHtmlString PasswordWithPlaceholderFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        return htmlHelper.PasswordFor(expression, htmlAttributes.AddAttribute("placeholder", metadata.Watermark));

    }
}

public static class HtmlAttributesHelper
{
    public static IDictionary<string, object> AddAttribute(this object htmlAttributes, string name, object value)
    {
        var dictionary = htmlAttributes == null ? new Dictionary<string, object>() : htmlAttributes.ToDictionary();
        if (!String.IsNullOrWhiteSpace(name) && value != null && !String.IsNullOrWhiteSpace(value.ToString()))
            dictionary.Add(name, value);
        return dictionary;
    }

    public static IDictionary<string, object> ToDictionary(this object obj)
    {
        return TypeDescriptor.GetProperties(obj)
            .Cast<PropertyDescriptor>()
            .ToDictionary(property => property.Name, property => property.GetValue(obj));
    }
}
0 голосов
/ 19 ноября 2018
@Html.TextBoxFor(model => model.Message,  new { @class = "form-control"  , @placeholder = "Message.." })
0 голосов
/ 18 октября 2018

Я думаю, что создание собственного EditorTemplate не является хорошим решением, потому что вам нужно заботиться о многих возможных шаблонах для разных случаев: строк, чисел, выпадающих списков и так далее.Другое решение - пользовательское расширение для HtmlHelper.

Модель:

public class MyViewModel
{
    [PlaceHolder("Enter title here")]
    public string Title { get; set; }
}

Расширение помощника HTML:

   public static MvcHtmlString BsEditorFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TValue>> expression, string htmlClass = "")
{
    var modelMetadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    var metadata = modelMetadata;

    var viewData = new
    {
        HtmlAttributes = new
            {
                @class = htmlClass,
                placeholder = metadata.Watermark,
            }
    };
    return htmlHelper.EditorFor(expression, viewData);

}

Соответствующее представление:

@Html.BsEditorFor(x => x.Title)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...