Run javascript jquery in razor page context - javascript

I have a asp.net razor partial view which is used multiple times on one page.
In that partial view I have javascript in the $(document).ready() which I want to do some jQuery stuff on the content of the partial view.
<div class="someclass">
</div>
<script>
$(document).ready(function() {
$('.someclass').dosomething();
));
</script>
So the problem is that $('.someclass') returns to much elements when this partial view is use multiple times on one page.
How can I achieve that $('.someclass') returns only the intended element?
The only solution I see is to generate a unique id for the element and use that in the jQuery selector. But I don't like generating id's for that.
Any other ideas for a solution?

As a general rule you should not include scripts in partial views and it will create unexpected behaviors if the partial views are used/loaded more than once. Also, the inline scripts avoids them get cached by the browser. Though sometimes we feel lazy it always best practice to separate the scripts out of the views.

A quick fix would be to use that class only for init and remove it after the initialization like this:
<div class="someclass initSomething">
</div>
<script>
$(document).ready(function() {
$('.initSomething').dosomething().removeClass('initSomething');
));
</script>

Related

ASP.NET Core - HTML code block reuse

I'm working on a ASP.NET Core project using Bootstrap 4 and I have some Bootstrap Modals that I want to show in multiple views.
These Modals have some Javascript functions for internal elements, like Buttons and Inputs.
What is the correct approach to load these Modals (with their Javascript) in multiple views?
I figured I'd use PartialViews, but I don't know where to put the Javascript code (I know that putting it in PartialViews is a bad practice).
Create a seperate JS file and reference it on the bottom of every page that uses this partial view, so the script does not block the page-rendering.
Alternatively you could create a layout file which contains both the modals HTML and JS, and let your views inherit from this. Although I would advise against this approach due to the composition over inheritance principle.
Tag helpers might be better used for this, here's an example of a bootstrap modal tag helper ModalTagHelper
Then if you put this in your _ViewImports file:
#using AssemblyNameWithTagHelpers
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#addTagHelper "*, AssemblyNameWithTagHelpers"
You can use a tag helper like this:
<modal id="simpleModalFromAnchor" title="Modal Title">
<modal-body>
<h4>Something happened</h4>
<p>Something happened</p>
</modal-body>
</modal>
With the javascript, put it in a separate js file and reference it from each page you use the modal in, better yet, put it in a bundle with other well used components and include it in the bottom of your _Layout file

Render Scripts-Section after scripts were loaded in ASP.NET Core PartialView

In an ASP.NET Core app, I've a dashboard with widgets. Every widget has its own PartialViews, so the full page is generated in the following way:
-Layout.cshtml
--Dashboard.cshtml
--- Widget1.cshtml
--- Widget2.cshtml
Following best practices according to fast page load times, JavaScript is loaded before the closing </body> tag in Layout.cshtml. After that, there is a section for custom JS, which I commonly use to initiate objects on page load. So this section looks like this:
<script asp-append-version="true" type="text/javascript" src="~/clientscript/page.min.js"></script>
#RenderSection("Js", required: false)
In my Views, which are using the Layout.cshtml as layout (in this example, its Dashboard.cshtml), I can define a section like
#section Js {
// Js Code here
}
which is rendered after the script tag containing all script files. So I can be sure, that all dependencies like jQuery or custom classes are avaliable here.
But I also need to do this in widgets like Widget1.cshtml for example. The problem is: I load the PartialView Widget1.cshtml in Dashboard.cshtml. In the documentation is written, that this is not possible:
If you declare a Razor section in a partial view, it will not be visible to its parent(s); it will be limited to the partial view.
But that's exactly what I need. Is there a way to work around this limitation? Shortly, the goal is to inject JavaScript from a PartialView to the LayoutView, with an regular View between them.
The only way I know is the usage of setInterval() with a low interval like 50ms, and check there if jQuery or some of my custom class is defined in a loop until they are. Its a JS solution yes. But it makes it possible to include the script-block directly in the PartialView without making usage of sections. It fits well when you depend on a single variable like jQuery.
But I need to wait for custom classes to get loaded. They're included after jQuery. So writing a generic function like waitForTypeLoaded(type, callback) is not possible. It would cause me to write always the raw setInterval() code, which seems not a smart solution for me.
Something I did to get my scripts to run after Jquery was done loading was in my Partial Views and View Components I used the "DOMContentLoaded" event to load all my jQuery js script after the page was done loading. That way I could defer the Load of jQuery and Still Have jQuery code on my pages.
<script>
window.addEventListener('DOMContentLoaded',
function() {
$('body')....
});
</script>
Your problem can be solved as mentioned in my answer to this post:
How to render scripts, generated in TagHelper process method, to the bottom of the page rather than next to the tag element?
To sum up, you can create a pair of tag helpers, one that can be located in a partial view and just stores its content in a temporary dictionary, and the other that renders the content at the appropriate position (e.g. in the layout page). I use it extensively to render small dynamically created scripts as the final scripts of the body.
Hope it helps.
Honestly, I would make one step back and look at architecture once again if you have such dilemmas.
Why not add to required scripts which will be used on a couple of views/partial views to the main layout? In ASP.NET MVC you can use bundling mechanism (or you can write our own) - minify and bundle them with other required. It won't be heavy...
Your approach looks like unnecessary complicated.

