In ASP.NET MVC / Razor, come aggiungere JavaScript di inizializzazione a un "controllo"?

5

In realtà, ho già almeno 3 diverse soluzioni per il problema, semplicemente non mi piacciono per nessuna ragione.

In ASP.NET MVC / Razor, non ci sono più controlli, nel senso in cui erano in ASP.NET. Un controllo ASCX usato per essere vista + controller si intrecciava, quindi ho capito. Invece abbiamo helper html che emettono stringhe, frammenti html. Diciamo che voglio creare un metodo di supporto in una libreria che crea un selettore di date dell'interfaccia utente jQuery.

Prima soluzione. Scrivo solo un metodo che prima crea una casella di testo (in realtà posso chiamare TextBoxFor perché fa la stessa cosa per me), quindi crea un piccolo frammento di codice JavaScript che chiama $('#textboxid').datepicker() . Quindi posso chiamarlo nelle mie visualizzazioni Razor e funziona. Non mi piace il fatto che le cose relative alla vista siano fatte in codice, e non in Razor, ma tutti i modelli di editor predefiniti sono così, purtroppo. Non mi piace il fatto che ci saranno molti piccoli frammenti di script dopo ogni casella di testo nell'output HTML. E il mio frammento di codice può diventare complesso, se quell'inizializzatore JS avesse molti parametri, sarebbe brutto, ci sarebbero problemi di escape delle stringhe, ecc.

Microsoft sta spingendo un'architettura JavaScript non invadente. Potrei semplicemente mettere una classe di marcatori CSS sulla mia casella di testo, aggiungere alcuni attributi dei dati, se necessario, ed emettere solo un JavaScript che trasforma tutte le mie caselle di testo fino alla data di selezione, in base alla classe del marcatore CSS. Questa ultima parte è il problema principale, ho bisogno di un codice JS imperativo per farlo. L'AJAX discreto e la convalida funzionano bene perché non ne hanno affatto bisogno, rispondono solo agli eventi di interazione dell'utente. Questo non è il caso, ho bisogno di trasformare le mie caselle di testo fino a raccoglitori di data ogni volta che appaiono. E possono apparire dinamicamente in una griglia modificabile, o dopo una chiamata AJAX, ogni volta.

Terza soluzione, la vista dovrebbe essere fatta in Razor, quindi facciamolo in Razor, come modello di editor. Il problema è che stiamo parlando di una biblioteca di classi qui. In passato, ho visto i brutti hack per incorporare i file .cshtml come risorse incorporate o compilarle nel codice C # durante la compilazione. L'ultima volta che ho controllato, sembravano brutti hack e non erano supportati.

C'è un'altra soluzione? In caso contrario, quale di questi è il più bello, quello più conforme alle convenzioni di codifica state-of-the-art, o l'idea di Microsoft, ecc.?

    
posta fejesjoco 14.01.2014 - 16:31
fonte

2 risposte

5

Non sono completamente sicuro di aver identificato il problema giusto, ma se lo avessi, questo potrebbe aiutare:

Abbiamo creato una classe chiamata ScriptManager che ci consente di aggiungere file javascript arbitrari e / o funzioni nella parte inferiore di tutte le nostre pagine al momento del rendering. Provalo:

public class ScriptManager
{
    public List<string> scripts = new List<string>();
    public List<string> scriptFiles = new List<string>();
}
public static class HtmlExtensions
{

    [ThreadStatic]
    private static ControllerBase pageDataController;
    [ThreadStatic]
    private static ScriptManager pageData;

    public static ScriptManager ScriptManager(this HtmlHelper html)
    {
        ControllerBase controller = html.ViewContext.Controller;

        // This makes sure we get the top-most controller
        while (controller.ControllerContext.IsChildAction)
        {
            controller = controller.ControllerContext.ParentActionViewContext.Controller;
        }
        if (pageDataController == controller)
        {
            // We've been here before
            return pageData;
        }
        else
        {
            // Initial setup
            pageDataController = controller;
            pageData = new ScriptManager();
            return pageData;
        }
    }
}

Quindi, nella parte inferiore della tua pagina _Layout.cshtml :

@foreach (var script in Html.ScriptManager().scriptFiles.Distinct())
{
    @Html.Script(script);
}
@foreach (var script in Html.ScriptManager().scripts)
{
    @Html.Raw("<script type='text/javascript'>")
    @Html.Raw(script)
    @Html.Raw("</script>")
}

Infine, lo usi in una vista parziale come:

@{
  Html.ScriptManager().scriptFiles.Add(Url.Content("~/Scripts/jquery.blockUI.js"));
 }

Perderai la possibilità di dire al client degli script nell'intestazione della pagina, ma saranno inclusi in tutte le pagine che utilizzi una vista parziale che usa il bloccoUI (ad esempio).

    
risposta data 14.01.2014 - 22:47
fonte
0

Un altro è avere un cshtml e il corrispondente controllore sotto. Tale cosa viene chiamata controllo e incorporata in un'altra vista utilizzando @Html.RenderPartial('<action_url>', <model>) . Nell'azione del controller dovrebbe essere annotata con l'attributo [ChildActionOnly] in modo che non possa essere chiamato in una chiamata diretta.

Non che io sia un grande fan di questo approccio, descrivilo qui in modo da avere una visione completa.

Puoi anche usare @helper del rasoio oltre a te @Html. helper.

    
risposta data 14.01.2014 - 21:02
fonte

Leggi altre domande sui tag