Add rendering logic for PreElement and PostElement on TagHelperOutput.

- Added unit tests to validate that the properties were rendered correctly.
- Modified functional tests to utilize PreElement and PostElement.

aspnet/Razor#341
This commit is contained in:
N. Taylor Mullen 2015-04-13 14:52:06 -07:00
parent d0e5118741
commit 2c4c35e126
5 changed files with 362 additions and 44 deletions

View File

@ -278,6 +278,8 @@ namespace Microsoft.AspNet.Mvc.Razor
var tagHelperOutput = tagHelperExecutionContext.Output;
var isTagNameNullOrWhitespace = string.IsNullOrWhiteSpace(tagHelperOutput.TagName);
WriteTagHelperContentTo(writer, tagHelperOutput.PreElement);
if (!isTagNameNullOrWhitespace)
{
writer.Write('<');
@ -324,6 +326,8 @@ namespace Microsoft.AspNet.Mvc.Razor
{
writer.Write(string.Format(CultureInfo.InvariantCulture, "</{0}>", tagHelperOutput.TagName));
}
WriteTagHelperContentTo(writer, tagHelperOutput.PostElement);
}
private void WriteTagHelperContentTo(TextWriter writer, TagHelperContent content)

View File

@ -28,12 +28,12 @@
<div>
<p>This website has <strong style="font-size: 1.25em;text-decoration: underline;">not</strong> been approved yet. Visit <strong><a target="_blank" href="http://www.contoso.com">www.contoso.com</a></strong> for <strong>more</strong> information.</p>
<p>This website has <em><strong style="font-size: 1.25em;text-decoration: underline;">not</strong></em> been approved yet. Visit <strong><a target="_blank" href="http://www.contoso.com">www.contoso.com</a></strong> for <strong>more</strong> information.</p>
</div>
<div>
<h3 style="font-family: cursive;">Current Tag Cloud from Tag Helper</h3>
<section>["Lorem","ipsum","dolor","sit","amet","consectetur","adipisicing","elit","sed","do","eiusmod","tempor","incididunt","ut","labore","et","dolore","magna","aliquaUt","enim"]</section>
<div>["Lorem","ipsum","dolor","sit","amet","consectetur","adipisicing","elit","sed","do","eiusmod","tempor","incididunt","ut","labore","et","dolore","magna","aliquaUt","enim"]</div>
<h3 style="font-family: cursive;">Current Tag Cloud from ViewComponentHelper:</h3>
<section>["Lorem","ipsum","dolor","sit","amet","consectetur","adipisicing","elit","sed","do","eiusmod","tempor","incididunt","ut","labore"]</section>
</div>

View File

