Skip to content

Commit d1d8266

Browse files
committed
Add Html.ReactWithInit helper method. Closes #42
This helper method renders both the HTML for the component, and its client-side initialisation script. It is useful when rendering self-contained partial views containing React components.
1 parent 8ca07d5 commit d1d8266

File tree

4 files changed

+128
-0
lines changed

4 files changed

+128
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (c) 2014, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
using System.Runtime.Remoting;
11+
using Moq;
12+
using NUnit.Framework;
13+
using React.Web.Mvc;
14+
15+
namespace React.Tests.Mvc
16+
{
17+
[TestFixture]
18+
class HtmlHelperExtensionsTests
19+
{
20+
/// <summary>
21+
/// Creates a mock <see cref="IReactEnvironment"/> and registers it with the IoC container
22+
/// This is only required because <see cref="HtmlHelperExtensions"/> can not be
23+
/// injected :(
24+
/// </summary>
25+
private Mock<IReactEnvironment> ConfigureMockEnvironment()
26+
{
27+
var environment = new Mock<IReactEnvironment>();
28+
AssemblyRegistration.Container.Register(environment.Object);
29+
return environment;
30+
}
31+
32+
[Test]
33+
public void ReactWithInitShouldReturnHtmlAndScript()
34+
{
35+
var component = new Mock<IReactComponent>();
36+
component.Setup(x => x.RenderHtml()).Returns("HTML");
37+
component.Setup(x => x.RenderJavaScript()).Returns("JS");
38+
var environment = ConfigureMockEnvironment();
39+
environment.Setup(x => x.CreateComponent(
40+
"ComponentName",
41+
new {},
42+
null
43+
)).Returns(component.Object);
44+
45+
var result = HtmlHelperExtensions.ReactWithInit(
46+
htmlHelper: null,
47+
componentName: "ComponentName",
48+
props: new { },
49+
htmlTag: "span"
50+
);
51+
Assert.AreEqual(
52+
"HTML" + System.Environment.NewLine + "<script>JS</script>",
53+
result.ToString()
54+
);
55+
56+
}
57+
}
58+
}

src/React.Tests/React.Tests.csproj

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444
<SpecificVersion>False</SpecificVersion>
4545
<HintPath>..\packages\JavaScriptEngineSwitcher.Core.1.2.0\lib\net40\JavaScriptEngineSwitcher.Core.dll</HintPath>
4646
</Reference>
47+
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
48+
<Private>True</Private>
49+
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
50+
</Reference>
4751
<Reference Include="Moq, Version=4.2.1408.717, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
4852
<SpecificVersion>False</SpecificVersion>
4953
<HintPath>..\packages\Moq.4.2.1408.0717\lib\net40\Moq.dll</HintPath>
@@ -54,6 +58,30 @@
5458
<Reference Include="System" />
5559
<Reference Include="System.Core" />
5660
<Reference Include="System.Web" />
61+
<Reference Include="System.Web.Helpers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
62+
<Private>True</Private>
63+
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.Helpers.dll</HintPath>
64+
</Reference>
65+
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
66+
<Private>True</Private>
67+
<HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.30506.0\lib\net40\System.Web.Mvc.dll</HintPath>
68+
</Reference>
69+
<Reference Include="System.Web.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
70+
<Private>True</Private>
71+
<HintPath>..\packages\Microsoft.AspNet.Razor.2.0.20710.0\lib\net40\System.Web.Razor.dll</HintPath>
72+
</Reference>
73+
<Reference Include="System.Web.WebPages, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
74+
<Private>True</Private>
75+
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.dll</HintPath>
76+
</Reference>
77+
<Reference Include="System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
78+
<Private>True</Private>
79+
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Deployment.dll</HintPath>
80+
</Reference>
81+
<Reference Include="System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
82+
<Private>True</Private>
83+
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll</HintPath>
84+
</Reference>
5785
<Reference Include="System.Xml.Linq" />
5886
<Reference Include="System.Data.DataSetExtensions" />
5987
<Reference Include="Microsoft.CSharp" />
@@ -71,13 +99,18 @@
7199
<Compile Include="Core\JavaScriptEngineFactoryTest.cs" />
72100
<Compile Include="Core\JsxTransformerTests.cs" />
73101
<Compile Include="Core\ReactComponentTest.cs" />
102+
<Compile Include="Mvc\HtmlHelperExtensionsTests.cs" />
74103
<Compile Include="Properties\AssemblyInfo.cs" />
75104
<Compile Include="Core\ReactEnvironmentTest.cs" />
76105
</ItemGroup>
77106
<ItemGroup>
78107
<None Include="packages.config" />
79108
</ItemGroup>
80109
<ItemGroup>
110+
<ProjectReference Include="..\React.Web.Mvc4\React.Web.Mvc4.csproj">
111+
<Project>{662d52ac-1ee9-4372-bd74-379f9ac56451}</Project>
112+
<Name>React.Web.Mvc4</Name>
113+
</ProjectReference>
81114
<ProjectReference Include="..\React.Web\React.Web.csproj">
82115
<Project>{134edd16-8dc8-4983-a2e0-b38dab1ecf1c}</Project>
83116
<Name>React.Web</Name>

src/React.Tests/packages.config

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
33
<package id="JavaScriptEngineSwitcher.Core" version="1.2.0" targetFramework="net40" />
4+
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
5+
<package id="Microsoft.AspNet.Razor" version="2.0.20710.0" targetFramework="net40" />
6+
<package id="Microsoft.AspNet.WebPages" version="2.0.20710.0" targetFramework="net40" />
7+
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net40" />
48
<package id="Moq" version="4.2.1408.0717" targetFramework="net40" />
59
<package id="NUnit" version="2.6.3" targetFramework="net40" />
610
</packages>

src/React.Web.Mvc4/HtmlHelperExtensions.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,39 @@ public static IHtmlString React<T>(
5555
return new HtmlString(result);
5656
}
5757

58+
/// <summary>
59+
/// Renders the specified React component, along with its client-side initialisation code.
60+
/// Normally you would use the <see cref="React{T}"/> method, but <see cref="ReactWithInit{T}"/>
61+
/// is useful when rendering self-contained partial views.
62+
/// </summary>
63+
/// <typeparam name="T">Type of the props</typeparam>
64+
/// <param name="htmlHelper">HTML helper</param>
65+
/// <param name="componentName">Name of the component</param>
66+
/// <param name="props">Props to initialise the component with</param>
67+
/// <param name="htmlTag">HTML tag to wrap the component in. Defaults to &lt;div&gt;</param>
68+
/// <param name="containerId">ID to use for the container HTML tag. Defaults to an auto-generated ID</param>
69+
/// <returns>The component's HTML</returns>
70+
public static IHtmlString ReactWithInit<T>(
71+
this HtmlHelper htmlHelper,
72+
string componentName,
73+
T props,
74+
string htmlTag = null,
75+
string containerId = null
76+
)
77+
{
78+
var reactComponent = Environment.CreateComponent(componentName, props, containerId);
79+
if (!string.IsNullOrEmpty(htmlTag))
80+
{
81+
reactComponent.ContainerTag = htmlTag;
82+
}
83+
var html = reactComponent.RenderHtml();
84+
var script = new TagBuilder("script")
85+
{
86+
InnerHtml = reactComponent.RenderJavaScript()
87+
};
88+
return new HtmlString(html + System.Environment.NewLine + script.ToString());
89+
}
90+
5891
/// <summary>
5992
/// Renders the JavaScript required to initialise all components client-side. This will
6093
/// attach event handlers to the server-rendered HTML.

0 commit comments

Comments
 (0)