View not updating in AngularJS - javascript

I am implementing infinite-scrolling in AngularJs. The below function gets called on a successful AJAX call, that takes place when:
The user scrolls to the end of screen.
The selects some filters, and hits the "Search" button.
In the first case, the data fetched from the AJAX call is appended to the existing list. In the second case, I intend to completely empty any existing data in the list, and display the new data. Here is my code to do that:
$scope.successCallBack=function(data){
$('#spn-model-buffering-image').hide(); //hide the loading spinner icon
if($scope.providersList === null) {
$scope.providersList = []; /* init if null */
}
if($scope.scrolled === 'true'){
/*If it was an scroll-end event, then simply append the new data to the existing one*/
Array.prototype.push.apply($scope.providersList, JSON.parse(data.serviceproviderlist)); //push the new data to the existing list
}
else{
/*If the user clicks on "Search Providers" button, then new data are fetched, and occupy the entire list view*/
$scope.providersList=[];
$scope.providersList=JSON.parse(data.serviceproviderlist);
}
viewToBeDisplayed(LIST_VIEW);
$scope.scrolled='true';
}
So, after a successful AJAX call, the above method is called. It hides the buffering image, and checks if the variable named scrolled is set to true. If yes, then it means that the event is not button-click, but the user has reached the end of screen, and hence, data have to be appended. Else, the user has clicked on the button, and hence, data have to be displayed fresh.
This is the function that gets called on button-click event:
$scope.getFilteredData=function(){
$scope.scrolled='false';
$scope.getMoreData();
}
My problem: View does not get updated. The AJAX call returns data as JSON. In the scroll-event, data are fetched and appended to the existing list, as expected.
Can someone suggest me what I might be doing wrong? Thanks!
Here is the AJAX call code:
$scope.getMoreData=function(){
$('#spn-model-buffering-image1').show(); //while the data are being fetched, display the loading spinner
$scope.updateAjaxData(); //update AJAX data: pagekey, category, and reftag
var url=$scope.getURL();
A.ajax(url, {
method: 'post',
params: AJAX_DATA,
success: function(data, s, x) {
$scope.successCallBack(data);
},
error: function(xhr, statusText, errorThrown) {
$scope.errorCallback(xhr);
}
});
}

Try to use the http provided by AngularJS.
$http.get('/someUrl', config).then(successCallback, errorCallback);
This is good practice and it will probably solve your problem of not updating the view.

Related

document.getElementById(..) gives null even though element is present

I have the following program in which a user can enter any name in a search box after which I redirect the user to a page called usernameSearchResults.php where I print a list of the usernames obtained in the form of an array from usernamesearch.php. Here is the javascript:
$(window).on('load', function() {
$(".searchBarForm").submit(function(e){
e.preventDefault();
var search=document.getElementsByClassName("search")[0].value;
$.ajax
({
type: 'POST',
url: 'usernamesearch.php',
data:
{
search:search
},
success: function (response)
{
window.location.href="usernameSearchResults.php";
response = JSON.parse(response);
var array_length = Object.keys(response).length;//getting array length
for(var i=0;i<array_length;i++){
if(i==0){
document.getElementById("searchResults").innerHTML=""+response[0].username+"<br>";//i=0
}else{
document.getElementById("searchResults").innerHTML+=""+response[i].username+"<br>";
}
}
window.stop();//stops page from refreshing any further(put here to fix a bug that was occuring)
},
error: function(xhr, status, error) {
alert(xhr.responseText);
}
});
return false;
})
});
This is usernameSearchResults.php(inside tags):
<h1>Username Search Results</h1>
<p id="searchResults"></p>
But the problem is that whenever I go to any other page say index.php and enter the username to be searched, the page redirected to is indeed usernameSearchResults.php but the page is blank and error in the console shown says document.getElementById("searchResults") is null.But if I stay at the page usernameSearchResults.php and refresh it and then search any name again, then the results are correctly obtained. What is the problem here?
I would say that the user is being redirected to usernameSearchResults.php but the JavaScript code is still being executed from the current page, which have no element with id "searchResults" defined.
As #Kashkain said, one way to achieve what you want is to pass your response variable in your redirection url and process it then into your other page.
I think the problem here is that the new document could very well still not have been loaded when you call getElementById.
You could add a listener on your target element which would trigger on the load event. In this event's handler you could execute the operations that are now giving you an error.
I have never done or tried this, but maybe something like this would work:
$('#searchResults').on('load', function() {
//execute code here
});
Or you could add a form to the page with action="target_url" method="post" and send your response data through post by doing form.submit, and place the problematic code into usernameSearchResults.php, which will need to read data from POST - this way you can send your ajax data to the new page

Ajax call function for each tab

I created responsive tabs just using css. But when I try to implement ajax calls, i am bit confused.
I have a few questions:
What is the best way to make ajax request for each tab?
Is there any shortest way to append response to "tab" div?
How can I call ajax on page load for selected tab?
After first click on tab, do not need to make ajax call again. I need to cache response, but "cache:true" does not work.
Also any other improvements, suggestions and corrections would be helpful.
Example: JSFiddle
if you must use ajax i would run a loop through all the data you need to load do it at once an store the data in a variable (or object in this case)
than the change event will get the id from the tabData which is already populated and you won't need to call the ajax pages again.
now this will solve your cache problem since you won't need it for this scenario
if you want to instant populate the first selected tab when you open the page created an if statement in the ajax success
end result would look something along these lines:
$(document).ready(function() {
//data for the tabs
var tabs = {
1:"tabone",
2:"tabtwo",
3:"tabthree"
}
//empty object for now will be filled with ajax data
var tabData = {};
var activeTabVal=1;
var activeTabID = $('input[name=tabs]:checked', ".tabs").attr('id');
for(key in tabs) {
ajaxCall(key);
}
$('.tabs input').on('change', function() {
var activeTab=$('input[type="radio"]:checked', '.tabs').val();
var tabElement = $('input[name=tabs]:checked', ".tabs").attr('id');
//since we have the data already no need to call ajax here we just get it out of our already loaded data
var data = tabData[activeTab];
replaceData(tabElement, data);
});
function ajaxCall(key){
$.ajax({
type: "POST",
dataType: 'jsonp',
url: 'https://jsonplaceholder.typicode.com/posts/'+key,
async: false,
cache: true,
contentType: "application/json; charset=utf-8",
success: function (msg) {
tabData[key] = msg.body;
//use this to imediatly populate the selected div fo your second point
if(key == activeTabVal) {
replaceData(tabs[key], tabData[key]);
}
}
});
}
function replaceData(tabElement, tabData) {
$('#'+tabElement).next().next().closest('div').append(tabData);
}
});
I would instead of calling it on change I would call it on tab button clicked
Give your tab a data-id and the corresponding container div the same data-id, then when you append you can do something like $('.tab-container[data-id='+$(this).attr('data-id')+']').append('The content');
If you bind it to click you can simply run $('.tab-button .active').trigger('click');
If I were you I would store the data into the data portion of the container div and retrieve it again when they click on it again. So you just check if it was set, if not then do ajax call, if it was just pluck it out and display it. https://api.jquery.com/jquery.data/

Sorting a table column in a grid in extjs after adding multiple records to it

I have a grid in my application where i am showing some data in tabular form. Normally when I load a store to it, it will work normally, i mean if we click on the column header, it will sort accordingly. now I am adding multiple records to this table by performing some bulk add operation. That operation is adding the new records at the end and after that if i am sorting the column, its sorting the previous list separately and the new data separately. But if I am adding only one record(that I am doing from different function), it works fine.
code for single add is :
onSingleAdd : function() {
var rec = Ext.create('kav.model.xyz.xyzmodel', {
id : null,
recordid : this.recordid
});
this.store.insert(0, rec);
this.rowEditing.startEdit(0, 0);
}
For multiple add, I am showing a popup and then hitting a ajax call after that, and on success of that ajax call i am coming back to this page. Code for that ajax call is :
Ext.Ajax.request({
url : 'some/url'
params : dataToSend,
scope : this,
success : function(response, opts){
var data = eval('('+response.responseText+')');
if(data.success){
this.up('window').manager.loadStore();
this.up('window').close();
} else {
//show message
}
},
failure : function(response, opts){
//handle failure
}
});
Thanks in advance.

Proper way handling nested ajax request