@ -722,85 +722,365 @@ namespace Microsoft.AspNet.Mvc.Razor
{
{
// parameters: TagName, Attributes, SelfClosing, PreContent, Content, PostContent
GetTagHelperOutput("div", new Dictionary<string, object>(), false, null, "Hello World!", null),
GetTagHelperOutput(
tagName: "div",
attributes: new Dictionary<string, object>(),
selfClosing: false,
preElement: null,
preContent: null,
content: "Hello World!",
postContent: null,
postElement: null),
"<div>Hello World!</div>"
},
{
GetTagHelperOutput(null, new Dictionary<string, object>(), false, null, "Hello World!", null),
"Hello World!"
},
{
GetTagHelperOutput(" ", new Dictionary<string, object>(), false, null, "Hello World!", null),
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object>(),
selfClosing: false,
preElement: null,
preContent: null,
content: "Hello World!",
postContent: null,
postElement: null),
"Hello World!"
},
{
GetTagHelperOutput(
"p",
new Dictionary<string, object>() { { "test", "testVal" } },
false,
null,
"Hello World!",
null),
tagName: " ",
attributes: new Dictionary<string, object>(),
selfClosing: false,
preElement: null,
preContent: null,
content: "Hello World!",
postContent: null,
postElement: null),
"Hello World!"
},
{
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>() { { "test", "testVal" } },
selfClosing: false,
preElement: null,
preContent: null,
content: "Hello World!",
postContent: null,
postElement: null),
"<p test=\"testVal\">Hello World!</p>"
},
{
GetTagHelperOutput(
"p",
new Dictionary<string, object>() { { "test", "testVal" }, { "something", " spaced " } },
false,
null,
"Hello World!",
null),
tagName: "p",
attributes: new Dictionary<string, object>() { { "test", "testVal" }, { "something", " spaced " } },
selfClosing: false,
preElement: null,
preContent: null,
content: "Hello World!",
postContent: null,
postElement: null),
"<p test=\"testVal\" something=\" spaced \">Hello World!</p>"
},
{
GetTagHelperOutput(
"p",
new Dictionary<string, object>() { { "test", "testVal" } },
true,
null,
"Hello World!",
null),
tagName: "p",
attributes: new Dictionary<string, object>() { { "test", "testVal" } },
selfClosing: true,
preElement: null,
preContent: null,
content: "Hello World!",
postContent: null,
postElement: null),
"<p test=\"testVal\" />"
},
{
GetTagHelperOutput(
"p",
new Dictionary<string, object>() { { "test", "testVal" }, { "something", " spaced " } },
true,
null,
"Hello World!",
null),
tagName: "p",
attributes: new Dictionary<string, object>() { { "test", "testVal" }, { "something", " spaced " } },
selfClosing: true,
preElement: null,
preContent: null,
content: "Hello World!",
postContent: null,
postElement: null),
"<p test=\"testVal\" something=\" spaced \" />"
},
{
GetTagHelperOutput("p", new Dictionary<string, object>(), false, "Hello World!", null, null),
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>(),
selfClosing: false,
preElement: null,
preContent: "Hello World!",
content: null,
postContent: null,
postElement: null),
"<p>Hello World!</p>"
},
{
GetTagHelperOutput("p", new Dictionary<string, object>(), false, null, "Hello World!", null),
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>(),
selfClosing: false,
preElement: null,
preContent: null,
content: "Hello World!",
postContent: null,
postElement: null),
"<p>Hello World!</p>"
},
{
GetTagHelperOutput("p", new Dictionary<string, object>(), false, null, null, "Hello World!"),
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>(),
selfClosing: false,
preElement: null,
preContent: null,
content: null,
postContent: "Hello World!",
postElement: null),
"<p>Hello World!</p>"
},
{
GetTagHelperOutput("p", new Dictionary<string, object>(), false, "Hello", "Test", "World!"),
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>(),
selfClosing: false,
preElement: null,
preContent: "Hello",
content: "Test",
postContent: "World!",
postElement: null),
"<p>HelloTestWorld!</p>"
},
{
GetTagHelperOutput("p", new Dictionary<string, object>(), true, "Hello", "Test", "World!"),
GetTagHelperOutput(
tagName: "p",
attributes: new Dictionary<string, object>(),
selfClosing: true,
preElement: null,
preContent: "Hello",
content: "Test",
postContent: "World!",
postElement: null),
"<p />"
},
{
GetTagHelperOutput("custom", new Dictionary<string, object>(), false, "Hello", "Test", "World!"),
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object>(),
selfClosing: false,
preElement: null,
preContent: "Hello",
content: "Test",
postContent: "World!",
postElement: null),
"<custom>HelloTestWorld!</custom>"
},
{
GetTagHelperOutput("random", new Dictionary<string, object>(), true, "Hello", "Test", "World!"),
GetTagHelperOutput(
tagName: "random",
attributes: new Dictionary<string, object>(),
selfClosing: true,
preElement: null,
preContent: "Hello",
content: "Test",
postContent: "World!",
postElement: null),
"<random />"
}
},
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object>(),
selfClosing: false,
preElement: "Before",
preContent: null,
content: null,
postContent: null,
postElement: null),
"Before<custom></custom>"
},
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object>(),
selfClosing: false,
preElement: "Before",
preContent: null,
content: null,
postContent: null,
postElement: null),
"Before"
},
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object> { { "test", "testVal" } },
selfClosing: true,
preElement: "Before",
preContent: null,
content: null,
postContent: null,
postElement: null),
"Before"
},
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object> { { "test", "testVal" } },
selfClosing: true,
preElement: "Before",
preContent: null,
content: null,
postContent: null,
postElement: null),
"Before<custom test=\"testVal\" />"
},
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object>(),
selfClosing: true,
preElement: "Before",
preContent: null,
content: null,
postContent: null,
postElement: null),
"Before<custom />"
},
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object>(),
selfClosing: false,
preElement: null,
preContent: null,
content: null,
postContent: null,
postElement: "After"),
"<custom></custom>After"
},
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object>(),
selfClosing: false,
preElement: null,
preContent: null,
content: null,
postContent: null,
postElement: "After"),
"After"
},
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object> { { "test", "testVal" } },
selfClosing: true,
preElement: null,
preContent: null,
content: null,
postContent: null,
postElement: "After"),
"After"
},
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object> { { "test", "testVal" } },
selfClosing: true,
preElement: null,
preContent: null,
content: null,
postContent: null,
postElement: "After"),
"<custom test=\"testVal\" />After"
},
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object>(),
selfClosing: true,
preElement: null,
preContent: null,
content: null,
postContent: null,
postElement: "After"),
"<custom />After"
},
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object>(),
selfClosing: false,
preElement: "Before",
preContent: "Hello",
content: "Test",
postContent: "World!",
postElement: "After"),
"Before<custom>HelloTestWorld!</custom>After"
},
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object> { { "test", "testVal" } },
selfClosing: false,
preElement: "Before",
preContent: "Hello",
content: "Test",
postContent: "World!",
postElement: "After"),
"Before<custom test=\"testVal\">HelloTestWorld!</custom>After"
},
{
GetTagHelperOutput(
tagName: "custom",
attributes: new Dictionary<string, object>(),
selfClosing: true,
preElement: "Before",
preContent: "Hello",
content: "Test",
postContent: "World!",
postElement: "After"),
"Before<custom />After"
},
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object>(),
selfClosing: true,
preElement: "Before",
preContent: "Hello",
content: "Test",
postContent: "World!",
postElement: "After"),
"BeforeHelloTestWorld!After"
},
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object>(),
selfClosing: false,
preElement: "Before",
preContent: "Hello",
content: "Test",
postContent: "World!",
postElement: "After"),
"BeforeHelloTestWorld!After"
},
{
GetTagHelperOutput(
tagName: null,
attributes: new Dictionary<string, object> { { "test", "testVal" } },
selfClosing: false,
preElement: "Before",
preContent: "Hello",
content: "Test",
postContent: "World!",
postElement: "After"),
"BeforeHelloTestWorld!After"
},
};
}
}
@ -937,18 +1217,22 @@ namespace Microsoft.AspNet.Mvc.Razor
string tagName,
IDictionary<string, object> attributes,
bool selfClosing,
string preElement,
string preContent,
string content,
string postContent)
string postContent,
string postElement)
{
var output = new TagHelperOutput(tagName, attributes)
{
SelfClosing = selfClosing
};
output.PreElement.SetContent(preElement);
output.PreContent.SetContent(preContent);
output.Content.SetContent(content);
output.PostContent.SetContent(postContent);
output.PostElement.SetContent(postElement);
return output;
}

