Inyectar contenido en secciones específicas de una vista parcial ASP.NET MVC 3 con Razor View Engine



Answers

Esta es una pregunta bastante popular, así que publicaré mi solución.
Tuve el mismo problema y aunque no es ideal, creo que realmente funciona bastante bien y no hace que el parcial dependa de la vista.
Mi hipótesis era que una acción era accesible por sí misma, pero también podría integrarse en una vista: un mapa de Google.

En mi _layout tengo:

@RenderSection("body_scripts", false)

En mi vista de index tengo:

@Html.Partial("Clients")
@section body_scripts
{
    @Html.Partial("Clients_Scripts")
}

En mi vista de clients tengo (todo el mapa y assoc. Html):

@section body_scripts
{
    @Html.Partial("Clients_Scripts")
}

La vista My Clients_Scripts contiene el javascript que se representará en la página

De esta forma, mi secuencia de comandos está aislada y puede mostrarse en la página donde se requiera, con la etiqueta body_scripts solo representada en la primera aparición que el motor de visualización de la máquina de afeitar la encuentre.

Eso me permite separar todo: es una solución que funciona bastante bien para mí, otros pueden tener problemas, pero repara el agujero "por diseño".

Question

Tengo esta sección definida en mi _Layout.cshtml

@RenderSection("Scripts", false)

Puedo usarlo fácilmente desde una vista:

@section Scripts { 
    @*Stuff comes here*@
}

Lo que estoy luchando es cómo obtener contenido inyectado dentro de esta sección desde una vista parcial.

Supongamos que esta es mi página de vista:

@section Scripts { 

    <script>
        //code comes here
    </script>
}

<div>
    poo bar poo
</div>

<div>
  @Html.Partial("_myPartial")
</div>

Necesito inyectar un poco de contenido dentro de la sección Scripts desde _myPartial partial view.

¿Cómo puedo hacer esto?




Usando Mvc Core puedes crear scripts TagHelper ordenados como se ve a continuación. Esto podría transformarse fácilmente en una etiqueta de section donde también se le da un nombre (o el nombre se toma del tipo derivado). Tenga en cuenta que la inyección de dependencia debe configurarse para IHttpContextAccessor .

Al agregar scripts (por ejemplo, en un parcial)

<scripts>
    <script type="text/javascript">
        //anything here
    </script>
</scripts>

Al enviar los guiones (por ejemplo, en un archivo de diseño)

<scripts render="true"></scripts>

Código

public class ScriptsTagHelper : TagHelper
    {
        private static readonly object ITEMSKEY = new Object();

        private IDictionary<object, object> _items => _httpContextAccessor?.HttpContext?.Items;

        private IHttpContextAccessor _httpContextAccessor;

        public ScriptsTagHelper(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            var attribute = (TagHelperAttribute)null;
            context.AllAttributes.TryGetAttribute("render",out attribute);

            var render = false;

            if(attribute != null)
            {
                render = Convert.ToBoolean(attribute.Value.ToString());
            }

            if (render)
            {
                if (_items.ContainsKey(ITEMSKEY))
                {
                    var scripts = _items[ITEMSKEY] as List<HtmlString>;

                    var content = String.Concat(scripts);

                    output.Content.SetHtmlContent(content);
                }
            }
            else
            {
                List<HtmlString> list = null;

                if (!_items.ContainsKey(ITEMSKEY))
                {
                    list = new List<HtmlString>();
                    _items[ITEMSKEY] = list;
                }

                list = _items[ITEMSKEY] as List<HtmlString>;

                var content = await output.GetChildContentAsync();

                list.Add(new HtmlString(content.GetContent()));
            }
        }
    }



Bueno, supongo que los otros carteles te proporcionaron un medio para incluir directamente una @sección dentro de tu parcial (usando ayudantes html de terceros).

Pero creo que, si su script está estrechamente relacionado con su parcial, simplemente coloque su javascript directamente dentro de una etiqueta <script> línea dentro de su parcial y termine con esto (solo tenga cuidado con la duplicación de scripts si tiene la intención de usar el parcial más de una vez en una sola vista);




Tuve este problema y usé this técnica.

Es la mejor solución que encontré, que es muy flexible.

También vote here para agregar soporte para la declaración de sección acumulativa




No puede necesitar usar secciones en vista parcial.

Incluir en su Vista parcial. Ejecuta la función después de que jQuery cargó. Puede alterar la cláusula de condición para su código.

<script type="text/javascript">    
var time = setInterval(function () {
    if (window.jQuery != undefined) {
        window.clearInterval(time);

        //Begin
        $(document).ready(function () {
           //....
        });
        //End
    };
}, 10); </script>

Julio Spader




Tuve el problema similar resuelto con esto:

@section ***{
@RenderSection("****", required: false)
}

Esa es una forma bonita de inyectar, adivino.




Si tiene una necesidad legítima de ejecutar algunos js de un partial , he aquí cómo puede hacerlo, se requiere jQuery :

<script type="text/javascript">        
    function scriptToExecute()
    {
        //The script you want to execute when page is ready.           
    }

    function runWhenReady()
    {
        if (window.$)
            scriptToExecute();                                   
        else
            setTimeout(runWhenReady, 100);
    }
    runWhenReady();
</script>



La primera solución que puedo pensar es usar ViewBag para almacenar los valores que se deben representar.

Primero, nunca lo intenté si esto funciona desde una vista parcial, pero debería ser imo.




Puede utilizar estos métodos de extensión : (Guardar como PartialWithScript.cs)

namespace System.Web.Mvc.Html
{
    public static class PartialWithScript
    {
        public static void RenderPartialWithScript(this HtmlHelper htmlHelper, string partialViewName)
        {
            if (htmlHelper.ViewBag.ScriptPartials == null)
            {
                htmlHelper.ViewBag.ScriptPartials = new List<string>();
            }

            if (!htmlHelper.ViewBag.ScriptPartials.Contains(partialViewName))
            {
                htmlHelper.ViewBag.ScriptPartials.Add(partialViewName);
            }

            htmlHelper.ViewBag.ScriptPartialHtml = true;
            htmlHelper.RenderPartial(partialViewName);
        }

        public static void RenderPartialScripts(this HtmlHelper htmlHelper)
        {
            if (htmlHelper.ViewBag.ScriptPartials != null)
            {
                htmlHelper.ViewBag.ScriptPartialHtml = false;
                foreach (string partial in htmlHelper.ViewBag.ScriptPartials)
                {
                    htmlHelper.RenderPartial(partial);
                }
            }
        }
    }
}

Use esto:

Ejemplo parcial: (_MyPartial.cshtml) Coloque el html en if y el js en else.

@if (ViewBag.ScriptPartialHtml ?? true)
    <p>I has htmls</p>
}
else {
    <script type="text/javascript">
        alert('I has javascripts');
    </script>
}

En su _Layout.cshtml, o donde quiera que se procesen los scripts de los parciales, ponga lo siguiente (una vez): solo renderizará el javascript de todos los parciales en la página actual en esta ubicación.

@{ Html.RenderPartialScripts(); }

Luego, para usar su parcial, simplemente haga esto: renderizará solo el html en esta ubicación.

@{Html.RenderPartialWithScript("~/Views/MyController/_MyPartial.cshtml");}



De forma personalizada, puede usar una carpeta Folder / index.cshtml como página maestra y luego agregar scripts de sección. Entonces, en tu diseño tienes:

@RenderSection("scripts", required: false) 

y su index.cshtml:

@section scripts{
     @Scripts.Render("~/Scripts/file.js")
}

y funcionará sobre todas tus vistas parciales. Funciona para mí




Links