I was wondering if there is any proper way to prevent ajax request from delivering random 404/500 Errors when calling many of them at the same time (synchronous or asynchronous)
e.g. a simple html table with some rows and columns to show a list of 500-800 people with some data
Way to go:
Getting ppl by selection (html form with organizational units) from the backend and write the resultlist in the first columns of the table
getting events of each person by his/her personId (result of the first request)
getting attributes of each person
getting roles for each person
getting calculated stuff from the backend for each person depending on their individual attributes,roles and events.
pseudocode:
function createTableData(){
var selected;
var personIds;
//get personIds by selection and write them into table
object.executeJSONRequest(...,
{ _ts: new Date().getTime(),
input: selected
},function(data) {
// write result into table
// fill resourceIds with result param
},..);
getEvents(personIds);
getAttribtues(personIds);
getRoles(personIds);
calculateStuff(personIds);
}
function getEvents(personIds){
object.executeGetRequest('...',
{ _ts: new Date().getTime(),
ppl: personIds
},function(data) {
//add result to table
}
}
function getAttributes(personIds){...} //and so on..
if i call all these methods in a row i sometimes get random errors sometimes while loading attributes, sometimes on loading roles, sometimes it all works fine.
if i call them nested in each ajax success block like
function createTableData(){
object.executeJSONRequest(...
{ _ts: new Date().getTime(),
input: selected
},function(data) {
getEvents(..);
});
}
function getEvents(..){
object.executeGETRequest(...
{ _ts: new Date().getTime(),
input: selected
},function(data) {
getAttributes(..);
});
}
function getAttributes(..){ ...,function(data){ getRole(..)}); and so on
it all works fine. If i try a solution with something like
document.ajaxStart/Stop(function(){ //if table columns i expected are filled do next}
i have to check all neccessary table colums if they are already filled with data or not.
Is there any really proper solution i just dind't think about?
(jQuery Version 1.2 /IE V7-8 ^^)
"If possible update jquery and ie versions"
First of all why are you calling multiple server calls in a single process.
It's better if you combine all the process into a single request and response cycle, do the required handling of data in java code.Don't go forth and back with request and response.
Any way you can use the jquery ajax which returns the status of the ajax call.
$.post("url",function(result,status){{
if(status == success){
//continue....
}else{
alert("Sorry something went wrong");
}
}});
Like this check all the request weather it successfully finished.
I strongly recommend you consider combining all the ajax calls into a single request.

Display user profile in div using ajax

I want to display user profile when admin mouser over on username link. If this is first time, user profile is displayed; then next time ajax should not fire and display user profile without ajax fire.
To implement the functionality proceed step by step:
On mouseover of the username, implement an ajax call that renders user profile in html near the username
Through javascript, implement functionality such that when user leaves the username/userprofile, the user profile div is now hidden
While making ajax calls in #1 above, check if the div already exist which contains user profile for the userid which you are trying to request. This can be easily achieved by having some id in the user profile part and checking if that #user_profile_#{id} div exists.
Your requirement is too broad to be able to provide any code...
If you have problem in implementation of any of the above parts, post them as question separately one by one..
You need to know the id and the class of the username link.
You can make jQuery listen to the hover, when that event occurs you can call the function which will do the ajax.
But, you need to know the id of the user, the best way to do that is to do something like
<a href='user123.php' class='userHref' id='user_123'>I want to be hovered</a>
Now you have a link to hover over.
$('.userHref').live("hover", function()
{
var userHrefId = $(this).attr('id');
var userHrefIdSplit = userHrefId .split('_');
var userId = userHrefIdSplit[1];
useAjax(userId);
});
Now you have listened to the hover by listening to any hovering over a link of the class userHref, jquery has responded by taking the id of the a element, splitting the id into 2 seperate items, where the second one indicates the user Id.
Now we have also called with useAjax function and we have sent the id of the user. Now you can POST the userId to a known backend site (rails in your example), which will query the database and return the url to the user image. We then only have to know the id of the div element which you want the image to appear in.
function useAjax(userId);
{
var id = userId;
var select = true;
var url = '../scripts/ajax.php';
$.ajax(
{
// Post select to url.
type : 'post',
url : url,
dataType : 'json', // expected returned data format.
data :
{
'select' : select, // the variable you're posting.
'userId' : id
},
success : function(data)
{
// This happens AFTER the backend has returned an JSON array
var userUrl, userImg, message;
for(var i = 0; i < data.length; i++)
{
// Parse through the JSON array which was returned.
// A proper error handling should be added here (check if
// everything went successful or not)
userUrl = data[i].userUrl;
message = data[i].message;
userImg = "<img src='"+userUrl+"' alt='' title='' />";
$('#someDiv').html(userImg); // Here's your image.
}
},
complete : function(data)
{
// do something, not critical.
}
});
}
I'm not familar with rails but you can probably program the backend in a similar wasy as I exmplained here: Javascript function as php?
Search for my answer, it should give you a very detailed example.
I hope this helps.
Tip for the future: Try and google first :)
Assuming you're using jQuery, bind a hover event to the user name link. As so:
$('.username').hover(function (e) {
console.log("i'm hovering!! on id: "+$(this).attr('data-user-id')); //See the next step for where this came from
}
Next, add the user's id to the username element, perhaps in a data attribute:
<span class="username" data-user-id="1234567890">Username</span>
Next, keep a record of which users are already loaded, perhaps by id. When you fetch something new, add it to the object. I like to keep objects like this on the window.
window.loadedUserInfo = {};
On hover check if the userId key exists in this object. If it does, user it. If not, use an ajax call to get it:
$.ajax({
url : "path/to/userinfo"+userid, //I'm assuming you're using restful endpoints
type : "GET",
success : function (res) {
window.loadedUserInfo[userid] = res;
//Format your popover with the info
},
error: function (jqxhr) {
//something went wrong
}
})
As for the popover itself, you could probably use a bootstrap popover.
Putting it all together:
$(".username").hover(function (e) {
console.log("i'm hovering!! on id: "+$(this).attr("data-user-id")); //See the next step for where this came from
if (typeof window.loadUserInfo[$(this).attr("data-user-id")] == 'undefined') {
$.ajax({
url : "path/to/userinfo"+userid, //I'm assuming you're using restful endpoints
type : "GET",
success : function (res) {
window.loadedUserInfo[userid] = res;
//Format your popover with the info
},
error: function (jqxhr) {
//something went wrong
}
})
} else {
//populate popover with info in window.loadUserInfo[$(this).attr('data-user-id')]
}
}

Categories