Pass default image to Sitecore MVC Field helper - sitecore

Anyone know how I can specify the default editor image that shows when rendering a sitecore Image field?
#Html.Sitecore().Field("Image", new { #class = "full" })
In Page Editor, before the author as set the image, I get the ugly default sitecore image. I want to specify my own for different cases. Is there a way to pass the default image to use the Field helper?

The default image is defined on the following item in the core database, which you can change.
Alternatively, you can subclass Sitecore's default image rendered (Sitecore.Xml.Xsl.ImageRenderer), and override the GetDefaultImage() method.
Another less fragile solution is to place an Edit Frame around the image. This allows you to retain the Page Editor functionality that you get from #Html.Sitecore().Field() helper.
This example assumes the use of the Glass Mapper, however, you should be able to adapt it to use the default SitecoreHelper.
#using (Html.BeginEditFrame(Model.Id, new ID(Constants.ItemIDs.EditFrameButtons.Image)))
{
if (Model.Image != null && !String.IsNullOrEmpty(Model.Image.Src))
{
// Render image here
}
else
{
<img src="//placehold.it/400x225/2379cf/fff" alt="placeholder_image" />
}
}

Related

How to make a NameValueCollection list editable in GlassMapper

I am trying to make a NameValueList collection editable with GlassMapper and I don't seem to be able to get to the bottom of this.
We have a list of validations that can be attached to a field and I would like to have the validation message editable in ExperienceEditor.
The collection is pre-processed when GlassMapper is retrieving the item:
Validations = glassItem.GetValidations();
#foreach(Validation validation in Model.Validations)
{
<div id="#validation.Identifier" ng-message="#validation.AngularKey" ng-cloak class="mtg-validation-msg">
#Html.Glass().Editable(validation, e => e.ErrorMessage)
</div>
}
Error that I am getting:
Failed item resolve - You cannot save a class that does not contain a property that represents the item ID. Ensure that at least one property has been marked to contain the Sitecore ID. Type: MyAssembly.Models.Validation
It is not possible to directly edit certain types of complex fields in the Experience Editor, such as Treelist, Multilist or Name Value Collection.
Instead, you should set up and use an Edit Frame. This will pop up a modal dialog allowing you to edit the field, it is not inline but means you do not need to leave the Experience Editor. This is the recommended approach to this problem.
Since you are using Glass Mapper, since version 4 you can declare Edit Frames all directly from code and now have to declare/set them up in the Core database first.
#if (Sitecore.Context.PageMode.IsExperienceEditor)
{
using (Html.Glass().BeginEditFrame(Model, "Edit", x => x.Validations))
{
<div>Edit Validations</div>
}
}
You might be interested in this blog post I wrote about adding a wrapper around the Edit Frame to make the UX more friendly.

Show preview of image in form

I want to achieve the following in a django form, for a models.ImageField:
do not show the standard <input type="file"> button ("choose file" button)
show a preview of the current image, for already populated models
for empty (new) models, show a custom button
clicking on the image preview or the custom button will open a file dialog to select the image from the user's file system
selecting a new image replaces the custom button or the old image preview with the preview of the new image
This seems to me like a normal workflow to select images in a form, but I do not seem to find any fully working solution. All I can find involves hacking around several parts:
styling the label and hiding the standard "choose file" button: https://www.youtube.com/watch?v=4p2gTDZKS9Y
use a widget instead of the standard for forms.FileField.
I have tried to use:
class ImagePreviewWidget(Widget):
def render(self, name, value, attrs=None):
return mark_safe('<img src="/media/%s" width="100px"/>' % escape(value))
For the widget, and I am using this in the form like this:
class DesignCampaignForm(ModelForm):
brand_logo = FileField(widget=ImagePreviewWidget)
This is properly showing the preview of the existing image, but I am unable to click on it to select another file, and even if I was that would not update the preview.
Is there an already available solution for this simple use case?
I haven't been able to find a complete solution, so I have done the following:
use a widget to render a modified ClearableFileInput, rendering an image and an <input> element
style the <input> in the element with CSS, to hide it
make sure that clicking in the image triggers the hidden <input> element, wrapping the <img> in a <label> and using the for attribute
add some javascript to replace the image preview whenever the selection in the <input> element changes
whenever the selection is cleared, show the original preview
A gist can be found here.
In my final solution (not yet in the gist), I have added a button for when the image is not yet selected.
edit: Gist only works for Django before version 1.11.x.
class ClearableFileInput has since been gutted and changed

render sitecore mvc renderings programmatically

