Search code examples
javascriptcssassetscastle-monorailnvelocity

Can I programmatically append tags to <head> from within body in Castle MonoRails / NVelocity?


I've been trying to find a way to programmatically add a link to an external CSS file to the <head> tag from markup within the <body> tag in Castle MonoRails and NVelocity view engine. Anyone know how this can be done?

I need to resolve this problem as the page I work on can consist of many "widgets", and each widget would optimally acquire additional assets such as JS and CSS, rather than putting the <link ..> within the body tag and risk rendering problems.


Solution

  • The solutions posted here are not properly working. A better approach is to add your scripts to httpContext.Current.Items

    Using same structure as @jishi:

    in your view or your viewcomponent, you would be able to invoke something like this:

    $Style.Add("/static/style1.css")
    

    and in your layout (head-section):

    $Style.Render()
    

    Your helper consists of 2 simple methods using httpcontext to store and retreive the list of files.

        public class StyleHelper
    {
        public static void Add(string file) {
            if (string.IsNullOrWhiteSpace(file))
                return;
    
            var obj = HttpContext.Current.Items["AssetFiles"] as List<string>; // get the collection which might be empty
            if (obj == null || obj.Count == 0) {
                IList<string> list = new List<string>();
                list.Add(file.ToLower());
                HttpContext.Current.Items.Add("AssetFiles", list); // adds your first asset to your collection and returns
                return;
            }
    
            if (obj.Contains(file.ToLower()))
                return; // asset is already added
    
            // new asset ready to be added to your collection
            obj.Add(file.ToLower());
            HttpContext.Current.Items.Add("AssetFiles", obj);
        }
    
        public string Render() {
            var obj = HttpContext.Current.Items["AssetFiles"] as List<string>;
            if (obj == null || obj.Count == 0)
                return ""; // you never added anything to the collection. Nothing more to do.
    
            // not using linq here for the sake of readability:
            string res = string.Empty;
            foreach (var item in obj) {
                res = res + string.Format("<link rel=\"stylesheet\" {0} />", item);
            }
            return res;
        }
    
    }
    

    In your controller (preferably base controller) add this:

    [Helper( typeof( StyleHelper ), "Style" )] public class YourController