Today I created a rendering component which has around 10 fields but the whole component is not editable in Experience Editor. I decided to use Edit Frame from Glass Mapper. The BeginEditFrame
wants all the editable fields as a parameter. But for around 10 fields not that comfortable.
The following code snippet creates an Edit Frame only with 1 field.
@using Glass.Mapper.Sc.Web.Mvc | |
@model IYourModel | |
@using (@Html.Glass().BeginEditFrame(Model, "Edit The Component", x => x.Image)) | |
{ | |
// your code | |
} |
Let’s implement a method which gets all the fields from your model.
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Linq.Expressions; | |
namespace YourProject.Extensions | |
{ | |
public static class ExperienceEditor | |
{ | |
public static Expression<Func<T, object>>[] GetAllEditFrameFields<T>() where T : IGlassBase | |
{ | |
var propertyNames = typeof(T).GetProperties().Select(p => p.Name); | |
var expressions = new List<Expression<Func<T, object>>>(); | |
foreach (var propertyName in propertyNames) | |
{ | |
var param = Expression.Parameter(typeof(T), "model"); | |
var body = Expression.Convert(Expression.PropertyOrField(param, propertyName), typeof(object)); | |
expressions.Add(Expression.Lambda<Func<T, object>>(body, param)); | |
} | |
return expressions.ToArray(); | |
} | |
} | |
} |
This method gets the model property names with some reflection magic and creates the lambda expressions dynamically.
You can see that the method has a limitation to allows only IGlassBase
interfaces. It is needed to make it more safe as this interface contains all the base properties for a Sitecore item.
using System; | |
using System.Collections.Generic; | |
using Sitecore.Globalization; | |
namespace YourProject.Models | |
{ | |
public interface IGlassBase | |
{ | |
Guid Id { get; set; } | |
Language Language { get; } | |
int Version { get; set; } | |
IEnumerable<Guid> BaseTemplateIds { get; } | |
string TemplateName { get; } | |
Guid TemplateId { get; set; } | |
string Name { get; set; } | |
string Url { get; } | |
string FullPath { get; } | |
} | |
} |
Let’s use this util method in our view.
@using Glass.Mapper.Sc.Web.Mvc | |
@using YourProject.Extensions | |
@model IYourModel | |
@using (@Html.Glass().BeginEditFrame(Model, "Edit The Component", ExperienceEditor.GetAllEditFrameFields<IYourModel>())) | |
{ | |
// your code | |
} |
Nice idea! That works really nicely with view models. Do you mind if add this or something similar to the framework?
LikeLiked by 3 people
That would be really cool 🙂 You can do it more optimizely directly in Glass.Mapper. Because now it is resolving the model twice. I would really appreciate it!
LikeLiked by 1 person