Search code examples
asp.net-mvcasp.net-mvc-5bundling-and-minificationjquery-globalize

MVC 5, globalize, validate german date: How to bundle the js-scripts?


In the answer to this question (MVC 5 - can not get globalisation running) I solve the problem with a bunch of "<sript src="..." declarations and some js.

What I not managed: I want to bundle the scripts. If I try it like this (excerpt from bundleConfig.cs):

 bundles.Add(new ScriptBundle("~/bundles/jqueryvalDe").Include(
                    "~/Scripts/jquery.validate.js",
                    "~/Scripts/jquery.validate.unobtrusive.js",
                    "~/Scripts/cldr.js",
                        "~/Scripts/cldr/event.js",
                        "~/Scripts/cldr/supplemental.js",
                        "~/Scripts/cldr/unresolved.js",
                        "~/Scripts/globalize.js",
                        "~/Scripts/globalize/currency.js",
                        "~/Scripts/globalize/number.js",
                        "~/Scripts/globalize/date.js",
                        "~/Scripts/globalize/plural.js",
                        "~/Scripts/globalize/relative-time.js",
                        "~/Scripts/globalize/unit.js",
                        "~/Scripts/jquery.validate.globalize.js"
                    ));         

But I get an error from JavaScript: "Globalize" is undefined

It seems, the order of scrpts is changed...

At the moment I use a Workaround: I wrote an custom HTM-Helper.

 public static class GermanDateValidationExtension
{
    public static MvcHtmlString ScriptsForGermanDateValidation(this HtmlHelper helper)
    {
        return new MvcHtmlString("<script src=\"~/ Scripts / jquery.validate.js\"></script>\n" +
                                 "<script src = \"~/Scripts/jquery.validate.unobtrusive.js\"></script>\n" +
                                 "<script src = \"~/Scripts/cldr.js\"></script>\n" +
                                 "<script src = \"~/Scripts/cldr/event.js\"></ script>\n" +
                                 "<script src = \"~/Scripts/cldr/supplemental.js\"></script>\n" +
                                 "<script src = \"~/Scripts/cldr/unresolved.js\"></script>\n" +
                                 "<script src = \"~/Scripts/globalize.js\"></script>\n" +
                                 "<script src = \"~/Scripts/globalize/currency.js\" ></script>\n" +
                                 "<script src = \"~/Scripts/globalize/number.js\"></script>\n" +
                                 "<script src = \"~/Scripts/globalize/date.js\"></script>\n" +
                                 "<script src = \"~/Scripts/globalize/plural.js\" ></script>\n" +
                                 "<script src = \"~/Scripts/globalize/relative-time.js\"></script>\n" +
                                 "<script src = \"~/Scripts/globalize/unit.js\"></script>\n" +
                                 "<script src = \"~/Scripts/jquery.validate.globalize.js\"></script>\n" +
                                 "<script>\n" +
                                 "$.when(\n" +
                                 "$.get(\"/Scripts/cldr/main/de/ca-gregorian.json\"),\n" +
                                 "$.get(\"/Scripts/cldr/main/de/numbers.json\"),\n" +
                                 "$.get(\"/Scripts/cldr/supplemental/likelySubtags.json\"),\n" +
                                 "$.get(\"/Scripts/cldr/supplemental/timeData.json\"),\n" +
                                 "$.get(\"/Scripts/cldr/supplemental/weekData.json\")\n" +
                                 ").then(function() {\n" +
                                 "return [].slice.apply(arguments, [0]).map(function(result) {\n" +
                                 "return result[0];\n" +
                                 "});\n" +
                                 "}).then(Globalize.load)\n" +
                                 ".then(function() {\n" +
                                 "Globalize.locale(\"de-DE\");\n" +
                                 "});\n" +
                                 "</ script > ");
    }

}

And use it in the view:

...
@section Scripts {      
@Html.ScriptsForGermanDateValidation()
}  
...

My question is: How to bundle the scripts correctly?


Solution

  • The problem seems originated from bundling order which rendered jquery.validate.globalize.js before globalize.js, which uses "dependency tree" established in favor of well-known libraries & their custom extensions will rendered before others. Hence, in order to set load order as you want, create a class which implements IBundleOrder interface & its corresponding extension method:

    // from Sebastián Rojas (/a/26602075)
    class UnorderedBundleOrderer : IBundleOrderer
    {
        public IEnumerable<BundleFile> OrderFiles(BundleContext context, IEnumerable<BundleFile> files)
        {
            return files;
        }
    }
    
    static class BundleExtensions
    {
        public static Bundle UnorderedBundling(this Bundle bundle)
        {
            bundle.Orderer = new UnorderedBundleOrderer();
            return bundle;
        }
    }
    

    Then you can use custom bundling order above in BundleConfig.cs file:

    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new ScriptBundle("~/bundles/jqueryvalDe")
               .UnorderedBundling()
               .Include(
                "~/Scripts/jquery.validate.js",
                "~/Scripts/jquery.validate.unobtrusive.js",
                ...
                ...
                "~/Scripts/globalize.js",
                ...
                ...
                "~/Scripts/jquery.validate.globalize.js"
        ));
    }
    

    Related issue:

    ASP.NET MVC - Bundle Config order

    Ordering of Files within a bundle - What are the known libraries?