I've seen numerous sources stating that it's incorrect / bad practice to put scripts in Partial Views, but this raises a huge question...
How are you supposed to run scripts that interact with Partial Views? I've tried using #section scripts { } or something like that, but it doesn't work. At all. The section contains the scripts just fine, but they don't get rendered when the Partial is loaded into the full View.
In addition, I can't render the scripts my Partial View needs on my full View because the scripts pull values from the Model, which is only rendered on the Partial View, since it's the piece of the puzzle that actually works with data.
I hope that doesn't sound too complicated... How can I effectively, efficiently, and correctly render scripts for use with my Partial View's elements and Model?
#keyCrumbs I will not give you a direct answer, but something for you to analyze.
One of the most biggest problems in you call scripts for you partial view is replication of code.
Think you'll use ajax to get the partial view and you will continue doing this for a while. In every call you'll download the script code, and you put it in html. Every time you reset the script block in html, the functions are reset, the variables are reset. It's can be a big problem depending on your js code.
Other point is the size of the response, you can say, but js has a small size, and I'll say multiply this size for every call of a user and next multiply for ever user connected.
So finally, a solution for you, in this case is: create function in the page and call the function in partial view like this:
Your page: Page.cshtml
<script type="text/javascript">
function myPartialView_Load() {
$("birth").datepicker();
$("phone").mask("000-0000");
}
</script>
<!-- Some other code here -->
<div>
<!-- Or you can call from a ajax or other way... -->
#Html.Action("MyActionPartialView")
</div>
Your partial view: MyPartialView.cshtml
<script type="text/javascript">
$(function () { myPartialView_Load(); });
</script>
<form>
<input type="text" name="birth" id="birth" />
<input type="text" name="phone" id="phone" />
</form>
So as you see the problem lies not in putting js in partial view, but the way as you do it. All rules of good practice has a "why" behind, if you understand the "why" you can determine how far the rule is a help and not a burden. And decide break it or not.
Like a said, I'm not given you a ultimate answer but something you thing about. You can use other ways to contour the problem.
Related
I have 2 grails views that both refer to the same layout:
index.gsp & custom.gsp
Both pages have a <script> block in the <head>. I would like to be able to go to the custom.gsp directly OR work with the content in a tab in index.gsp.
I'm including the custom.gsp content using:
<g:include controller='controllername' action='custom'/>
It appears as if the custom.gsp's <script> block is overwritting the index.gsp's <script> block. If I remove the include everything else on the index page operates normally. If I add the include the code in the <script> block of index.gsp is not executed and upon inspection does not appear to be there.
What is really happening here and why? How can I structure things differently so this doesn't happeN?
UPDATE
I've tried moving the code in custom.gsp out of a <script> block and into a separate javascript file. However; when the include happens now it still pulls the code in as a <script> block and replaces the old one.
I've tried moving the block of each one into the body instead and I've tried adding id attributes to each thinking maybe sitemesh might see it as a unique block then. Still no luck.
UPDATE #2
I tried adding this to the body of index.gsp:
<div>this is a script
<script type="application/javascript">
var xyz='xyz';
</script>
</div>
And the text this is a script is visible but the script is gone!
UPDATE #3
update #2 is wrong, the text is visible but the script is actually there too. I thought it was gone because I was observing the same behavior as when it was gone. However; the real issue is that the entire head of index.gsp was replaced with the included page's head so index.gsp lost the libraries it needed to execute the script code.
As commented by #joshua the view returned by this call:
<g:include controller='controllername' action='custom'/>
must be a fragment instead of a whole gsp view with html, head .. tags.
Think of this when including views using g:include, if you have HomeController and NewsController (check figures below), and you want to include NewsController's view with HomeController's view,
You have to define an action on your NewsController that will only return the content fragment you see on the figure. To do this you can keep the news.gsp view but refactor it in such a way you put the content section in a new template(content fragment). I hope you get what I mean, but leave a comment if something is not clear on my example.
Please note I'm not interested in a Polymer-, Angular- or route-based solution here. I'm trying to learn "pure" Dart here, and while I'll likely switch to using one of those frameworks down the road, I need to have a good understanding of the fundamentals first.
In Dart, is it possible to download a whole bunch of HTML "snippets" (see below) all at once (at app startup), and then load them into the browser (either the entire window or just inside a particular <div> element, etc.) dynamically?
For instance, my HTML file might have a <div> element:
<body>
<!-- lots of HTML -->
<div id="container"></div>
<!-- more HTML -->
</body>
And I would like to download two "snippets" (DOM subtrees, HTML templates) of HTML, and dynamically load either one of them into the container div tag. Perhaps one of the snippets looks like this:
<h1>I'm Snippet #1!!!</h1>
<input type="button" name="redPillButton" value="Red Pill!" />
And another snippet my look like:
<h1>I'm Snippet #2!!!</h1>
<input type="button" name="bluePillButton" value="Blue Pill!" />
Can the two snippets be inside their own HTML file, or do I have to put them inside one big file and extract out the "snippet" that I want to load? Either way, how do I accomplish this in a Dart web app?
You can keep each parts in their own file and load them like that :
HttpRequest.getString("part.html").then((html) {
querySelector('#container').innerHtml = html;
});
i have 3 partial views
View 1:
//_yard.cshtml
#model Yard
<div>#Model.Name</div>
<div class="yard"></div>
#foreach(var house in Model.Houses)
{
<script type="text/javascript">
$(document).ready(function{
$(".yard").load("/community/Houses");
});
</script>
}
View 2
//_houses.cshtml
#model House
<div>#Model.Name<div>
<div class="house"></div>
#foreach(var level in Model.levels)
{
<script type="text/JavaScript">
$(document).ready(function{
$(".house").load("/Community/Levels");
});
</script>
}
View 3:
//_levels.cshtml
#model Level
<div>#Model.Name<div>
<div class="room"></div>
#foreach(var room in Model.Rooms)
{
<script type="text/JavaScript">
$(document).ready(function{
$(".room").load("/Community/Rooms");
});
</script>
}
The above sample, shows that i am loading a View 1 within another view using jQuery Load(), i then load View 2 withing View 1, and then and so forth, however, the first load() works fine, but the subsequint loads does not fire.
I think it is due to the $(document).ready(); function not being reset, however, i am not sure how to reset it on each load.
Problem Solved
With MVC the default template renders the jQuery script at the bottom of the page. I moved it to the top, and the ajax loads worked.
I know this makes no sense, but it fixed the problem. I will update the question after doing a little bit more investigation as to why this solves the problem.
Edit:
The answer below in general is helpful, but I think the real problem is syntax errors in your JavaScript. The .load() lines of code all have one too many ) at the end. Fix that, make sure you do not have more syntax errors by checking the JavaScript console in your browser, then also use the advice below :-)
Thinking about $(document).ready(); being "reset" is unhelpful, because it isn't and cannot be "reset".
It is an event that is fired the first time the DOM has been fully loaded and ready to be manipulated by JavaScript. The event happens once, and only once, when a web page is loaded for the first time. Any subsequent AJAX requests will not fire new $(document).ready(); events on the page. They will, however, fire other events - but not $(document).ready();.
Remove $(document).ready(); from View 2 and 3 and your code will work. (Tip: you should wrap your JavaScript in <script> tags, otherwise you may get some weird behaviour in some browsers).
The events that fire when AJAX requests have finished may help you out:
$.ajax(); has a success/error/complete handlers.
.load(); has a complete handler.
I have a ContentPlaceholder inside of a MasterPageView. All of my other pages come from the same master and I have one page that needs about 70% of the behavior in this master. There is a navigation panel in the master that is spitting out un-necessary html even if left blank by the page. Looks like this:
<div class="span3">
<div class="side_navigation">
<ul>
<asp:ContentPlaceHolder ID="SideNavigation" runat="server" />
</ul>
</div>
</div><%-- /master sub-navigation --%>
I simply want to hide ALL of this markup whenever my placeholder (SideNavigation) has 0 children. I don't want to use javascript. I'd rather do this work on the server and deliver it to the client with less responsibility and markup. I've already tried doing "this.SideNavigation.Controls.Count" but it always ends up being 0. If there was a way I could tie into a loaded event and then test this logic that would be great. I am ok with making a code-behind file for my master, but it would be nice to be able to accomplish my goal in the .master file only.
Let me know what you think.
I would probably recommend using a different master page for the page without the navigation. You can have nested master pages so you don't necessarily need to duplicate code to do this.
However if you do wish to keep it like this, I would personally use a bit of javascript (with jquery) as follows
$(function(){
if($('.span3 .side_navigation ul li').length() == 0){
$('.span3').hide();
}
});
obviously i'd give span3 an ID to make it not hide every span3 but you hopefully get the idea.
I'm trying to add some Model properties into my JavaScript within my content page:
$(document).ready(function () {
createPager(1, <%=Model.TotalPages %>);
createUnprocessedPager(1, <%=Model.TotalUnprocessedPages %>);
});
Does anyone know if this is by design? Are you not meant to combine Model properties with JavaScript? Or is this a bug?
This works as expected. However, I do not have any Intellisense within the <% ... %> tags when actually writing the code. If I write any code within <script> tags, then there's no Intellisense. If I go directly under the tag </script> and type <% Model.... %> then boom, I have Intellisense again.
UPDATE: 22/10/2010
Just read Scott Guthrie's latest blog post and it appears this functionality is coming out soon with the up coming release of ASP.Net MVC 3 (possibly for the beta as well):
Note: Visual Studio Code/Markup
Intellisense and Colorization within
Razor files aren’t enabled yet with
the Beta earlier this month. You’ll
see this show up in a few weeks though
– and it will support full code
intellisense for HTML, JavaScript, CSS
and C#/VB code within Razor files.
There is also no syntax highlighting I think. Not sure if that's a bug or a feature, but AFAIK, combining the code this way isn't a good practice. Generally inline javascript is not a good practice, but if you go with it, combine Model properties with it, and later decide to extract the scripts into a separate js file, your code will break. Therefore, it is quite common to populate hidden fields with your Model properties and read them in your js with jQuery, e.g.:
<input type="hidden" id="valTotalPages" value="<%=Model.TotalPages %>" />
<input type="hidden" id="valTotalUnprocessedPages" value="<%=Model.TotalUnprocessedPages %>" />
...
// in js
$(document).ready(function () {
createPager(1, $("#valTotalPages").val());
createUnprocessedPager(1, $("#valTotalUnprocessedPages").val());
});
So lack of syntax highlighting and intellisense might be a bug, but might as well be a way of discouraging certain code patterns.
You will loose you Intellisense in the views inside quotes "" like attributes.
<input type="text" value="<%= DateTime.Today.ToShortDateString() %>" />
or if it appears inside of Javascript blocks.
<script type="text/javascript">
<%= DateTime.Today.ToShortDateString() %>
</script>
It is my opinion that there should be Intellisense in these scenarios, so I would say it is a bug and hope future updates to Visual Studio will address and resolve this.