Open kdubious opened 3 years ago
I think what you're trying to achieve is to be able to write a widget template, without specifying in that widget template this div <div class="@String.Join(" ", Model.Classes.ToArray())">
?
Unless I'm mistaken?
Wrappers are evil.
I suggest to try and avoid them as much as possible, but that's an opinionated, reasonably hard won voice of experience. We probably spend more time removing wrappers than adding them.
But it's totally possible to do already.
Just add an IShapeTableProvider
which adds whatever wrapper you want.
Something like
builder.Describe("Content")
.OnDisplaying(displaying =>
{
dynamic shape = displaying.Shape;
if (displaying.Shape.Metadata.DisplayType == "Detail" && shape.ContentItem.Content.Body != null)
{
displaying.Shape.Metadata.Alternates.Add("Content__Body");
displaying.Shape.Metadata.Wrappers.Add("SomeFunkyWrapperShapeNameHere");
}
});
or just do that in a FlowPart
template.
widgetContent.Metadata.Wrappers.Add("ShapeName");
@await DisplayAsync(widgetContent)
or via placement...
The voice of experience bit says, that when you do that, you'll eventually find one widget.template that needs to modify it's classes slightly. So then you'll end up with switches all through the FlowPart
template, or IShapeTableProvider
, like
if (widget.ContentType == "thisspecialone")
{
widgetContent.Classes.Add("offset-3")
}
else if(...)
{
}
Recommendation is to refactor FlowPart.cshtml and extract the section that defines the classes into a new intermediate shape, like FlowMetadata.cshtml
based on the c# type FlowMetadataViewModel { FlowMetadata, IShape Widget }
that will render:
if (flowMetadata != null)
{
widgetContent.Classes.Add("widget");
widgetContent.Classes.Add("widget-" + widget.ContentItem.ContentType.HtmlClassify());
widgetContent.Classes.Add("widget-align-" + flowMetadata.Alignment.ToString().ToLowerInvariant());
widgetContent.Classes.Add("widget-size-" + flowMetadata.Size);
}
@await DisplayAsync(widgetContent)
This won't break any existing site. Themes can now define a common way to render the chrome/positioning for widgets.
But each widget should still understand how its positioning is defined (classes right now).
Documentation of this new template should be provided in Liquid and Razor.
Currently, we have a workaround where we add 2 Alternates to Widget.cshtml to allow us to override a custom widget template, yet still wrap the widget with this:
<div class="@String.Join(" ", Model.Classes.ToArray())">
Let's work out how to create a wrapper for widgets in a Flow or a Layer.