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.
Related
My front-end structure is like below:
<div id='item-list'>
# List of items to be replaced every time
</div>
<form>
<submit/>
</form>
The idea is that, every time when the submit button is clicked, my JS would send AJAX request, and the server would return an HTML partial for the item-list, and in my front-end, the item-list would be replaced with the ajax return.
However, since there're also some use of UJS in my item-list, the bindings no longer works after the replacement.
I believe it's the problem that the UJS code didn't execute when the replacement happens. I want to ask how to force the execution of UJS code?
Thanks a lot
You'll need to delegate your event bindings from an element which is always going to be present on your page (typically document):
$(document).on("submit", ".element", function(){
//stuff
});
The problem you have is that Javascript only works with elements in the actual DOM. It doesn't, nor can it work with, elements which are appended after the DOM has been loaded
This means you have to bind the javascript events to elements which will always be present in the DOM, and delegate from them
--
That's the best I can do with what you've sent so far - if you give more context, I'll be able to provide a richer answer
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.
I face some strange issues when integrating jQuery with Wicket.
We load each content item as Panel in Wicket using Ajax. So it is a Single Page Application.
In the header of the Panel we add some JS, for example:
<script type="text/javascript">
$(document).ready( function() {
$('#example').dataTable( {
"sScrollY": "200px",
"bPaginate": false
} );
} );
</script>
However this code seems to be executed only the first time the Panel is loaded. If you reload the Panel into the application using Ajax, the code is not executed anymore.
I guess JS $(document).ready is only initialized one time, the second time you load the same JS into the browser $(document).ready is no more called.
Is there a workaround with Wicket for that issue?
Thanks!
Sebastian
document ready gets called only once, if you want to call on every load write the code as a seperate method and call it on success of every ajax load
I was able to resolve my issues given on this answer: http://mail-archives.apache.org/mod_mbox/wicket-users/201209.mbox/%3CCAAJwaYUSfoFZHVP4EXSxuw_Co-J0W6qvV1MR8wGERjfNzj2CxA%40mail.gmail.com%3E
You could add Renderhead().It executes whatever is being written inside it even on page refresh
I am trying to execute a snippet of JS only once, after the page has completely loaded and JQM has taken care of all the ui modifications (i.e. listviews, buttons, etc.). I do want it to execute only on that page, and not on subsequent pages.
What I tried first, was pageshow
<script>
$('[data-role=page]').live("pageshow", function() {
alert("Ready!");
});
</script>
This has the problem that the function is now attached to the page div and gets executed every time any subsequent page gets shown. However, I only want this to be executed once, and only for the page that contains that JS snippet.
Is there a way to listen to the pageshow event, without actually attaching the function to it.
The only way I was able to do it was by binding and unbinding like this:
<script>
$('[data-role=page]').bind("pageshow.test", testfun);
function testfun() {
alert("Ready!");
$('[data-role=page]').unbind("pageshow.test", testfun);
}
</script>
But is there a more elegant way to do so?
jQuery has a one function to bind an event handler to be executed only once. Check the reference.
The pageinit event fires once per page just after the jQuery Mobile framework initializes its widgets; I think it may be what you're looking for.
pageinit
Triggered on the page being initialized, after initialization occurs.
We recommend binding to this event instead of DOM ready() because this
will work regardless of whether the page is loaded directly or if the
content is pulled into another page as part of the Ajax navigation
system.
Source: http://jquerymobile.com/demos/1.1.0-rc.1/docs/api/events.html
If you want to bind to a specific page and not the rest, then select only the page you want to alter... Here's an example:
<script>
$(document).delegate('#my-page-id', 'pageinit', function() {
alert("PageInit!");
});
</script>
I have a single file for each page and i am trying to implement the pageinit event handler on every page (I think what belongs strictly to one page, should be declared there) as shown below:
<body>
<div id="myPage" data-role="page">
<!-- Content here -->
<script type="text/javascript">
$("#myPage").live('pageinit', function() {
// do something here...
});
</script>
</div>
</body>
The event is bound properly to the page, so the code is executed but - now my problem - if i go to another page and return later on the pageinit event will be executed twice. I think that is because the .live method binds the pageinit event again to the page. But shouldn't the pageinit event only called once at page initialization? What I am missing here?
I solve the issue by passing the name of the event, in this case the "pageinit" instead of the handler.
<script defer="defer" type="text/javascript">
var supplier = null;
$("#pageID").die("pageinit"); //<--- this is the fix
$("#pageID").live("pageinit", function(event){
console.log("initialized - #(ViewBag.ID)");
supplier = new Tradie.Supplier();
supplier.Initialize("#(ViewBag.ID)");
});
Ref: http://www.rodcerrada.com/post/2012/04/26/jQuery-Mobile-Pageinit-Fires-More-Than-Once.aspx
I think its probably best to move your JavaScript code into another file as while your navigating around your site jQuery Mobile may cleanup (read: delete from DOM) that myPage page and therefore will have to load it in again and hense rerun that same block of code you defined and bind 2 listeners for the pageinit event.
Thats basically why they suggest using the live or on functions however it falls over if you include the binding code on the page ;)
However if you insist on having your code placed on a per page basis than use bind instead of live.
Ref: http://jquerymobile.com/demos/1.0/docs/pages/page-cache.html
jQuery Mobile therefore has a simple mechanism to keep the DOM tidy. Whenever it loads a page via Ajax, jQuery Mobile flags the page to be removed from the DOM when you navigate away from it later (technically, on the pagehide event).
I'm pretty sure they recommend binding pageinit to the document using on(). E.g.
$(document).on ('pageinit', '#myPage', function (event) {
instead of having the pageinit bound to the page, which is getting re-inited. In fact, I thought $(document).on() was the recommended way to bind events in jQuery, in general, now.
A quick workaround I have used is declaring a variable containing the handler function.
var handler = function() {
// your code
};
Then always use die() before binding the handler with live()
$( "#myPage" ).die( handler ).live( handler );
I'm sure this is not the intended usage by the authors, but it does the trick, you can leave your code within the page DIV.
$("#page1").live("pageinit", function () {
alert('pageinit');
$("#page1").die("pageinit"); //<--- prevent from firing twice on refresh
});