107 votes

Remplir une section de rasoir à partir d'un partiel

Ma principale motivation pour essayer de faire cela est d'obtenir le Javascript qui est seulement requis par un partiel au bas de la page avec le reste du Javascript et non au milieu de la page où le partiel est rendu.

Voici un exemple simplifié de ce que j'essaie de faire :

Voici la mise en page avec une section Scripts juste avant le corps.

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />    
</head>

<body>
    @RenderBody()
    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
    @RenderSection("Scripts", false)
</body>
</html>

Voici un exemple de vue utilisant cette mise en page.

<h2>This is the view</h2>

@{Html.RenderPartial("_Partial");}

@section Scripts {
<script type="text/javascript">
        alert("I'm a view.");
</script>
}

Et voici le rendu partiel de la vue.

<p>This is the partial.</p>

@* this never makes it into the rendered page *@
@section Scripts {
<script type="text/javascript">
    alert("I'm a partial."); 
</script>
}

Dans cet exemple, le balisage spécifié dans la vue est placé dans la section, mais pas le balisage du partiel. Est-il possible de remplir une section à partir d'une vue partielle avec Razor ? Si ce n'est pas le cas, quelles sont les autres méthodes pour obtenir du Javascript qui n'est nécessaire qu'aux partiels en bas de la page sans l'inclure globalement ?

0 votes

Peut-être que c'est un problème parce que vous avez une autre section script dans le partiel IDK votre code est un peu confus

1 votes

Ce n'est pas le cas. Même si la section est laissée hors de la vue, le code dans le partiel ne se retrouve pas dans la page finale rendue. Je pense que SLaks a raison de dire que les partiels ne peuvent pas participer aux sections de la vue parent.

80voto

Mr Bell Points 2990

La façon dont j'ai traité ce problème est d'écrire quelques méthodes d'extension à la classe HtmlHelper. Cela permet aux vues partielles de dire qu'elles ont besoin d'un script, puis dans la vue de mise en page qui écrit la balise, j'appelle ma méthode d'aide pour émettre les scripts requis.

Voici les méthodes d'aide :

public static string RequireScript(this HtmlHelper html, string path, int priority = 1)
{
    var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
    if (requiredScripts == null) HttpContext.Current.Items["RequiredScripts"] = requiredScripts = new List<ResourceInclude>();
    if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority });
    return null;
}

public static HtmlString EmitRequiredScripts(this HtmlHelper html)
{
    var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
    if (requiredScripts == null) return null;
    StringBuilder sb = new StringBuilder();
    foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
    {
        sb.AppendFormat("<script src=\"{0}\" type=\"text/javascript\"></script>\n", item.Path);
    }
    return new HtmlString(sb.ToString());
}
public class ResourceInclude
{
    public string Path { get; set; }
    public int Priority { get; set; }
}

Une fois que vous avez mis cela en place, votre vue partielle a juste besoin d'appeler @Html.RequireScript("/Path/To/Script") .

Et dans la section d'en-tête de la vue de mise en page, vous appelez @Html.EmitRequiredScripts() .

En outre, cela vous permet d'éliminer les demandes de script en double. Si vous avez plusieurs vues/parties de vues qui ont besoin d'un script donné, vous pouvez supposer sans risque que vous ne l'afficherez qu'une seule fois.

0 votes

Solution élégante et propre. +1

0 votes

Je viens de tomber sur cette solution après m'être arraché la plupart de mes cheveux - excellente solution.....

0 votes

Je n'arrive pas à faire fonctionner cette solution. Il semble que EmitRequiredScripts() soit appelé avant que les vues partielles puissent appeler RequireScript(). Est-ce que je fais quelque chose de mal ?

29voto

SLaks Points 391154

Les vues partielles ne peuvent pas participer aux sections de leurs vues parentes.

1 votes

C'est ce que je soupçonnais. Merci.

0 votes

JohnBubriski Il existe dans Razor 2. Je ne sais pas pour les versions précédentes.

0 votes

