-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Widgets overwrite zone tag helper. #11481
Comments
Upon further investigation the widget doesn't overwrite the zone tag helpers (the widget filter runs before the tag helpers), but it breaks them. It's because the zone shape ( It seems to me, that the |
Layout zones are pre-rendered before executing the layout itself, so using the zone tag helper here is too late. The zone tag helper can be used while rendering any layout zone, for example through a part / field shape while rendering the layout Content zone, through a widget in any zone using the Liquid zone tag targetting another zone, and so on. The only constraint is that the targeted layout zone should not be pre-rendered before the layout zone in which the zone tag helper is used, for info the first pre-rendered layout zone is the layout Content zone. |
Good to take a look at |
Zones are pre-rendered in |
I don't think it should be too late at this point, this should work up until the using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Logging;
using OrchardCore.DisplayManagement;
using OrchardCore.DisplayManagement.Layout;
using OrchardCore.DisplayManagement.Shapes;
using OrchardCore.DisplayManagement.Zones;
using System;
using System.Threading.Tasks;
namespace Lombiq.HelpfulLibraries.OrchardCore.Shapes;
[HtmlTargetElement("zone2", Attributes = NameAttribute)]
public sealed class Zone2TagHelper : TagHelper
{
private const string PositionAttribute = "position";
private const string NameAttribute = "name";
private readonly ILayoutAccessor _layoutAccessor;
private readonly Func<ValueTask<IShape>> _zoneFactory;
private readonly ILogger<Zone2TagHelper> _logger;
public Zone2TagHelper(
ILayoutAccessor layoutAccessor,
IShapeFactory shapeFactory,
ILogger<Zone2TagHelper> logger)
{
_layoutAccessor = layoutAccessor;
_zoneFactory = () => shapeFactory.CreateAsync("Zone");
_logger = logger;
}
[HtmlAttributeName(PositionAttribute)]
public string Position { get; set; }
[HtmlAttributeName(NameAttribute)]
public string Name { get; set; }
public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
if (string.IsNullOrEmpty(Name))
{
throw new ArgumentException("The name attribute can't be empty");
}
return ProcessInnerAsync(output);
}
private async Task ProcessInnerAsync(TagHelperOutput output)
{
var childContent = await output.GetChildContentAsync();
var layout = await _layoutAccessor.GetLayoutAsync();
var zone = layout.Zones[Name];
if (zone is PositionWrapper positionWrapper && layout is ZoneHolding zoneHolding)
{
zone = new ZoneOnDemand(_zoneFactory, zoneHolding, Name);
await zone.AddAsync(positionWrapper, positionWrapper.Position);
}
if (zone is Shape shape)
{
await shape.AddAsync(childContent, Position);
}
else
{
_logger.LogWarning(
"Unable to add shape to the zone using the <zone2> tag helper because the zone's type is " +
"\"{ActualType}\" instead of the expected {ExpectedType}",
zone.GetType().FullName,
nameof(Shape));
}
// Don't render the zone tag or the inner content
output.SuppressOutput();
}
} |
Yes, the result of a pre-rendering is a
Then good idea to wrap it but as I remember we do pre-rendering for perf, hmm but here we re-build a zone on demand, but only on demand ;) So looks like a good solution allowing to add items to a zone later on. |
If you suggest a PR, would need to also update the Liquid |
For info zones are pre-rendered since #5436, not for perf but for the following (and not only I think).
So okay, your suggested version allows to add items to an already pre-rendered zone, e.g. from a given layout (we can have different layouts) or from any other zone. Just one thing to be aware of, the positioning may not be relative to the positions of other zone items if the whole is already pre-rendered, the PositionWrapper having no specific position in itself. |
Technically you can use However, IMHO zone tag helper should not be defined within The reason its prerendered is not just perf but also to collect resource info defined in zones which rendered in head section of layout before actual zone rendering |
I'm fine with discouraging this use case, but currently it's not communicated to the developer at all. So at first it works anyway, and when it breaks silently the developer is left confused. At least a |
Isn't it already throwing an Not implemented exception ? |
It doesn't throw.
|
Describe the bug
I can't use both
<zone>
tag helpers and widgets for the same zone. If you have a widget in the zone, the content in zone tag helpers are ignored.To Reproduce
Steps to reproduce the behavior:
Hello from Widget!
and any tag helpers are ignored.Expected behavior
You should see
in the footer.
The text was updated successfully, but these errors were encountered: