assuming I have a partial view that is just an editor box for inputting some data (asp.net application)
#Html.Editor("New", new { htmlAttributes = new { #class = "my_editor" } })
in my main view, I have a section that I'd like to update with the partial view I mentioned above using an ajax call.
<div id="editor_section"></div>
My question is, is it possible to continuously append to the same div using the same partial view. In other words, I call ajax once, and a new input box appears. Then I click on the ajax link again, and a second input box appears coming from the same partial view obviously. And I should be able to continue doing this as many times as I like each time appending a new input box under the others.
Yes it is possible, but it is not very efficient. You should only have to make the AJAX call once, then you can cache the html you get from the partial view in a JavaScript variable, so when you append it later, you don't have to make the round trip to the server to retrieve HTML you have already requested.
Something like:
var inputHtml = null;
var appendInput = function () {
if (!inputHtml) {
$.get('/input', function (data) {
inputHtml = data;
$('#someDiv').append(inputHtml);
});
} else {
$('#someDiv').append(inputHtml);
}
};
Related
I have tried to do something with Django and javascript. So for example, if I want to go to my "about" page from my "home" page, I only want to load the contents of the page. There are many similar elements in both pages (such as a header image and navbar) that does not need to be reloaded. I have already 80% achieved what I want, my code is below:
javascript
function loadcontent(url, classname) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// below changes the url to the new page
window.history.pushState(url, url, url);
var htmlres = document.createElement("div");
// get the html from the ajax response and then change the required parts.
htmlres.innerHTML = this.response;
document.querySelector(classname).innerHTML = htmlres.querySelector(
classname
).innerHTML;
}
};
xhttp.open("GET", url, true);
xhttp.send();
}
window.addEventListener("popstate", function(e) {
window.location.reload();
});
example link for about page
<a onclick = "loadcontent('{%url 'about_page'%}', '.content')" id = 'About'>About</a>
Django views.py about page
def about_page(request):
if request.is_ajax():
return HttpResponse('mainsite/about_page.html')
return render(request, 'mainsite/about_page.html')
First, of all I would appreciate feedback if this is actually a good idea or not. I have just started learning web programming and this is a mini-project of sorts.
Secondly, my issue is with pressing the back button on my browser. With the current code, I cause it to reload the url because if I press the back button and go back to my "Home" page without reloading, the webpage still displays the same thing on my "About" page.
Having to reload is not ideal since I went through the trouble of creating a way to only load certain parts of my webpage. Is there any way to store what has changed, so that when I "popstate()", it will revert the changes? One possible way is to call my loadcontent() function when popstate happens. However as shown in my function, I need to pass it the url to go to, and class name of the "div" that I want to swap. Is there a way to store the previous URL and which classname was changed?
Thirdly, as shown in my load content function, I don't really know what the "state" parameter sent to history.pushState() is for... I understand that it is a key-value dictionary-like object, however, when is it stored and when will I need to access it? Is it useful for my case where I just need to reload content without any user-selected items?
The only thing I can think of now is to do something like to use {wasloaded: True} as my state parameter, so that when I do "popstate()", it is able to identify if the current page was loaded through my loadcontent() or not, and handle it as required. (I guess this is because if someone came to my page from a totally different website, I would need to reload their page instead of trying to do loadcontent().)
Thank you for taking the time to read this!
Your approach is not good for this.
you have to follow following steps to achieve this;
the DOM which you want to update on JS event should have a unique ID or class.
make your ajax call which should return JSON response not HttpResponse and JSONResponse should have HTML field, rendered HTML of you template. You can use get_template and render methods for this.
On success, you have to update the HTML of the page by selecting the unique DOM container.
My page sends out an ajax calls as part of page load and the response takes ~5 seconds
I take result from the ajax call and store it in a hidden div.
Now after page is rendered , there is a table (JQuery Datatable) , and each table row has some action buttons (view, edit , delete), which the user can click.
Some of these actions need the data from the div.
So if the user clicks any of those actions before the Ajax is complete, the action fails, but it will work fine in case Ajax call is complete.
Can I add a wait/sleep logic to those calls/code, so that if the use click the actions, it just waits for AJAX response, rather than enabling the action buttons as callback or failure and the user doesn't have to click the button again.
I tried adding a function with setTimeout logic, but it breaks my model.
Ajax Call
$.ajax({
url: "ajax?AJAXKeyword=keyword",
success: function(result){
$(document).ready(function () {
$( "#div" ).html( result );
});
}
})
OnClick Action which needs the data
.on('click', 'a.show-row', function( e ) {
e.preventDefault();
doPoll1();
})
function doPoll1(){
if( $("#div").text().length == 0) {
setTimeout(doPoll1,1000);
} else {
=== myActions ===
}
}
I would like the execution of JS Code to sleep/wait in case the data is not present.
So you have 2 different ajax call one loading Datatable another loading Div.
In that case
1 Either load div first and than call Datatable
2 Disable all buttons by default and enable when Div is loaded. Keep a divLoaded variable globally as boolean.
In that case user will not be able to click button.
3 Keep track of all button clicked before Div was loaded and once div is loaded, do action for clicked row record.
If you have Data in Datatable call itself. This is way to get row data on button click.
Instead of saving data in a separate Div you can get clicked Row data from Datatable API itself and this will avoid ajax load call issue.
Sample Edit Row event:
$('.dt-edit').each(function () {
$(this).on('click', function(evt){
$this = $(this);
var dtRow = $this.parents('tr');
$('div.modal-body').innerHTML='';
$('div.modal-body').append('Row index: '+dtRow[0].rowIndex+'<br/>');
$('div.modal-body').append('Number of columns: '+dtRow[0].cells.length+'<br/>');
for(var i=0; i < dtRow[0].cells.length; i++){
$('div.modal-body').append('Cell (column, row) '+dtRow[0].cells[i]._DT_CellIndex.column+', '+dtRow[0].cells[i]._DT_CellIndex.row+' => innerHTML : '+dtRow[0].cells[i].innerHTML+'<br/>');
}
$('#myModal').modal('show');
});
});
dtRow will contain all fields needed for that particular row.
Refer this for demo
What you can do easily is show a loading icon and disable the buttons until the ajax loads.
function waiting(btnState){
$('btn.waitAjaxXY').attr("disabled", btnState);
if(btnState)
$('displayLoadGif').show()
else
$('displayLoadGif').hide()
}
$.Ajax({...... waiting(true)}).always(function(){waiting(false)})
This example is pretty raw but i hope it helps you.
It's better if you show the user why they can't push the button and how long since it's frustrating if just wont do the action i asked for.
I have a function which opens a jQuery dialog. The user is able to modify some data fields, like a dropdown and save the result. That works fine and the parent page is updated through JQ. Now when the same item is clicked again, the dialog appears without ever hitting the jQuery call and the data is as it was before changed. How do force the JavaScript to go through the same functions again and call the controller again for the new values? Let me know if you need code, but there has to be a command to cause the once invoked dialog to refresh it's data. Is this because of the browser cache? The code is like this:
function showTourDetails(tourId, row) {
$("#divSelectedTour").dialog("open");
$("#divSelectedTour").load('#Url.Action("_SelectedTour", "Tour", null, Request.Url.Scheme))?tourId = ' + tourId);
}
And the div is just an empty div that is filled with the partial view page:
[HttpGet]
public PartialViewResult _SelectedTour(string tourId)
{
SelectedTourModel tour = GetTour(Convert.ToInt64(tourId));
return PartialView(tour);
}
After trying many different approaches, this finally worked:
$.ajaxSetup ({
// Disable caching of AJAX responses
cache: false
});
I am currently working in my first backbone.js app. I made a "show comment" function that renders a view in an underscore.js template and renders it to my view. The problem is, I want to "toggle" all the comments when a button is clicked, not just "show" commentView. How can I refactor this "showComment" function to not duplicate the current view? The success callback iterates over each comment in the comment view and then renders it. Using toggle, I would like it to just render 1 view, not render the same view, multiple times on each click when clicking toggle.
Example:
User clicks the show comments button, 5 comments are displayed.
User clicks the show comments button, comments are hidden.
User clicks the show comments button, 10 comments are displayed (the first 5 and since the success function renders a whole new view, the first 5 questions initially displayed are appended to the first 5, so there are 10 total now).
Here is the main function
showComments: function() {
this.commentsView = this.$el.find(".comments_container");
this.commentsView.show(); ***INSTEAD OF .show() I CAN USE .TOGGLE() but I get DUPLICATES WHENEVER THE VIEW IS RENDERED ***
this.commentCollection = new app.CommentList();
// // debugger;
var self = this;
this.commentCollection.fetch({
data: { question_id: this.$el.attr('question_id') },
success: function(collection) {
collection.each(function(comment) {
var commentView = new app.CommentView({model: comment});
var html = commentView.render().el;
self.commentsView.append(html);
});
}
});
Here is the backbone Event:
'click .show_comments': 'showComments'
Any suggestions would be appreciated, thanks!
There is a few ways that you could do it.
You could render and hide the comment view on page load and then bind the button commentsView.toggle.
OR in your showComments function you can have an evaluation that checks to see if the commentsView is already created.
If (this.commentView != null)
//toggle
else
//create your view and show it
I have an array that is dynamically filled from some server-side C#. When the page loads that C# builds the content for a JQuery function. If the user changes a control, the page triggers a postback and that c# refills the content of my array with the correct data. However, even though it changes the data according to Firebug, I only see the data from the original array contents.
for example: The page initially loads this
<script>
function pageLoad() {
var ary= new Array('original-1','original-2', 'original-3', 'original-4');
}
</script>
On post back, it loads this (when I inspect it with firebug this is what is loaded on postback)
<script>
function pageLoad() {
var ary= new Array('updated-1','updated-2', 'updated-3', 'updated-4');
}
</script>
Even though the new content is loaded, I still get the original data not the updated data.
My question is: How can I use the data that is given on postback?
I feel like there is an easy fix, I just can not wrap my brain around it.
Declare your var ary=array() OUTSIDE the function so it has global visibility.
<script>
var ary= new Array('');
function pageLoad() {
ary= new Array('original-1','original-2', 'original-3', 'original-4');
}
</script>