সম্পাদক / প্রদর্শন টেম্পলেটগুলিতে বিভাগ ব্যবহার করে


104

আমি আমার সমস্ত জাভাস্ক্রিপ্ট কোড এক বিভাগে রাখতে চাই; সমাপ্তির ঠিক আগেbodyআমার মাস্টার লেআউট পৃষ্ঠাতে ট্যাগের এমভিসি শৈলী সম্পর্কে এটি সম্পর্কে সবচেয়ে ভাল অবাক করে।

উদাহরণস্বরূপ, আমি যদি DisplayTemplate\DateTime.cshtmlজাভাস্ক্রিপ্টটি সরাসরি সেই টেমপ্লেটে এম্বেড করার চেয়ে jQuery UI এর ডেটটাইম পিকার ব্যবহার করি তবে এমন একটি ফাইল তৈরি করি তবে এটি মাঝ পৃষ্ঠাটি রেন্ডার করবে।

আমার স্বাভাবিক দর্শনগুলিতে আমি কেবলমাত্র @section JavaScript { //js here }এবং তারপরে @RenderSection("JavaScript", false)আমার মাস্টার বিন্যাসে ব্যবহার করতে পারি তবে এটি প্রদর্শন / সম্পাদক টেম্পলেটগুলিতে কাজ করে বলে মনে হচ্ছে না - কোনও ধারণা?


4
যে কারও পরে এটি আসার জন্য - এটি হ্যান্ডেল করার জন্য একটি নুগেট প্যাকেজ রয়েছে: nuget.org/packages/ Forloop.Html সহায়তা
রাশ ক্যাম

উত্তর:


189

আপনি দুজন সহায়িকারীর সমন্বয়ে এগিয়ে যেতে পারেন:

public static class HtmlExtensions
{
    public static MvcHtmlString Script(this HtmlHelper htmlHelper, Func<object, HelperResult> template)
    {
        htmlHelper.ViewContext.HttpContext.Items["_script_" + Guid.NewGuid()] = template;
        return MvcHtmlString.Empty;
    }

    public static IHtmlString RenderScripts(this HtmlHelper htmlHelper)
    {
        foreach (object key in htmlHelper.ViewContext.HttpContext.Items.Keys)
        {
            if (key.ToString().StartsWith("_script_"))
            {
                var template = htmlHelper.ViewContext.HttpContext.Items[key] as Func<object, HelperResult>;
                if (template != null)
                {
                    htmlHelper.ViewContext.Writer.Write(template(null));
                }
            }
        }
        return MvcHtmlString.Empty;
    }
}

এবং তারপরে আপনার _Layout.cshtml:

<body>
...
@Html.RenderScripts()
</body>

এবং কোথাও কিছু টেমপ্লেট:

@Html.Script(
    @<script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
)

3
যেহেতু একটি অভিধান আন-অর্ডারযুক্ত হয় আমি প্রথমে কীভাবে করব? যাতে এটা আউটপুট র্যান্ডম (সম্ভবত কারণ GUID এর) এসে গেছে ..
eth0 এর

সম্ভবত আপনি একটি স্থিতিশীল পূর্ণসংখ্যার ক্ষেত্র সেট আপ করতে পারেন এবং অর্ডার পাওয়ার জন্য জিইউডির জায়গায় ইন্টারলকড.ইনক্রিমেন্ট () ব্যবহার করতে পারেন, তবে তারপরেও আমি মনে করি যে কোনও অভিধান কখনও আদেশ দেওয়ার নিশ্চয়তা দেয় না। দ্বিতীয় ভাবাতে, সম্ভবত কোনও স্থির ক্ষেত্রটি অদ্ভুত কারণ এটি পৃষ্ঠা প্রদর্শনগুলি জুড়ে রাখতে পারে। পরিবর্তে আইটেম অভিধানে একটি পূর্ণসংখ্যার যোগ করতে পারে তবে আপনাকে এটির চারপাশে একটি লক রাখতে হবে।
অ্যাডামসনকে

আমি এই সমাধানটি সম্প্রতি ব্যবহার করতে শুরু করেছি, তবে আমি একক @ এইচটিএমএল.স্প্রিপ্ট () লাইনে দুটি স্ক্রিপ্ট স্টাফ করতে পারছি না, কারণ হেল্পার রেজাল্ট কীভাবে কাজ করে তা আমি নিশ্চিত নই। 1 টি এইচটিএমএল.স্প্রিপ্ট কলে 2 স্ক্রিপ্ট ব্লক করা কি সম্ভব নয়?
ল্যাংডন

2
@ টিমমিয়ার্স, আপনার অর্থ কী? আমার জন্য এটি সবসময়ই অপ্রচলিত। আমি এই সাহায্যকারীদের মোটেই ব্যবহার করব না। আমার আংশিক দৃষ্টিতে কোনও স্ক্রিপ্ট অন্তর্ভুক্ত করার প্রয়োজন ছিল না। আমি কেবল স্ট্যান্ডার্ড রেজারের সাথে লেগে থাকি sections। এমভিসি 4 এ বন্ডলিংয়ে সত্যই ব্যবহৃত হতে পারে পাশাপাশি এটি স্ক্রিপ্টগুলির আকার হ্রাস করতে সহায়তা করে।
দারিন দিমিত্রভ

4
আপনি যদি আপনার স্ক্রিপ্টস বা স্টাইলগুলি headট্যাগের পরিবর্তে ট্যাগের শেষে রাখতে চান তবে এই পন্থাটি কার্যকর হয় না body, কারণ @Html.RenderScripts()আপনার আংশিক দেখার আগে এবং তাই এর আগে কার্যকর করা হবে @Html.Script()
মাকসিম ভি।

41

আদেশ নিশ্চিত করার জন্য দারিনের উত্তরের পরিবর্তিত সংস্করণ। সিএসএসের সাথেও কাজ করে:

public static IHtmlString Resource(this HtmlHelper HtmlHelper, Func<object, HelperResult> Template, string Type)
{
    if (HtmlHelper.ViewContext.HttpContext.Items[Type] != null) ((List<Func<object, HelperResult>>)HtmlHelper.ViewContext.HttpContext.Items[Type]).Add(Template);
    else HtmlHelper.ViewContext.HttpContext.Items[Type] = new List<Func<object, HelperResult>>() { Template };

    return new HtmlString(String.Empty);
}

public static IHtmlString RenderResources(this HtmlHelper HtmlHelper, string Type)
{
    if (HtmlHelper.ViewContext.HttpContext.Items[Type] != null)
    {
        List<Func<object, HelperResult>> Resources = (List<Func<object, HelperResult>>)HtmlHelper.ViewContext.HttpContext.Items[Type];

        foreach (var Resource in Resources)
        {
            if (Resource != null) HtmlHelper.ViewContext.Writer.Write(Resource(null));
        }
    }

    return new HtmlString(String.Empty);
}

আপনি এর মতো জেএস এবং সিএসএস সংস্থানগুলি যুক্ত করতে পারেন:

@Html.Resource(@<script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>, "js")
@Html.Resource(@<link rel="stylesheet" href="@Url.Content("~/CSS/style.css")" />, "css")

এবং জেএস এবং সিএসএস সংস্থানগুলি এর মতো রেন্ডার করুন:

@Html.RenderResources("js")
@Html.RenderResources("css")

স্ক্রিপ্ট / লিঙ্ক দিয়ে এটি শুরু হয় কিনা তা দেখতে আপনি স্ট্রিং চেক করতে পারেন যাতে প্রতিটি সংস্থান কী তা আপনাকে স্পষ্টভাবে সংজ্ঞায়িত করতে হবে না।


ধন্যবাদ eth0। আমি এই বিষয়ে আপস করেছি, তবে আমাকে এটি পরীক্ষা করে দেখতে হবে।
one.beat.consumer

আমি এটি প্রায় 2 বছর আগে জানি, তবে CSS বা জেএস ফাইলটি ইতিমধ্যে উপস্থিত রয়েছে এবং এটি রেন্ডার করছে না তা পরীক্ষা করার কোনও উপায় আছে কি? ধন্যবাদ
কোডিংস্লেয়ার

1
ঠিক আছে. এটি কতটা কার্যকরী তা নিশ্চিত নয়, তবে বর্তমানে আমি এটি করছি: var httpTemplates = HtmlHelper.ViewContext.HttpContext.Items [प्रकार] তালিকা হিসাবে <ফানক <অবজেক্ট, হেল্পার রেজাল্ট >>; var prevItem = q থেকে http টেম্পলেটগুলি যেখানে q (নাল) o টুস্ট্রিং () == টেমপ্লেট (নাল) o যদি (! prevItem.Any ()) {// টেম্পলেট যুক্ত করুন}
কোডিংস্লেয়ার

@ আইএমআবি ধন্যবাদ, আমার যা দরকার ছিল তা দেখতে আইটেমের সাথে 1 টি লুপের মতো বান্ডিলের মতো লাগে oস্ট্রিং যাতে আমি মনে করি এটি যথেষ্ট দ্রুত হওয়া উচিত
কুনুকন

35

আমি একই সমস্যার মুখোমুখি হয়েছি, তবে এখানে প্রস্তাবিত সমাধানগুলি কেবলমাত্র সংস্থানটিতে রেফারেন্স যুক্ত করার জন্য ভাল কাজ করে এবং ইনলাইন জেএস কোডের জন্য খুব উপযুক্ত নয়। আমি একটি খুব সহায়ক নিবন্ধ পেয়েছি এবং আমার সমস্ত ইনলাইন জেএস (এবং স্ক্রিপ্ট ট্যাগগুলি) এতে মোড়ানো করেছি

@using (Html.BeginScripts())
{
    <script src="@Url.Content("~/Scripts/jquery-ui-1.8.18.min.js")" type="text/javascript"></script>
    <script>
    // my inline scripts here
    <\script>
}

এবং @Html.PageScripts()'বডি' ট্যাগ বন্ধ করার ঠিক আগে লেআউট ভিউতে রাখা হয়েছে । আমার জন্য একটি কবজ ভালো কাজ করে।


সাহায্যকারীরা নিজেরাই:

public static class HtmlHelpers
{
    private class ScriptBlock : IDisposable
    {
        private const string scriptsKey = "scripts";
        public static List<string> pageScripts
        {
            get
            {
                if (HttpContext.Current.Items[scriptsKey] == null)
                    HttpContext.Current.Items[scriptsKey] = new List<string>();
                return (List<string>)HttpContext.Current.Items[scriptsKey];
            }
        }

        WebViewPage webPageBase;

        public ScriptBlock(WebViewPage webPageBase)
        {
            this.webPageBase = webPageBase;
            this.webPageBase.OutputStack.Push(new StringWriter());
        }

        public void Dispose()
        {
            pageScripts.Add(((StringWriter)this.webPageBase.OutputStack.Pop()).ToString());
        }
    }

    public static IDisposable BeginScripts(this HtmlHelper helper)
    {
        return new ScriptBlock((WebViewPage)helper.ViewDataContainer);
    }

    public static MvcHtmlString PageScripts(this HtmlHelper helper)
    {
        return MvcHtmlString.Create(string.Join(Environment.NewLine, ScriptBlock.pageScripts.Select(s => s.ToString())));
    }
}

3
এটি সেরা উত্তর; এটি আপনাকে বেশ কিছুতে ইনজেকশন দেয় এবং শেষ পর্যন্ত বিলম্ব করতে দেয়
ড্রাজাস

1
আপনার নিবন্ধটি কোডটি কমে যাওয়ার ক্ষেত্রে কপি-পেস্ট করা উচিত! এটি একটি দুর্দান্ত উত্তর!
শামান

আমরা কীভাবে এটি এসপ নেট কোর করতে পারি
রমান্মিটাল

13

@ জন- ডাব্লু-হার্ডিংয়ের পোস্ট করা সমাধানটি আমি পছন্দ করেছি , তাই নীচের সম্ভবত অতিরিক্ত জটিলতার সমাধান করার জন্য আমি @ ডারিন-ডিমিট্রভের উত্তরের সাথে সংযুক্ত করেছি যা আপনাকে কোনও ব্লকের মধ্যে কোনও এইচটিএমএল (স্ক্রিপ্টগুলি) সরবরাহ করতে বিলম্ব করতে দেয়।

, USAGE

বারবার আংশিক দৃষ্টিতে কেবল একবারে ব্লকটি অন্তর্ভুক্ত করুন:

@using (Html.Delayed(isOnlyOne: "MYPARTIAL_scripts")) {
    <script>
        someInlineScript();
    </script>
}

একটি (পুনরাবৃত্তি?) আংশিক দৃশ্যে, প্রতিবার আংশিক ব্যবহৃত হওয়ার জন্য ব্লকটি অন্তর্ভুক্ত করুন:

@using (Html.Delayed()) {
    <b>show me multiple times, @Model.Whatever</b>
}

একটি (পুনরাবৃত্তি?) আংশিক দৃশ্যে, ব্লকটি একবার অন্তর্ভুক্ত করুন এবং পরে এটি বিশেষভাবে নাম দ্বারা রেন্ডার করুন one-time:

@using (Html.Delayed("one-time", isOnlyOne: "one-time")) {
    <b>show me once by name</b>
    <span>@Model.First().Value</span>
}

রেন্ডার করতে:

@Html.RenderDelayed(); // the "default" unidentified blocks
@Html.RenderDelayed("one-time", false); // render the specified block by name, and allow us to render it again in a second call
@Html.RenderDelayed("one-time"); // render the specified block by name
@Html.RenderDelayed("one-time"); // since it was "popped" in the last call, won't render anything

কোড

public static class HtmlRenderExtensions {

    /// <summary>
    /// Delegate script/resource/etc injection until the end of the page
    /// <para>@via https://stackoverflow.com/a/14127332/1037948 and http://jadnb.wordpress.com/2011/02/16/rendering-scripts-from-partial-views-at-the-end-in-mvc/ </para>
    /// </summary>
    private class DelayedInjectionBlock : IDisposable {
        /// <summary>
        /// Unique internal storage key
        /// </summary>
        private const string CACHE_KEY = "DCCF8C78-2E36-4567-B0CF-FE052ACCE309"; // "DelayedInjectionBlocks";

        /// <summary>
        /// Internal storage identifier for remembering unique/isOnlyOne items
        /// </summary>
        private const string UNIQUE_IDENTIFIER_KEY = CACHE_KEY;

        /// <summary>
        /// What to use as internal storage identifier if no identifier provided (since we can't use null as key)
        /// </summary>
        private const string EMPTY_IDENTIFIER = "";

        /// <summary>
        /// Retrieve a context-aware list of cached output delegates from the given helper; uses the helper's context rather than singleton HttpContext.Current.Items
        /// </summary>
        /// <param name="helper">the helper from which we use the context</param>
        /// <param name="identifier">optional unique sub-identifier for a given injection block</param>
        /// <returns>list of delayed-execution callbacks to render internal content</returns>
        public static Queue<string> GetQueue(HtmlHelper helper, string identifier = null) {
            return _GetOrSet(helper, new Queue<string>(), identifier ?? EMPTY_IDENTIFIER);
        }

        /// <summary>
        /// Retrieve a context-aware list of cached output delegates from the given helper; uses the helper's context rather than singleton HttpContext.Current.Items
        /// </summary>
        /// <param name="helper">the helper from which we use the context</param>
        /// <param name="defaultValue">the default value to return if the cached item isn't found or isn't the expected type; can also be used to set with an arbitrary value</param>
        /// <param name="identifier">optional unique sub-identifier for a given injection block</param>
        /// <returns>list of delayed-execution callbacks to render internal content</returns>
        private static T _GetOrSet<T>(HtmlHelper helper, T defaultValue, string identifier = EMPTY_IDENTIFIER) where T : class {
            var storage = GetStorage(helper);

            // return the stored item, or set it if it does not exist
            return (T) (storage.ContainsKey(identifier) ? storage[identifier] : (storage[identifier] = defaultValue));
        }

        /// <summary>
        /// Get the storage, but if it doesn't exist or isn't the expected type, then create a new "bucket"
        /// </summary>
        /// <param name="helper"></param>
        /// <returns></returns>
        public static Dictionary<string, object> GetStorage(HtmlHelper helper) {
            var storage = helper.ViewContext.HttpContext.Items[CACHE_KEY] as Dictionary<string, object>;
            if (storage == null) helper.ViewContext.HttpContext.Items[CACHE_KEY] = (storage = new Dictionary<string, object>());
            return storage;
        }


        private readonly HtmlHelper helper;
        private readonly string identifier;
        private readonly string isOnlyOne;

        /// <summary>
        /// Create a new using block from the given helper (used for trapping appropriate context)
        /// </summary>
        /// <param name="helper">the helper from which we use the context</param>
        /// <param name="identifier">optional unique identifier to specify one or many injection blocks</param>
        /// <param name="isOnlyOne">extra identifier used to ensure that this item is only added once; if provided, content should only appear once in the page (i.e. only the first block called for this identifier is used)</param>
        public DelayedInjectionBlock(HtmlHelper helper, string identifier = null, string isOnlyOne = null) {
            this.helper = helper;

            // start a new writing context
            ((WebViewPage)this.helper.ViewDataContainer).OutputStack.Push(new StringWriter());

            this.identifier = identifier ?? EMPTY_IDENTIFIER;
            this.isOnlyOne = isOnlyOne;
        }

        /// <summary>
        /// Append the internal content to the context's cached list of output delegates
        /// </summary>
        public void Dispose() {
            // render the internal content of the injection block helper
            // make sure to pop from the stack rather than just render from the Writer
            // so it will remove it from regular rendering
            var content = ((WebViewPage)this.helper.ViewDataContainer).OutputStack;
            var renderedContent = content.Count == 0 ? string.Empty : content.Pop().ToString();

            // if we only want one, remove the existing
            var queue = GetQueue(this.helper, this.identifier);

            // get the index of the existing item from the alternate storage
            var existingIdentifiers = _GetOrSet(this.helper, new Dictionary<string, int>(), UNIQUE_IDENTIFIER_KEY);

            // only save the result if this isn't meant to be unique, or
            // if it's supposed to be unique and we haven't encountered this identifier before
            if( null == this.isOnlyOne || !existingIdentifiers.ContainsKey(this.isOnlyOne) ) {
                // remove the new writing context we created for this block
                // and save the output to the queue for later
                queue.Enqueue(renderedContent);

                // only remember this if supposed to
                if(null != this.isOnlyOne) existingIdentifiers[this.isOnlyOne] = queue.Count; // save the index, so we could remove it directly (if we want to use the last instance of the block rather than the first)
            }
        }
    }


    /// <summary>
    /// <para>Start a delayed-execution block of output -- this will be rendered/printed on the next call to <see cref="RenderDelayed"/>.</para>
    /// <para>
    /// <example>
    /// Print once in "default block" (usually rendered at end via <code>@Html.RenderDelayed()</code>).  Code:
    /// <code>
    /// @using (Html.Delayed()) {
    ///     <b>show at later</b>
    ///     <span>@Model.Name</span>
    ///     etc
    /// }
    /// </code>
    /// </example>
    /// </para>
    /// <para>
    /// <example>
    /// Print once (i.e. if within a looped partial), using identified block via <code>@Html.RenderDelayed("one-time")</code>.  Code:
    /// <code>
    /// @using (Html.Delayed("one-time", isOnlyOne: "one-time")) {
    ///     <b>show me once</b>
    ///     <span>@Model.First().Value</span>
    /// }
    /// </code>
    /// </example>
    /// </para>
    /// </summary>
    /// <param name="helper">the helper from which we use the context</param>
    /// <param name="injectionBlockId">optional unique identifier to specify one or many injection blocks</param>
    /// <param name="isOnlyOne">extra identifier used to ensure that this item is only added once; if provided, content should only appear once in the page (i.e. only the first block called for this identifier is used)</param>
    /// <returns>using block to wrap delayed output</returns>
    public static IDisposable Delayed(this HtmlHelper helper, string injectionBlockId = null, string isOnlyOne = null) {
        return new DelayedInjectionBlock(helper, injectionBlockId, isOnlyOne);
    }

    /// <summary>
    /// Render all queued output blocks injected via <see cref="Delayed"/>.
    /// <para>
    /// <example>
    /// Print all delayed blocks using default identifier (i.e. not provided)
    /// <code>
    /// @using (Html.Delayed()) {
    ///     <b>show me later</b>
    ///     <span>@Model.Name</span>
    ///     etc
    /// }
    /// </code>
    /// -- then later --
    /// <code>
    /// @using (Html.Delayed()) {
    ///     <b>more for later</b>
    ///     etc
    /// }
    /// </code>
    /// -- then later --
    /// <code>
    /// @Html.RenderDelayed() // will print both delayed blocks
    /// </code>
    /// </example>
    /// </para>
    /// <para>
    /// <example>
    /// Allow multiple repetitions of rendered blocks, using same <code>@Html.Delayed()...</code> as before.  Code:
    /// <code>
    /// @Html.RenderDelayed(removeAfterRendering: false); /* will print */
    /// @Html.RenderDelayed() /* will print again because not removed before */
    /// </code>
    /// </example>
    /// </para>

    /// </summary>
    /// <param name="helper">the helper from which we use the context</param>
    /// <param name="injectionBlockId">optional unique identifier to specify one or many injection blocks</param>
    /// <param name="removeAfterRendering">only render this once</param>
    /// <returns>rendered output content</returns>
    public static MvcHtmlString RenderDelayed(this HtmlHelper helper, string injectionBlockId = null, bool removeAfterRendering = true) {
        var stack = DelayedInjectionBlock.GetQueue(helper, injectionBlockId);

        if( removeAfterRendering ) {
            var sb = new StringBuilder(
#if DEBUG
                string.Format("<!-- delayed-block: {0} -->", injectionBlockId)
#endif
                );
            // .count faster than .any
            while (stack.Count > 0) {
                sb.AppendLine(stack.Dequeue());
            }
            return MvcHtmlString.Create(sb.ToString());
        } 

        return MvcHtmlString.Create(
#if DEBUG
                string.Format("<!-- delayed-block: {0} -->", injectionBlockId) + 
#endif
            string.Join(Environment.NewLine, stack));
    }


}

রহস্যময়। আমি এই অন্য থ্রেডের উত্তরটি অনুলিপি করার কথা মনে নেই , তবে আমি সেখানে কিছুটা ভাল লেখার চেষ্টা করেছি ...
drzaus

12

ফরলুপ.এইচটিএমএল হেল্পার্স নুগেট প্যাকেজটি ইনস্টল করুন - এটি আংশিক দর্শন এবং সম্পাদক টেম্পলেটগুলিতে স্ক্রিপ্টগুলি পরিচালনার জন্য কিছু সহায়ক যুক্ত করে।

আপনার লেআউটের কোথাও, আপনাকে কল করতে হবে

@Html.RenderScripts()

এটি যেখানে পৃষ্ঠায় কোনও স্ক্রিপ্ট ফাইল এবং স্ক্রিপ্ট ব্লকগুলি আউটপুট করা হবে তাই আমি এটিকে আপনার মূল স্ক্রিপ্টগুলি বিন্যাসে এবং একটি স্ক্রিপ্ট বিভাগের পরে রাখার পরামর্শ দিচ্ছি (যদি আপনার একটি থাকে)।

আপনি যদি বান্ডিলিংয়ের সাথে ওয়েব অপ্টিমাইজেশন ফ্রেমওয়ার্ক ব্যবহার করেন তবে আপনি ওভারলোডটি ব্যবহার করতে পারেন

@Html.RenderScripts(Scripts.Render)

যাতে এই পদ্ধতিটি স্ক্রিপ্ট ফাইলগুলি লেখার জন্য ব্যবহৃত হয়।

এখন, আপনি যে কোনও সময় কোনও দৃশ্য, আংশিক দর্শন বা টেম্পলেটটিতে স্ক্রিপ্ট ফাইল বা ব্লক যুক্ত করতে চান, কেবল ব্যবহার করুন

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

সহায়করা নিশ্চিত করে যে একাধিকবার যোগ করা হলে কেবলমাত্র একটি স্ক্রিপ্ট ফাইলের রেফারেন্স রেন্ডার করা হয়েছে এবং এটিও নিশ্চিত করে যে স্ক্রিপ্ট ফাইলগুলি প্রত্যাশিত ক্রমে রেন্ডার করা হয়েছে অর্থাৎ

  1. বিন্যাস
  2. পার্টিয়ালস এবং টেম্পলেটগুলি (ক্রম অনুযায়ী তারা দৃশ্যে প্রদর্শিত হবে, উপরে থেকে নীচে)

5

এই পোস্টটি সত্যিই আমাকে সাহায্য করেছে তাই আমি ভেবেছিলাম যে আমি আমার প্রাথমিক ধারণাটির বাস্তবায়ন পোস্ট করব। আমি একটি সহায়ক ফাংশন চালু করেছি যা @ এইচটিএমএল. রিসোর্স ফাংশনে ব্যবহারের জন্য স্ক্রিপ্ট ট্যাগগুলি ফিরিয়ে দিতে পারে।

আমি একটি সাধারণ স্ট্যাটিক ক্লাসও যুক্ত করেছি যাতে আমি কোনও জেএস বা সিএসএস সংস্থান চিহ্নিত করতে টাইপড ভেরিয়েবলগুলি ব্যবহার করতে পারি।

public static class ResourceType
{
    public const string Css = "css";
    public const string Js = "js";
}

public static class HtmlExtensions
{
    public static IHtmlString Resource(this HtmlHelper htmlHelper, Func<object, dynamic> template, string Type)
    {
        if (htmlHelper.ViewContext.HttpContext.Items[Type] != null) ((List<Func<object, dynamic>>)htmlHelper.ViewContext.HttpContext.Items[Type]).Add(template);
        else htmlHelper.ViewContext.HttpContext.Items[Type] = new List<Func<object, dynamic>>() { template };

        return new HtmlString(String.Empty);
    }

    public static IHtmlString RenderResources(this HtmlHelper htmlHelper, string Type)
    {
        if (htmlHelper.ViewContext.HttpContext.Items[Type] != null)
        {
            List<Func<object, dynamic>> resources = (List<Func<object, dynamic>>)htmlHelper.ViewContext.HttpContext.Items[Type];

            foreach (var resource in resources)
            {
                if (resource != null) htmlHelper.ViewContext.Writer.Write(resource(null));
            }
        }

        return new HtmlString(String.Empty);
    }

    public static Func<object, dynamic> ScriptTag(this HtmlHelper htmlHelper, string url)
    {
        var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
        var script = new TagBuilder("script");
        script.Attributes["type"] = "text/javascript";
        script.Attributes["src"] = urlHelper.Content("~/" + url);
        return x => new HtmlString(script.ToString(TagRenderMode.Normal));
    }
}

এবং ব্যবহারে

@Html.Resource(Html.ScriptTag("Areas/Admin/js/plugins/wysiwyg/jquery.wysiwyg.js"), ResourceType.Js)

@ ড্যারিন দিমিত্রভকে ধন্যবাদ যারা এখানে আমার প্রশ্নের উত্তর সরবরাহ করেছিল ।


2

উত্তর দেওয়া একটি আংশিক থেকে একটা ক্ষুর বিভাগে পূরণ ব্যবহার RequireScriptHtmlHelper একই প্যাটার্ন অনুসরণ করে। এটির একই সুবিধাটি এটি একই জাভাস্ক্রিপ্ট URL এর সদৃশ রেফারেন্সগুলির জন্য পরীক্ষা করে এবং দমন করে এবং এর স্পষ্টতই রয়েছেpriority প্যারামিটারও রয়েছে যা ক্রম নিয়ন্ত্রণ করতে ব্যবহার করা যেতে পারে।

আমি এর জন্য পদ্ধতি যুক্ত করে এই সমাধানটি প্রসারিত করেছি:

// use this for scripts to be placed just before the </body> tag
public static string RequireFooterScript(this HtmlHelper html, string path, int priority = 1) { ... }
public static HtmlString EmitRequiredFooterScripts(this HtmlHelper html) { ... }

// use this for CSS links
public static string RequireCSS(this HtmlHelper html, string path, int priority = 1) { ... }
public static HtmlString EmitRequiredCSS(this HtmlHelper html) { ... }

আমি ডারিনের & এথ0 এর সমাধানগুলি পছন্দ করি যদিও তারা HelperResultটেম্পলেটটি ব্যবহার করে যা স্ক্রিপ্ট এবং সিএসএস ব্লকগুলির জন্য অনুমতি দেয়, কেবল জাভাস্ক্রিপ্ট এবং সিএসএস ফাইলগুলির লিঙ্ক নয়।


1

বান্ডেল এক্সটেনশন ব্যবহারের সাথে ব্যবহার করার জন্য @ ডারিন দিমিত্রভ এবং @ এথ0 ​​উত্তর:

@Html.Resources(a => new HelperResult(b => b.Write( System.Web.Optimization.Scripts.Render("~/Content/js/formBundle").ToString())), "jsTop")
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.