Matthew Cox
Matthew Cox

Reputation: 13672

Imitating BeginForm() syntax

I am curious as to whether or not this is something that can be copied through design of the HtmlHelper or if it is something special built into Razor itself.

I'm writing a small wrapper library for Knockout to move away from writing raw html using a Fluent Interface approach. However, it is going to be very cumbersome unless I can do something like the following:

@using(Html.KoDiv().ForEach("MyArray").Visible("!Busy"))
{
     <some html here>
}

The only thing that I have seen that has a similar look is the following:

@using(Html.BeginForm("Action"))
{
    <some html here>
}

Question: How Can I pull this syntax off? Or, are there other lightweight syntax approaches I haven't thought of?

I figured that they are writing directly to the response or perhaps calling HtmlHelper.Raw() and rendering the closing tag on the Dispose() method since you have to use a using statement in their approach. However, neither of those have worked so far. Any ideas? Thanks!

Sample Code:

 public class KoElement : IHtmlString, IDisposable
{
    protected StringBuilder m_sb;
    protected TagBuilder m_tagBuilder;
    protected List<string> m_events;


    public KoElement(TagBuilder tb, HtmlHelper html = null)
    {
        m_tagBuilder = tb;
        m_events = new List<string>();

    }

    public string ToHtmlString()
    {
        m_tagBuilder.Attributes.Add("data-bind", string.Join(", ", m_events));
        return m_tagBuilder.ToString(TagRenderMode.StartTag);
    }

    public void Dispose()
    {
         HttpContext.Current.Response.Write("</" + m_tagBuilder.TagName + ">");
    }

    public KoElement Visible(string expression)
    {
        if (!string.IsNullOrEmpty(expression))  
            m_events.Add(string.Format("visible: {0}", expression));
        return this;
    }

    public KoElement ForEach(string expression)
    {
        if (!string.IsNullOrEmpty(expression))
            m_events.Add(string.Format("foreach: {0}", expression));
        return this;
    }
}

Upvotes: 3

Views: 197

Answers (1)

McGarnagle
McGarnagle

Reputation: 102753

Rather than using HttpContext.Current.Response.Write(), you have to use ViewContext.Writer.Write() in the HTML Helper.

public class KoElement : IHtmlString, IDisposable
{
    protected HtmlHelper m_html;
    protected TagBuilder m_tagBuilder;
    protected List<string> m_events;

    public KoElement(TagBuilder tb, HtmlHelper html)
    { 
        m_html = html;
        m_tagBuilder = tb;
        m_events = new List<string>();
    }

    public string ToHtmlString()
    {
        m_tagBuilder.Attributes.Add("data-bind", string.Join(", ", m_events));
        return m_tagBuilder.ToString(TagRenderMode.StartTag);
    }

    public void Dispose()
    {
        m_html.ViewContext.Writer.Write("</" + m_tagBuilder.TagName + ">");
    }
}

Upvotes: 3

Related Questions