Where should my Javascript go for View Components?
Asked Answered
B

1

13

I'm getting used to view components in MVC 6, and I asked a similar question a few years ago about partial views. If I build a view component encapsulating a common use-case that requires its own Javascript, where do I put that Javascript? I know that it is dangerous at best to have Javascript in partial views, but it would be a lot simpler to include it in the view component, rather than in the containing view or a separate file that has to be referenced by the containing view.

For example, say I have a view component that has two drop-downs. The selection in the first drop-down determines what items appear in the second drop-down. This is easily handled in Javascript, of course, but where do I put it?

Balmy answered 21/1, 2016 at 19:31 Comment(0)
G
4

From my experience with ASP.NET 5 View Components, I would say that the best thing to do with them is to keep them isolated and in one place, so they will be easily to manage in long-term projects.

In one of my ASP.NET projects, I've developed View Components structure like this one:

View Components structure

View, Backend code and Model are all in one place, so when you move around the folder, you are sure that you move whole component. Moreover, when you are modyfying them, you have quick access to all of their parts.

It will be convinient to put JavaScript which is highly coupled with a component also in such structure. You can do this by simply creating the file under the component's folder, and then writing a GULP TASK that will copy JS file to wwwroot. From that point, you will be able to link that JavaScript code on component's .cshtml using standard syntax:

<script src="~/Components/yourcomponent.js"></script>

To obtain such a structure in my project, I've extended Razor, to be able to search for my component's CSHTML's in proper place. To do this, I've added this code in Startup.cs:

public partial class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
       //non relevant code skipped
       services.AddMvc().AddRazorOptions(ConfigureRazor);

    }

    public void ConfigureRazor(RazorViewEngineOptions razor)
    {
        razor.ViewLocationExpanders.Add(new ViewLocationExpander());
    }
}

and the ViewLocationExpander class is:

public class ViewLocationExpander : IViewLocationExpander
{
    protected static IEnumerable<string> ExtendedLocations = new[]
    {
        "/{0}.cshtml"
    };

    public void PopulateValues(ViewLocationExpanderContext context)
    {
        //nothing here
    }

    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {
        //extend current view locations
        return viewLocations.Concat(ExtendedLocations);
    }
}

Then, you invoke component like this (from any .cshtml view):

@await Component.InvokeAsync("NavigationComponent",new NavigationComponentModel())
Goebel answered 21/1, 2016 at 20:2 Comment(3)
From what I'm seeing, Javascript in view components is handled similarly to partials, but can be more isolated using your suggested approach or something like it. It looks like it's ok to have my Javascript isolated to view components as long as I don't do anything foolish with scope. Thanks!Balmy
About the way you add the javascript to the Component, wouldn't that create an issue if you're putting multiple times the same Component in one View? It means that you'll have multiple <script> tags with the same source, or did I miss something?Prepared
Yes, that's a good point, however it's easy to deal with it, i.e by saving temporary bool flag if the component was used beforeGoebel

© 2022 - 2024 — McMap. All rights reserved.