I am trying to write my first simple Sitecore Speak Component.
Nothing fancy about it i just need to get started. So i create in Visual Studio my Speak Component and in Sitecore i have my rendering that is pointing to my component. This is all out of the box. I insert my rendering on my SPEAK layout and when i visit the page i get an error saying this
Anyone has an idea why? What do i have to do? I am using Sitecore 7.5.
My cshtml looks like this:
#using Sitecore.Mvc
#using Sitecore.Mvc.Presentation
#using Sitecore.Web.UI.Controls.Common.UserControls
#model RenderingModel
#{
var rendering = Html.Sitecore().Controls().GetUserControl(Model.Rendering);
rendering.Class = "sc-Test2";
rendering.Requires.Script("client", "Test2.js");
var htmlAttributes = rendering.HtmlAttributes;
}
<div #htmlAttributes>
</div>
Basically the issue here is Sitecore SPEAK is unable to locate your javascript for the component.
It appears that you have your SPEAK component rendering and javascript in your own directory which is best practice. What you have to do is tell SPEAK where to look for your components. This is controlled within the Sitecore SPEAK config within the Include folder.
Here is an example of a patch include file to patch in directories for SPEAK to look for javascript components.
Set the source to the directory containing your custom components.The Deep = true parameters will scan subdirectories. Also note the category name here "MikeRobbins" in this example. Choose anything meaningful to your components, i would avoid using the Sitecore one not to impact sitecore standard components.
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<speak.client.resolveScript>
<processor type="Sitecore.Resources.Pipelines.ResolveScript.Controls, Sitecore.Speak.Client">
<sources hint="raw:AddSource">
<source folder="/sitecore/shell/client/MikeRobbins/Layouts/Renderings" deep="true" category="mikerobbins" pattern="*.js,*.css" />
</sources>
</processor>
</speak.client.resolveScript>
</pipelines>
</sitecore>
</configuration>
Update your component CSHTML and set the userControl.Requires.Script("mikerobbins"..... part to your category name you chose above. see example below.
#using Sitecore.Mvc
#using Sitecore.Mvc.Presentation
#using Sitecore.Web.UI.Controls.Common.UserControls
#model RenderingModel
#{
var userControl = Html.Sitecore().Controls().GetUserControl(Model.Rendering);
userControl.Requires.Script("mikerobbins", "JsonDataSource.js");
userControl.Attributes["type"] = "text/x-sitecore-jsondatasource";
userControl.DataBind = "Json: json";
var htmlAttributes = userControl.HtmlAttributes;
}
<script #htmlAttributes>
</script>
An example of this can be seen in my project here. https://github.com/sobek1985/SitecoreSPEAKBulkRolePermissions
Hope this helps, any problems give me a shout.
You can also specify the full javascript path in the Requires.Script method.
rendering.Requires.Script("/sitecore/shell/client/MikeRobbins/Layouts/Renderings/Test2.js");
Related
I tried to use ViewBag in a Sitecore MVC view rendering to pass some data to its relevant layout rendering but it didn't work. In standard ASP.NET MVC you can do that, but is it possible to do the same in Sitecore also? If not, then how do you pass data?
Edit
to clarify my question, here is what I was trying to do:
I have a layout rendering like this:
#using Sitecore.Mvc
#using Sitecore.Mvc.Analytics.Extensions
#using Sitecore.Mvc.Presentation
#model RenderingModel
#{
Layout = null;
}
<!doctype html>
<html>
<head>....</head>
<body>
#if (ViewBag.ShowNewsletterPopup == "display")
{
<!-- render proper html markup to show newsletter popup -->
}
else {
<!-- render regular html markup -->
}
<!-- some html markup here -->
#Html.Sitecore().Placeholder("widget")
<!-- some more html markup -->
And then, inside content placeholder goes a view rendering which has a code like this:
#using Sitecore.Mvc
#using Sitecore.Mvc.Presentation
#using Sitecore.Data.Items
#model RenderingModel
#{
ViewBag.ShowNewsletterPopup = Model.Rendering.Parameters["ShowNewsletterPopup"];
So, what I am trying to achieve is switching between two blocks of html markups depending on the settings of a view rendering which sits outside those blocks. Perhaps there is a better way to do this, but I am not sure. What I see is that the view rendering code gets compiled after layout rendering, so the code really never gets executed.
I can confirm that the current behaviour of Sitecore MVC would not work. In the following scenario MVC Layout with:
#using Sitecore.Mvc
#{
Layout = null;
ViewBag.Message = "ViewBagData";
}
<html>
<body>
Message: #Html.Partial("View Rendering") <br>
Message: #Html.Sitecore().ViewRendering("View Rendering")
</body>
</html>
And the View Rendering:
#ViewBag.Mything
You would see the following output:
Message: ViewBagData
Message:
The underlying issue is that the ViewRendering type spins up an new HtmlHelper. Althought the ViewData is passed into this, the actual write to the dictionary backing of the ViewData is deferred (this is an MVC thing).
I would think that the desired behaviour would be for ViewBag data to behave the same as it does for #Html.Partial().
There is a related topic around TempData on the Sitecore community user voice.
You could use something like (though it feels like a smell):
Sitecore.Context.Items["Message"]
Perhaps have a look at the this video, it has a concept around rendering interdependencies.
I need to style UL's coming from Rich Text Editor in Sitecore. I am trying to find out if there is a class that I can add to all UL's coming from Sitecore's Rich Text Editor.
Thanks in Advance
Ashok
The easiest solution is just to wrap your FieldRenderer with an HTML element with appropriate class applied in code:
<div class="rich-text">
<sc:FieldRenderer ID="frRichTextField" runat="server" FieldName="MyFieldName" />
</div>
And then add in some CSS styles to handle your UL's within this:
.rich-text ul {
/* add in your styling */
}
You can also use the before and after properties of the FieldRenderer to pass in your tag:
<sc:FieldRenderer ID="frRichTextField" runat="server" FieldName="MyFieldName"
Before="<div class='rich-text'>" After="</div>" />
EDIT:
If you wanted to be more drastic then you could add in your own renderField pipeline processor to ensure your control is always wrapped with the required tag or you could make use of the enclosingTag property and patch the AddBeforeAndAfterValues pipeline instead:
namespace MyCustom.Pipelines.RenderField
{
public class AddBeforeAndAfterValues
{
public void Process(RenderFieldArgs args)
{
Assert.ArgumentNotNull((object)args, "args");
if (args.Before.Length > 0)
args.Result.FirstPart = args.Before + args.Result.FirstPart;
if (args.After.Length > 0)
{
RenderFieldResult result = args.Result;
string str = result.LastPart + args.After;
result.LastPart = str;
}
if (args.EnclosingTag.Length == 0 || args.Result.FirstPart.Length <= 0 && args.Result.LastPart.Length <= 0)
return;
// check if a css class paramter has been passed in
string cssClass = args.Parameters.ContainsKey("class") ? args.Parameters["class"] : String.Empty;
// add the class to the enclosing tag property
args.Result.FirstPart = StringExtensions.FormatWith("<{0} class='{1}'>{2}", (object)args.EnclosingTag, cssClass, (object)args.Result.FirstPart);
args.Result.LastPart = StringExtensions.FormatWith("{0}</{1}>", (object)args.Result.LastPart, (object)args.EnclosingTag);
}
}
}
Patch the Sitecore config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"
xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<pipelines>
<renderField>
<processor type="Sitecore.Pipelines.RenderField.GetLinkFieldValue, Sitecore.Kernel"
set:type="MyCustom.Pipelines.RenderField.AddBeforeAndAfterValues, MyCustom.Pipelines" />
</renderField>
</pipelines>
</sitecore>
</configuration>
And then call the FieldRenderer with the EnclosingTag set and pass in your class parameter:
<sc:FieldRenderer ID="frRichTextField" runat="server" FieldName="MyFieldName"
EnclosingTag="div" Parameters="class=rich-text" />
This really doesn't add much over using the before/after properties though and I would generally try to stay away from overwriting default Sitecore processors to save heartache when upgrading.
You could either tap into relevant pipelines or update your sublayouts so that you always have a fixed class around every instance of the rich text field rendering:
<div class="rtf">
<sc:Text ID="scContent" runat="server" FieldName="Content" />
</div>
You will have to make sure as a developer that all current and future instances of rich text field renderings are enclosed by a tag with this class.
You could then include in the global CSS, a common style for this class.
.rtf ul {
...
....
}
If you don't want to have to add this wrapper for every single rtf rendering, you could tap into a relevant pipeline. (Note - this might be a better approach with regard to code maintainability)
You could choose to use one of the two:
renderField pipeline
or the
saveRichTextContent pipeline
So you would add a new processor for either of these pipelines, in which you could access the text within rich text fields only and process that as you please (easier to manipulate the html using the html agility pack)
If you use renderField pipeline - the text within the rich text field in sitecore will not change, the code you write will execure only while rendering the field - in preview / page editor or normal mode.
Using saveRichTextContent pipeline on the other hand, will update the in the rich text field when the content author clicks on save (after entering the text) in content editor mode.
You can see the following examples for these:
renderField - http://techmusingz.wordpress.com/2014/05/25/unsupported-iframe-urls-in-sitecore-page-editor-mode/ (Sample of HtmlUtility is also present here - instead of selecting all tags, you could select all and add your desired class attribute.)
saveRichTextContent - http://techmusingz.wordpress.com/2014/06/14/wrapping-rich-text-value-in-paragraph-tag-in-sitecore/
Hope this helps.
Best practice would be to just add the Class to the Rich Text Editor for use in the Editor.
There are lots of good articles on doing this. Here are a couple:
http://sitecoreblog.blogspot.com/2013/11/add-css-class-to-richtext-editor.html
http://markstiles.net/Blog/2011/08/13/add-css-classes-to-sitecore-rich-text-editor.aspx
These are minimal changes that provide you with the ability to put the styling ability in the hands of the Content Author, but still controlling what styles and classes they can use inline.
The Crosssells do not seem to be working on my Magento EE install, for the product view page.
Ive debugged the product list crosssells block, but seems to crash out somewhere on its way through the various code, whilst collecting the collection. Cant work out why (whitescreens when debug to a certain level...and item collection thus not being set. Hard to figure out. No exceptions being logged).
I have no errors on the install...and sure i should not need to edit any logic, as the functionality is provided by default.
Ive followed this example:
http://www.magentocommerce.com/boards/viewthread/51529/
My crossells show on the cart page, as they usually do...but i cant get them to display on my product view page.
Heres my bits of code:
Catalog.xml:
<block type="catalog/product_list_crosssell" name="product.info.crosssell" as="crosssell_products" template="catalog/product/list/crosssell.phtml"/>
product/list/crosssell.phtml:
if(count($this->getItems())): ?>
<div id="also_bought_productslist" class="inner">
<?php $i=0;
foreach ($this->getItems() as $product):
Anyone know what i may be missing. And has anyone added crossells to their product view page?
Just to clarify...THIS IS USING THE DEFAULT PRODUCT_LIST_CROSSELL block...and im NOT trying to utilise the checkout/cart/crossell code (i know this relies on cart functionality/data to work correctly. I did attempt this though, and still get no crossell items....but they DO show in the cart page.)
many thanks
Syntax within the catalog xml file. Namely, an AFTER="blahblah" declaration...and use of same block code twice
Old code:
<block type="catalog/product_list_crosssell" name="product.info.crosssell" as="crosssell_products" template="catalog/product/list/crosssell.phtml"/>
<block type="catalog/product_list_related" name="alsoboughttabs" after="forgettoaddproducts" template="pagetabs/alsobought_pagetabs.phtml" />
<block type="catalog/product_list_related" name="forgettoaddproducts" after="product.info" template="catalog/product/list/dontforgettoadd.phtml" />
New code:
<block type="catalog/product_list_crosssell" name="product.info.crosssell" as="crosssell_products" template="catalog/product/list/crosssell.phtml"/>
<block type="catalog/product_list_upsell" name="alsoboughttabs" template="pagetabs/alsobought_pagetabs.phtml" />
<block type="catalog/product_list_related" name="forgettoaddproducts" after="product.info" template="catalog/product/list/dontforgettoadd.phtml" />
As part of an SEO enhancement project, I've been tasked with adding the following property inside the markup for the image that the field renderer is generating on the page:
itemprop="contentURL" - before the closing tag.
<sc:FieldRenderer ID='FieldRenderer_MainImage' Runat='server' FieldName='Homepage Image'
CssClass="_image" Parameters="w=150" itemprop="contentURL" />
When I tried to place this inside the Field Renderer, or add it as a "parameter" - it doesn't work.
Is there another way to do this, without having to create a control file and generate the output in the code-behind?
You need to use the "Parameters" property for setting extra properties on both the and control.
You can to it like this :
<sc:FieldRenderer ID="PageImage" runat="server" FieldName="ContentImage" Parameters="ControlType=C4Image&rel=relString" />
<sc:Image ID="SCPageImage" runat="server" Field="ContentImage" Parameters="ControlType=C4Image&rel=relString" />
That will be rendered like this :
<img width="1232" height="637" controltype="C4Image" rel="relString" alt="" src="~/media/Images/DEMO backgrounds/background2.ashx">
Note: This works in 6.5 and 6.6 - not sure which version is being used in this question.
Couldn't this be done by extending the RenderField pipeline? You could potentially decompile (using Reflector or ILSpy) the GetImageFieldValue and add your own logic to adjust the output from the ImageRenderer?
Reference Sitecore.Pipelines.RenderField.GetImageFieldValue.
In cases where "Parameters" doesn't work or trying to create a Custom control, and instead of wrapping the control in a classed div like this:
<div class="my-class">
<sc:FieldRenderer runat="server" />
</div>
You can use this:
<sc:FieldRenderer Before="<div class='my-class'>" After="</div>" runat="server" />
Notice the Single quotes in the class declaration of the div above.
This keeps it a little cleaner and in context with the Sitecore control instead of a Web Developer adding an external div that might later lose its context if changes occur.
I recommend saving yourself some trouble and using the MVC version of Sitecore though, now, (when starting new Sitecore projects), as you can very simply add a class to it like so:
How can I get Sitecore Field Renderer to use a css class for an image
You actually cannot do this on a FieldRenderer. You're options are:
Extend the FieldRenderer with the ability to do this (this will likely require a high level of effort)
Use a regular .NET control and bind the data from the Sitecore item via the C# code-behind.
You may want to try using the <sc:image /> tag.
If you add a custom parameter there, it's added as an attribute to the img tag.
In your case the tag will look like this:
<sc:image runat="server" field="Homepage Image" width="150" itemprop="contentURL" class="_image" />
using mvc, I found this was easier than extending the FieldRender, should be reusable, but will have to test a bit more. WIP.
var image = "<span class=\"rightImage\">" + FieldRenderer.Render(contentBlock, "Image", "mw=300") + "</span>";
var text = FieldRenderer.Render(contentBlock, "Text");
model.Text = FieldRendererHelper.InjectIntoRenderer(text, image, "<p>");
public static HtmlString InjectIntoRenderer(string parentField, string injectField, string injectTag)
{
return new HtmlString(parentField.Insert(parentField.IndexOf(injectTag, StringComparison.InvariantCulture) + injectTag.Length, injectField));
}
I am creating an email engine in mvc3 and I am trying to use razor views as email templates.
I heard this is possible but I have not yet found any information about it.
You can use http://razorengine.codeplex.com/ to achieve this. It allows you to use razor outside of mvc.
string Email = "Hello #Model.Name! Welcome to Razor!";
string EmailBody = Razor.Parse(Email, new { Name = "World" });
It's simple to implement and it's available on http://nuget.codeplex.com/ for easy integration into your projects.
You CAN use a template file to serve as a razor email body template. You can use whichever extension you choose because you can load a file as text in .Net. Let's use the following example for the template:
Hello #Model.Name,
Welcome to #Model.SiteName!
Regards,
Site Admins
Save that file as something like "WelcomeMessage.cshtml", "WelcomeMessage.template", etc. Select the file in Solution Explorer and in the Properties window, select "Copy to Output Directory" and choose "Copy Always". The only down point is that this template has to accompany the application and doesn't compile as a class.
Now we want to parse it as a string to assign to a mail message body. Razor will take the template and a model class, parse them, and then return a string with the necessary values.
In your application you will need to add the RazorEngine package which can be found with NuGet. Here's a short code example to illustrate the usage:
using System.IO;
using RazorEngine;
// ...
MyModel model = new MyModel { Name = "User", SiteName = "Example.com" };
string template = File.OpenText("WelcomeMessage.template").ReadToEnd();
string message = Razor.Parse(template, model);
It's similar to the other answers but shows a quick way to load the template from a text file.
You should perhaps consider MvcMailer. RazorEngine is (very) good if you aren't already using MVC (I've used it successfully in a webforms context), but if you have MVC you may as well take advantage of it.
(via Hanselmen's NuGet package of the week 2)
You can also use Essential Mail: Razor package from NuGet. It is build over RazorEngine and provides simple interface for email rendering.
Email message template looks something like
#inherits Essential.Templating.Razor.Email.EmailTemplate
#using System.Net;
#{
From = new MailAddress("example#email.com");
Subject = "Email Subject";
}
#section Html
{
<html>
<head>
<title>Example</title>
</head>
<body>
<h1>HTML part of the email</h1>
</body>
</html>
}
#section Text
{
Text part of the email.
}
Read more on GitHub: https://github.com/smolyakoff/essential-templating/wiki/Email-Template-with-Razor
Mailzor
Linked to what #thiagoleite mentioned, I took Kazi Manzur Rashid's idea (with permission) and extended in to be more friendly for how I wanted to use it.
So check out the github project 'mailzor'
It's also up on Nuget.org/packages/mailzor