Использование.WrapWith при создании элементов управления HtmlTag

Я создаю несколько методов HTML Helper на основе библиотеки HtmlTags проекта Fubu для приложения, основанного на неизбежной платформе Twitter Bootstrap. Для большинства простых элементов управления у меня не было проблем с прямым подклассом HtmlTag; однако, когда дело доходит до более сложных элементов управления, которые обычно должны быть вложены в тег div, он становится немного более сложным.

Например, у меня есть TextboxWidget, который реализован примерно так:

public class TextboxWidget : HtmlTag
{
    public TextboxWidget() : base("input")
    {
        Attr("type", "text");
        AddClass("form-control");
        NoClosingTag();
    }
}

что довольно просто. Затем его можно использовать следующим образом (с несколькими другими методами расширения):

@Html.Bootstrap().Textbox(m => m.FirstName).Data("bind", "Employee.FirstName")

дать желаемый результат.

Моя реализация DatepickerWidget выглядит примерно так:

public class DatepickerWidget : HtmlTag
{
    public DatepickerWidget() : base("input")
    {
        Attr("type", "text");
        Attr("role", "datepicker");
        AddClasses("form-control", "datepicker");
        Data("dateformat", "dd/mm/yy");

        Button = new HtmlTag("span").AddClass("input-group-addon");
        var icon = new HtmlTag("i").AddClass("icon-calendar");

        Button.Append(icon);
        Append(Button);
        WrapWith(new DivTag().AddClass("input-group"));
    }
}

который затем используется так:

@Html.Bootstrap().Datepicker(m => m.StartDate).DataBind("click", "fnProcessClick").AddClass("special-offer")

но по какой-то причине тег div-обертки не отображается. Если я напишу несколько модульных тестов для элемента управления, то смогу увидеть тег div в объектной модели (в свойстве Parent), но он просто никогда не превращается в HTML на странице.

Я действительно хочу сохранить основной элемент ввода в качестве основного элемента управления, поэтому все красивые расширения HtmlTag свисают с виджета; мне придется идти по маршруту, указанному Джимми Богардом, выставляя модификаторы для каждого из отдельных элементов в элементе управления?

1 ответ

Решение

WrapWith возвращает новый HtmlTag; в вашей реализации DatePickerWidget в основном он просто игнорируется, а DatePickerWidget по-прежнему является просто тегом "input", на котором он основан.

Одним из вариантов будет отказаться от WrapWith строки из вашего класса добавим обертку позже:

@Html.Bootstrap().Datepicker(m => m.StartDate).DataBind("click", "fnProcessClick").AddClass("special-offer").WrapWith(new DivTag().AddClass("input-group"))

Если это громоздко, вы можете сократить его, добавив для него метод класса:

 public HtmlTag WrapWithInputGroup()
 {
    return WrapWith(new DivTag().AddClass("input-group"));
 }

@Html.Bootstrap().Datepicker(m => m.StartDate).DataBind("click", "fnProcessClick").AddClass("special-offer").WrapWithInputGroup()

Другой вариант, который работает так, как вы ожидали, что ваш оригинальный класс будет работать, - это переопределение ToString():

public class DatepickerWidget2 : HtmlTag
{
    public DatepickerWidget2()
        : base("input")
    {
        Attr("type", "text");
        Attr("role", "datepicker");
        AddClasses("form-control", "datepicker");
        Data("dateformat", "dd/mm/yy");

        var Button = new HtmlTag("span").AddClass("input-group-addon");
        var icon = new HtmlTag("i").AddClass("icon-calendar");

        Button.Append(icon);
        Append(Button);
    }

    public override string ToString()
    {
        return WrapWith(new DivTag().AddClass("input-group")).ToString();
    }
}

Огромное, огромное предостережение: в моем быстром и грязном тестировании это работает, но это может противоречить оригинальному дизайну HtmlTags. Я бы использовал это решение с осторожностью (до тех пор, пока кто-нибудь, например Джереми Миллер, не появится здесь и не скажет, что это правильное решение).

Другие вопросы по тегам