View File

@ -0,0 +1,30 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
namespace TagHelpersWebSite.TagHelpers
{
[TargetElement(Attributes = nameof(Surround))]
public class SurroundTagHelper : TagHelper
{
public override int Order
{
get
{
// Run first
return int.MinValue;
}
}
public string Surround { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
var surroundingTagName = Surround.ToLowerInvariant();
output.PreElement.SetContent($"<{surroundingTagName}>");
output.PostElement.SetContent($"</{surroundingTagName}>");
}
}
}

View File

@ -17,16 +17,16 @@
}
<div condition="!Model.Approved">
<p>This website has <strong>not</strong> been approved yet. Visit www.contoso.com for <strong make-pretty="false">more</strong> information.</p>
<p>This website has <strong surround="em">not</strong> been approved yet. Visit www.contoso.com for <strong make-pretty="false">more</strong> information.</p>
</div>
<div>
<h3>Current Tag Cloud from Tag Helper</h3>
<section><tag-cloud count="Model.TagsToShow" /></section>
<tag-cloud count="Model.TagsToShow" surround="div" />
<h3>Current Tag Cloud from ViewComponentHelper:</h3>
<section>@await Component.InvokeAsync("Tags", 15)</section>
</div>
@section footerContent {
<p condition="Model.Approved">&copy; @Model.CopyrightYear - My ASP.NET Application</p>
<p condition="Model.Approved" surround="section">&copy; @Model.CopyrightYear - My ASP.NET Application</p>
}