fluid icon indicating copy to clipboard operation
fluid copied to clipboard

How to use dotnet core viewcomponents in fluid?

Open Kevin-Deason opened this issue 5 years ago • 5 comments

My apologies if this is simple to do but I have searched for the last few days now and I can't figure it out.

Usually in a Razor page one would have code to invoke a ViewComponent @await Component.InvokeAsync("Products") or as a tag helper

<vc:products parameter1="parameter1 value" parameter2="parameter2 value"> </vc:products>

edit* I think this can be done with custom tags but I am facing the same problem as in https://github.com/sebastienros/fluid/issues/176

Where and how does one add the dependencies?

Kevin-Deason avatar May 03 '20 12:05 Kevin-Deason

The sample attached with the project shows a custom version that Fluid works with ASP.NET Core MVC, but not all the asp.net Core features is implemented to use Fluid

hishamco avatar May 04 '20 01:05 hishamco

Thank you for your prompt response, I appreciate it.

I have looked at the samples given and although they were quite helpful they are not very advanced.

I have created a custom tag that sort of does what I want but I'd prefer having it use the caching functionality of the Rendering Engine of fluid.

The below is just a hack I smashed together late last night and does what I want(will need to change it to be more dynamic on retrieving the model data and view.

Is there a better way to get the fluid View Engine to incorporate similar functionality as dotnet core's view components?

namespace TemplatingPOC.FluidTags
{
    public class ViewComponentTag : ExpressionTag
    {
        private IHttpContextAccessor _httpContext;
        private IHostingEnvironment _hostingEnvironment;

        internal HeaderTop GetHeaderTop() // TODO: Move this somewhere else
        {
            // TODO: Database.GeHeaderTop for current tenant
            var headerTop = new HeaderTop
            {
                DefaultWelcomeMessage = $"Welcome to my website",
                Items = new List<HeaderTopItem>()
            };

            headerTop.AddItem("Login", $"/account/login?tenant=tenant1");

            return headerTop;
        }

        public override async ValueTask<Completion> WriteToAsync(TextWriter writer, TextEncoder encoder,
            TemplateContext context, Expression expression)
        {

            //var scope = TemplateContext.GlobalScope;
            //var container = scope.GetValue("Container").ToObjectValue() as IContainer;
            //_httpContext = container.Resolve<IHttpContextAccessor>();
            var model = GetHeaderTop();


            var viewPath = (await expression.EvaluateAsync(context)).ToStringValue();
            if (!viewPath.EndsWith(FluidViewEngine.ViewExtension, StringComparison.OrdinalIgnoreCase))
            {
                viewPath += FluidViewEngine.ViewExtension;
            }

            var currentViewPath = context.AmbientValues[FluidRendering.ViewPath] as string;
            var currentDirectory = Path.GetDirectoryName(currentViewPath);
            var viewComponent = Path.Combine(currentDirectory, viewPath);

            var fileProvider = context.AmbientValues["FileProvider"];
            var fileInfo = (fileProvider as IFileProvider).GetFileInfo(viewComponent);
            context.Model = model;
            context.LocalScope.SetValue("Model", model);

            using (var stream = fileInfo.CreateReadStream())
            {
                using (var sr = new StreamReader(stream))
                {
                    var ss = sr.ReadToEnd();
                    if (FluidViewTemplate.TryParse(ss, out var template, out var errors))
                    {
                        await template.RenderAsync(writer, encoder, context);
                    }
                    else
                    {
                        throw new Exception(string.Join(Environment.NewLine, errors));
                    }
                }
            }

            return Completion.Normal;

        }
    }
}

Kevin-Deason avatar May 04 '20 09:05 Kevin-Deason

And the view(Header.liquid)

<div class="header-top">
    <div class="container">
        <div class="header-right">
            <p class="welcome-msg">{{Model.defaultWelcomeMessage}}</p>
            <div class="header-dropdown dropdown-expanded">
                <a href="#">Links</a>
                <div class="header-menu">
                    <ul>
                        {% for item in Model.items %}
                        <li><a href="{{item.link}}">{{item.displayText | prettyprint}}</a></li>
                        {% endfor %}
                    </ul>
                </div>
            </div>
        </div>
    </div>
</div>

Kevin-Deason avatar May 04 '20 09:05 Kevin-Deason

Is there a better way to get the fluid View Engine to incorporate similar functionality as dotnet core's view components?

If I'm not the wrong the sample provided in the repo is a show case of how Fluid can be used from withing AspNetCore, but may be @sebastienros has some feedback about what you asking for

hishamco avatar May 04 '20 19:05 hishamco

I assume the MVC View Engine could be extended with such tag. And probably also handle Tag Helpers (note Tag Helpers is already implemented in Orchard Core so that might be a good start)

sebastienros avatar May 03 '21 00:05 sebastienros