@SLaks, pourquoi est-ce à dessein ? Dans mon scénario, j'ai un partiel qui est un rotateur de bannière, je veux que ses scripts/styles ne soient chargés que lorsqu'il est activé, pourquoi est-ce mauvais de le charger en ligne ?

14voto

Sergi Papaseit Points 8979

Vous pourriez avoir un deuxième partiel qui se charge uniquement d'injecter le javascript nécessaire. Placez-y plusieurs scripts autour de @if des blocs, si vous voulez :

@model string
@if(Model == "bla") {
    <script type="text/javascript">...</script>
}

@else if(Model == "bli") {
    <script type="text/javascript">...</script>
}

Il est évident que cela pourrait être nettoyé un peu, mais alors, dans les Scripts de votre vue :

@section Scripts
{
    @Html.Partial("_Scripts", "ScriptName_For_Partial1")
}

Encore une fois, cela ne gagnera peut-être pas un prix de beauté mais cela fonctionnera.

1 votes

C'est assez proche de ce que j'ai fini par faire. Ce n'est pas très joli, mais ça marche. Le seul inconvénient est que vous ne pouvez pas obtenir le partiel via un appel ajax et avoir le JS inclus. Je pense qu'à long terme, je vais finir par refactorer en utilisant des templates jQuery et juste envoyer du JSON à partir de mes contrôleurs au lieu de construire le html du côté serveur.

0 votes

@CraigM c'est aussi ce vers quoi je me dirige. MVC est légitime, mais il est beaucoup plus logique (pour moi) d'utiliser des modèles côté client (je regarde Backbone.js) et ensuite de pousser/tirer à partir d'une API.

0 votes

@one.beat.customer - J'ai utilisé les modèles d'underscore puisque j'utilise aussi Backbone, mais je pense passer à la bibliothèque Hogan de Twitter ou Plates de Nodejitsu. Les deux ont des fonctionnalités très intéressantes.

10voto

VlaR Points 119

La façon la plus élégante de procéder est de déplacer les scripts de vue partielle dans un fichier séparé et de les rendre dans la section Scripts de la vue :

<h2>This is the view</h2>

@Html.RenderPartial("_Partial")

@section Scripts
{
    @Html.RenderPartial("_PartialScripts")

    <script type="text/javascript">
        alert("I'm a view script.");
    </script>
}

La vue partielle _ Partial.cshtml :

<p>This is the partial.</p>

La vue partielle _ PartialScripts.cshtml avec des scripts uniquement :

<script type="text/javascript">
    alert("I'm a partial script!");
</script>

0 votes

Ce n'est pas aussi automatique que certaines des méthodes d'extension ou de plug-in suggérées dans d'autres réponses, mais cela a l'avantage de la simplicité et de la clarté. Elle plaît.

7voto

Russ Cam Points 58168

Installer le Forloop.HtmlHelpers nuget - il ajoute quelques aides pour la gestion des scripts dans les vues partielles et les modèles d'éditeurs.

Quelque part dans votre mise en page, vous devez appeler

@Html.RenderScripts()

Ce sera l'endroit où tous les fichiers script et les blocs script seront sortis dans la page, donc je recommanderais de le mettre après vos scripts principaux dans la mise en page et après une section scripts (si vous en avez une).

Si vous utilisez The Web Optimization Framework avec le regroupement, vous pouvez utiliser la surcharge

@Html.RenderScripts(Scripts.Render)

afin que cette méthode soit utilisée pour l'écriture des fichiers script.

Maintenant, chaque fois que vous voulez ajouter des fichiers ou des blocs script dans une vue, une vue partielle ou un modèle, utilisez simplement

@using (Html.BeginScriptContext())
{
  Html.AddScriptFile("~/Scripts/jquery.validate.js");
  Html.AddScriptBlock(
    @<script type="text/javascript">
       $(function() { $('#someField').datepicker(); });
     </script>
  );
}

Les aides garantissent qu'une seule référence de fichier script est rendue si elle est ajoutée plusieurs fois et elles garantissent également que les fichiers script sont rendus dans un ordre attendu, c'est-à-dire

  1. Mise en page
  2. Partiels et modèles (dans l'ordre dans lequel ils apparaissent dans la vue, de haut en bas)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X