I want to get all the renderings of a content item and render each of them to html string inside an MVC action using C# code. Below is the code I am using to get all the renderings of a content item.
Item item = Sitecore.Context.Database.GetItem(someItem);
RenderingReference[] myRenderings = item.Visualization.GetRenderings(Sitecore.Context.Device, true);
foreach (RenderingReference rendering in myRenderings)
{
RenderingItem renderingItem = rendering.RenderingItem;
}
I am able to get this list and the rendering item's Id. But how can i render them to html string here?
Note: the renderings could be of any rendering type like view renderings, xsl renderings , controller renderings etc. I dont want to use the approach of WebClient or HtmlAgility pack.
Not sure what you really try to do, but this code allows you to render a rendering in a MVC action and returns the Html for this:
public ActionResult GetFirstRenderingHtml()
{
var rendering = PageContext.Current.PageDefinition.Renderings.First();
return this.View(new RenderingView(rendering));
}
This actually only returns the code of the first rendering of the current item. If you want to call this action directly, you need to add the sc_itemid parameter in the to specify the context item:
/api/yourcontroller/GetFirstRenderingHtml?sc_itemid=<item id>
If you want the Html for a complete item with all it's renderings, I suggest you create a web request to get the output.

CustomItemGenerator and the Page Editor

Sitecore 6.6 Update 4
We're using CustomItemGenerator 1.0 and I was using this to help build a primary navigation menu for a site. This worked as expected and everything was rendered properly.
My problem is when I attempt to edit the menu via Page Editor; I don't even see the menu.
I use a repeater and repeat over a list of links to include in the nav. Due to the way the HTML was created, each LI element needs to have its own, specific ID ("Nav Id" Field in Sitecore) that ties into the CSS. Code inside of my repeater's ItemDataBound event:
// Cast the item using CustomItemGenerator-generated class
GenericContentPageItem navItem = (GenericContentPageItem)e.Item.DataItem;
liMenuItem.ID = navItem.NavId.Rendered; // I tried "navItem.NavId" by itself as well
So while this renders properly in the browser, it doesn't when I'm in Page Editor:
<li id="<input id='fld_B72EB6696DCF41A49671972D5EA5DEB8_2163B90C08AB4A18970A7F3ECE79DCFC_en_1_f71bd37d18d146c19e222e89fcffe278_3' class='scFieldValue' name='fld_B72EB6696DCF41A49671972D5EA5DEB8_2163B90C08AB4A18970A7F3ECE79DCFC_en_1_f71bd37d18d146c19e222e89fcffe278_3' type='hidden' value=" Home?="">
... instead of it rendering like this:
<li id="Home">...</li>
Now, that having been said, I can change my code to not use the CustomItemGenerator and it works fine in the browser and Page Editor as follows:
GenericContentPageItem navItem = (GenericContentPageItem)e.Item.DataItem;
Item nav = Sitecore.Context.Database.GetItem(navItem.ID);
liMenuItem.ID = nav.Fields["Nav Id"].ToString();
I would like to avoid having to hardcode field names in my code, which is why I am using CustomItemGenerator. Is there something that I'm doing wrong with my code that it doesn't want to work in Page Editor?
Thanks!
If you need the actual value out of the field regardless of if you are in the page editor or not, you want to use the Raw property:
liMenuItem.ID = navItem.NavId.Raw;

Accessing Sitecore Properties for an Image field in user control's Code-behind

I want to access (and then modify) the properties for the image field(s) in Sitecore (esp. interested in 'Dimensions' and 'Keep Ratio' check box) via a code-behind file (blah.ascx.cs).
[This to ensure that all the images have a consistent size, when displayed in the sublayouts (irrespective of the original size)]
I know these properties can be added manually, but for the case where content authors "forget" to add the dimensions for image(s), I don't want my sublayouts to screw up. Hence, I need a check for that.
Is there a way to access and then modify these properties via code?
Here is an image that shows exactly what I want to access and modify via code:
If you're using an <asp:Image ... /> and binding the ImageUrl via C#, you can access the ImageField in C# and get the properties, like so:
Sitecore.Data.Fields.ImageField field = item.Fields["My Image Field"];
// you can now access:
// field.Width
// field.Height etc...
If you're using a <sc:Image ... /> renderer or a regular <sc:FieldRenderer ... /> I would recommend you use <sc:FieldRenderer ... /> as the image parameters only work on that, as documented here.
Here's a sample snippet:
<sc:FieldRenderer FieldName="My Image Field" Parameters="w=100&h=200&as=1" runat="server" />
This to ensure that all the images have a consistent size, when displayed in the sublayouts (irrespective of the original size
I'd suggest to use FieldRenderer class, or <sc:image> for rendering such fields in sublayouts, and then specify "mh" (max height) and "mw" (max width) parameters, so they will always fit into layout.
You can read more about parameters here - http://sdn.sitecore.net/Articles/XSL/5%203%20Enhancements/Image%20Enhancements.aspx
Not a 100% sure (can't check here), but if you retrieve the field as an ImageField you should be able to access those values.
var cur = Sitecore.Context.Item;
Sitecore.Data.Fields.ImageField imgfield = cur.Fields["imagefieldname"] as Sitecore.Data.Fields.ImageField;
//imgfield.<properties>