Code-only controls - Render end tag

Hello,
I’ve been trying to render a canvas element on the page using Dotvvm code-only controls.
I have set the RenderBeginTag and RenderEndTag like this:

protected override void RenderBeginTag(IHtmlWriter writer, IDotvvmRequestContext context)
{
    writer.RenderBeginTag(TagName);
}

protected override void RenderEndTag(IHtmlWriter writer, IDotvvmRequestContext context)
{
    writer.RenderEndTag();
}

But when the html is created, I get only the <canvas …> tag and no the closing tag. Am i missing something? I’m also using AddAttributesToRender and OnPreRender

The code looks correct.
Can you try to put a breakpoint on the writer.RenderEndTag() to see whether it is called?
Or can you provide the full code of the control?

Yes, of course.

public class GraphControl: HtmlGenericControl
    {
        public GraphControl() : base("canvas")
        {

        }

        public List<GraphModel> Data
        {
            get { return (List<GraphModel>)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }
        public static readonly DotvvmProperty DataProperty
            = DotvvmProperty.Register<List<GraphModel>, GraphControl>(c => c.Data, null);

        protected override void RenderBeginTag(IHtmlWriter writer, IDotvvmRequestContext context)
        {
            writer.RenderBeginTag(TagName);
        }

        protected override void AddAttributesToRender(IHtmlWriter writer, IDotvvmRequestContext context)
        {
            var graphBinding = GetValueBinding(DataProperty);

            if (graphBinding != null)
            {
                writer.AddKnockoutDataBind("graph-binding", this, DataProperty, renderEvenInServerRenderingMode: true);
            }

            base.AddAttributesToRender(writer, context);
        }

        protected override void RenderEndTag(IHtmlWriter writer, IDotvvmRequestContext context)
        {
            writer.RenderEndTag();
        }

        protected override void OnPreRender(IDotvvmRequestContext context)
        {
            context.ResourceManager.AddRequiredResource("GraphJS");
            base.OnPreRender(context);
        }
    }

I just tried the GraphControl and it outputs <canvas></canvas>, as expected. Are you sure there is no end tag? One possibilite reason why it might seem missing is that the in dothtml is unclosed, so the dothtml parser placed everything into the control Children. I’d suggest using [ControlMarkupOptions(AllowContent = false)] to avoid this issue (if the control isn’t expected to have child nodes)

I also tried the ControlMarkupOptions but it didn’t work. What I see after inspecting element (chrome dev tools) is:
image

For some reason, Chrome doesn’t show the end tag for canvas elements in the devtools. I tried it out

Generated HTML: html code with canvas start and end tags

Firefox: shows canvas element with both start and end tag

Chrome: show only the start tag

1 Like

Yes, you’re write. Google Chrome (not sure about older versions) only renders the end tag if some content is added inside

Chrome:
image

Firefox:
image

Thank you for the help!