Best practices to load HTML + Javascript dynamically

I have a page that loads (using a XHR request) a modal box with a form inside.
The form is composed by HTML tags + some Javascript to do validation and to submit it (using another XHR request).
I did that, and it already works, but the resulting DOM is ugly, because the script tag is inside the modal, like in this simplified example:
<html>
<head>...</head>
<body>
<div id="modal">
<form>...</form> <!-- This is my dynamically loaded HTML -->
<script>...</script> <!-- This is the dynamically loaded JS -->
</div>
<script>...</script> <!-- My main scripts -->
</body>
</html>
I have two questions about this:
1) The best practice is to put all JS code right before body closes, but when I do my dynamic loading, I end up with JS inside the modal div. Is there an efficient way to load only HTML to the div and inject the JS at the end of body? Are there any tools for that? Or should I not worry about it?
2) I'm using jQuery, so I try to use $(document).ready() for all JS code, but if I use this for modal JS, it won't run, probably because the event is not triggered a second time. Is there any event I can use to make my dynamically loaded JS to run after laoding is complete? Or should I just put it in the end?
Answer to both questions:
I don't see a reason why you shouldn't insert the JS scripts in the DOM inside the modal. I think it's even better that way compared to a global place where you put all the injected scripts. This way you will still know which modal loads which script.
And it solves your second problem as well. When you first insert your DOM nodes and then the <script> element that will work on them, you don't need to wait for a ready event.
Only other way I can think of is having the modal scripts available globally, loading the modal and then doing something like ModalScript.initialize("#modal").
You could use a framework like Browserify to bundle and dynamically load ("lazy load") resources as needed.
This is a good example/tutorial.

How to render a html partial in another html page?

I need to render a simple HTML page as partial within this div.It is a simple HTML5 application, not of MVC architecture hence Html.RenderPartial is not working.Any help??
<div id= "this_div_will_contain_partial">
</div>
Use jquery's load:
<script>
$(function(){
$('#this_div_will_contain_partial').load('http://www.urpartialurl.com');
});
</script>
I have noticed that you haven't included javascript tag but this is the only option to achieve this. Also the page you are trying to access needs to be on the same domain.

How do I share jQuery script between pages?

what is the best way to share jQuery code between pages? this is the situation:
-------SITUATION---------
I have several different pages that goes this way (pseudo code)
<% render "content/link" , collection => required_links %>
In the "content/link" partial
<div class="element_to_be_changed"/>
Currently in EVERY PAGE that renders the partial, i call
jQuery.('.element_to_be_changed')... effect that i want...
This strikes me as unscalable, but i am not sure what is the best way to handle it. anyone has any ideas?
If it is exactly the same on each page put it in an external script and include the script in the pages that use it.

Categories