Skip to content

Instantly share code, notes, and snippets.

@asmagin
Last active October 8, 2016 21:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save asmagin/707e25fd2c0617a4b7b271f89569de00 to your computer and use it in GitHub Desktop.
Save asmagin/707e25fd2c0617a4b7b271f89569de00 to your computer and use it in GitHub Desktop.
Sitecore + React
'use strict';
let path = require('path');
let webpack = require('webpack');
let baseConfig = require('./base');
let defaultSettings = require('./defaults');
// Add needed plugins here
let BowerWebpackPlugin = require('bower-webpack-plugin');
let config = Object.assign({}, baseConfig, {
entry: {
app: path.join(__dirname, '../src/index'),
components: path.join(__dirname, '../src/server.js')
},
output: {
path: path.join(__dirname, '/../dist/assets'),
filename: '[name].js',
publicPath: defaultSettings.publicPath
},
cache: false,
devtool: 'eval-source-map',
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new BowerWebpackPlugin({
searchResolveModulesDirectories: false
})
],
module: defaultSettings.getDefaultModules()
});
// Add needed loaders to the defaults here
config.module.loaders.push({
test: /\.(js|jsx)$/,
loader: 'babel',
include: [].concat(
config.additionalPaths,
[ path.join(__dirname, '/../src') ]
)
});
module.exports = config;
module.exports = {
// All the components you'd like to render server-side
HeaderComponent: require('./HeaderComponent'),
SimpleContentComponent: require('./SimpleContentComponent')
};
var Components = require('expose?Components!./components/common');
'use strict';
import React from 'react';
import { Grid, Row, Col } from 'react-bootstrap'
require('styles/common/SimpleContent.css');
let yeomanImage = require('../../images/yeoman.png');
var SimpleContentComponent = React.createClass({
propTypes: {
data: React.PropTypes.shape({
image: React.PropTypes.string,
title: React.PropTypes.string,
text: React.PropTypes.string
}).isRequired ,
placeholders: React.PropTypes.shape({
leftColumn: React.PropTypes.string,
rightColumn: React.PropTypes.string
}).isRequired
},
getDefaultProps: function() {
return {
data: {
image: '<img src="' + yeomanImage + '">',
title: 'SAMPLE: My First Sc.React Component',
text: 'SAMPLE: When designing interfaces, break down the common design elements (buttons, form fields, layout components, etc.) into reusable components with well-defined interfaces. <br/> That way, the next time you need to build some UI, you can write much less code. This means faster development time, fewer bugs, and fewer bytes down the wire.text'
},
placeholders: {
leftColumn: '',
rightColumn: ''
}
};
},
// this function would be called by ReactJS.NET to identify placeholders avaliable in a component.
getPlaceholders: function() {
return 'leftColumn|rightColumn';
},
render: function() {
return (
<Grid>
<Row>
<Col xs={12} md={4}><div dangerouslySetInnerHTML={{ __html: this.props.data.image }} /></Col>
<Col xs={12} md={8}>
<h1><div dangerouslySetInnerHTML={{ __html: this.props.data.title }} /></h1>
<div className='rte'>
<div dangerouslySetInnerHTML={{ __html: this.props.data.text }} />
</div>
</Col>
</Row>
<Row>
<Col xs={12} md={6}><div dangerouslySetInnerHTML={{ __html: this.props.placeholders.leftColumn }} /></Col>
<Col xs={12} md={6}><div dangerouslySetInnerHTML={{ __html: this.props.placeholders.rightColumn }} /></Col>
</Row>
</Grid>
)
}
});
module.exports = SimpleContentComponent;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Web.Mvc;
using Epam.Sc.EngX.CodeGeneration.Domain;
using Glass.Mapper.Sc;
using React;
using Sitecore.Data;
using Sitecore.Diagnostics;
using Sitecore.Mvc.Controllers;
using Sitecore.Mvc.Pipelines;
using Sitecore.Mvc.Pipelines.Response.RenderPlaceholder;
using Sitecore.Mvc.Presentation;
namespace Smagin.Common.Sc.Mvc.Controllers
{
public class SitecoreReactController : SitecoreController
{
private const string JsFunctionToGetPlaceholdersInfo = @"
(function(obj){{
if (typeof obj === 'undefined'
|| typeof obj.prototype.getPlaceholders !== 'function' ) {{
return [];
}}
return obj.prototype.getPlaceholders();
}})({0})
";
protected readonly ISitecoreContext Context;
public SitecoreReactController() : this(new SitecoreContext())
{
}
public SitecoreReactController(ISitecoreContext context)
{
Context = context;
}
/// <summary>
/// Get current data source object and cast it to a specific model
/// </summary>
/// <typeparam name="T">Class, that implements IGlassBase interface</typeparam>
/// <returns>Retunrs and instance of T type</returns>
public T DataSource<T>() where T : class, IGlassBase
{
var datasourceId = RenderingContext.Current.Rendering.DataSource;
if (ID.IsID(datasourceId))
{
return Context.GetItem<T>(new Guid(datasourceId));
}
return Context.GetCurrentItem<T>();
}
/// <summary>
/// Generate a content of a placeholder into a string
/// </summary>
/// <param name="placeholderName">Name of a placeholder</param>
/// <param name="rendering">Rendering definition object</param>
/// <returns>Returns string with a rendered placeholder content</returns>
protected virtual string Placeholder(string placeholderName, Rendering rendering)
{
Assert.ArgumentNotNull(placeholderName, "placeholderName");
var stringWriter = new StringWriter();
PipelineService.Get()
.RunPipeline("mvc.renderPlaceholder",
new RenderPlaceholderArgs(placeholderName, stringWriter, rendering));
return stringWriter.ToString();
}
/// <summary>
/// Generate component ReactJS action results
/// </summary>
/// <param name="componentName">Name of a component exposed from a js package</param>
/// <param name="model">Data to be passed into a component</param>
/// <param name="renderContainerOnly">Render only container flag</param>
/// <param name="renderServerOnly">Use only server-side rendering code</param>
/// <returns>ActionResult object</returns>
public virtual ActionResult React(string componentName, object model, bool renderContainerOnly = false,
bool renderServerOnly = false)
{
return React(componentName, model, RenderingContext.Current.Rendering, renderContainerOnly, renderServerOnly);
}
/// <summary>
/// Generate component ReactJS action results
/// </summary>
/// <param name="componentName">Name of a component exposed from a js package</param>
/// <param name="model">Data to be passed into a component</param>
/// <param name="rendering">Rendering definition object</param>
/// <param name="renderContainerOnly">Render only container flag</param>
/// <param name="renderServerOnly">Use only server-side rendering code</param>
/// <returns>ActionResult object</returns>
public virtual ActionResult React(string componentName, object model, Rendering rendering,
bool renderContainerOnly = false, bool renderServerOnly = false)
{
// Get placeholders meta information from a React Component. List of placeholders separated by pipe
var placeholderKeys =
ReactEnvironment.Current.Execute<string>(string.Format(JsFunctionToGetPlaceholdersInfo, componentName)) ?? "";
// Create dynamic object to convert dictionary keys into object properties
dynamic placeholders = new ExpandoObject();
var placeholdersDictionary = (IDictionary<string, object>) placeholders;
foreach (var placeholderKey in placeholderKeys.Split(new[] {"|"}, StringSplitOptions.RemoveEmptyEntries))
{
placeholdersDictionary.Add(placeholderKey, Placeholder(placeholderKey, rendering));
}
// Create ReactJS component props object
var reactComponent = ReactEnvironment.Current.CreateComponent(componentName, new
{
data = model,
placeholders
});
// Render ReactJS component
return Content(reactComponent.RenderHtml(renderContainerOnly, renderServerOnly));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment