Check when a list is fully rendered with angular - javascript

I have an ul that loads data from an array using a ng-repeat. The array is pretty big and the load of the list lasts too much.
I want to put a loader so its shown at the begining of the loading and hides just, and this is the important part, when that ul is fully rendered in the html.
My problem is that I can’t find a way to throw a function when the ul is fully rendered.
The way I have this right now is:
Controller:
function renderMatters() {
api_horus.getMatters()
.success(function (data)
{
$scope.matters = data.matters;
}
})
.error(function (error) {
status = 'Unable to load matters data: ' + error.message;
});
}
HTML:
<ul ng-model="matters" class="list clearfix" ng-class="{'floatingList':isHorizontal}">
<li ng-repeat="matter in filtered = (matters | filter:searchText) class="matter_grid_li">
…
I’ve tried these possible solutions already:
1. Using ngRoute and $viewContentLoaded:
In angular-directive.js
$scope.$on('$viewContentLoaded', function() {
App.initComponent();
alert("Loaded");
});
This works, but the alert is not thrown when the is fully loaded, but half way of it more or less.
2. Using a template, ng-include and onload
I put the ul in a different file and call it as a template
<div ng-include src="'template/test-loading.html'" onload="alert(‘ends’);"></div>
It does not work either. The alert shows at the middle of the load.
I even tried putting the ng-repeated li as the template instead of the ul because I read that the onload is thrown only when the PARENT element is loaded. Not success either.
How can I know when an element is fully rendered in HTML?
Tx in advance.

just create one div with
<div ng-if="showMsg">{{msg}}</div>
<div ng-if="!showmMsg">
<ul ng-model="matters" class="list clearfix" ng-class=" {'floatingList':isHorizontal}">
<li ng-repeat="matter in filtered = (matters | filter:searchText) class="matter_grid_li"></div>
In controller :
$scope.showMsg = true;
$scope.msg = "loading...";
function renderMatters() {
api_horus.getMatters()
.success(function (data)
{
$scope.matters = data.matters;
$scope.showMsg = false;
$timeout(angular.noop)
}
})
.error(function (error) {
status = 'Unable to load matters data: ' + error.message;
});
}

Related

Toggle visibility using v-show or v-if in Vue while using a setTimeout function

I am using Vue2. I have a form. When submit is clicked I want to show a "Loading" Div for X amount of time. After this X amount of time, I want to Load the Form again. In a nutshell, after a click, toggle visibility, after certain code is executed and waited certain time, toggle it again.
I have two Divs:
<div v-if="this.isHidden">
LOADING....
</div>
<div v-if="!this.isHidden"> <!--or v-else -->
<form #submit.prevent="">
<!--Fields-->
<button #click="updateProduct(product)" type="button">Submit</button>
</form>
</div>
On load, only "CONTENT" shows (isHidden = false).
When the method updateProduct() is executed I want the div "LOADING" to appear for X amount of seconds (isHidden=true) while "CONTENT" div must hide. Then after executing some code inside a setTimeout function, I want them to toggle once again (isHidden = false).
data: function() {
return {
//isHidden is initialized as false
isHidden: false,
};
},
My method looks like this:
updateProduct(product){
this.isHidden = true;
alert(this.isHidden + 'This correctly shows true. CONTENT correctly toggles and HIDES. LOADING also works correctly and APPEARS.');
//I want to delay the following code with setTimeout so that I am able to control for how long I want to show LOADING
setTimeout(function(){
//do a bunch of tasks that work correctly...
axios.post('/api/product/' + product.id, data)
.then(function (response) {
console.log(response);
}).catch(function (error) {
console.log(error);
});
//After all my code is executed, I am still inside the setTimeout function inside the updateProduct method so now i do this:
this.isHidden = false;
alert(this.isHidden + ' This correctly shows false BUT DIVS DO NOT UPDATE ANYMORE, I am stuck with the LOADING div');
//although my code works fine and the alert shows the correct value for isHidden, my view is stuck in LOADING
}, 2000);
}
I have attempted to move this.isHidden = false; outside of the setTimeout function but it still doesn't "toggle" the visibility.
I have also tried to use v-if instead of v-show, same behaviour.
Your main issue is this inside the setTimeout callback
Because you use function() {} it's NOT what you want this to be
Either use arrow notation setTimeout(() => {}, 2000)
updateProduct(product) {
this.isHidden = true;
setTimeout(() => {
//do a bunch of tasks that work correctly...
axios.post('/api/product/' + product.id, data)
.then(function(response) {
console.log(response);
}).catch(function(error) {
console.log(error);
});
this.isHidden = false;
}, 2000);
}
Or, if arrow notation scares you setTimeout(function() {}.bind(this), 2000)
updateProduct(product) {
this.isHidden = true;
setTimeout(function() {
//do a bunch of tasks that work correctly...
axios.post('/api/product/' + product.id, data)
.then(function(response) {
console.log(response);
}).catch(function(error) {
console.log(error);
});
this.isHidden = false;
}.bind(this), 2000);
}
As a side note, do not use alert for debugging - it blocks execution of javascript and can lead to unreliable debugging results
Just Use V-else
<div v-if="!this.isHidden"> <!--or v-else -->
<form #submit.prevent="">
<!--Fields-->
<button #click="updateProduct(product)" type="button">Submit</button>
</form>
</div>
<div v-else>
<div v-if="this.isHidden">
LOADING....
</div>
</div>

AngularJS needs to execute a function two times to show the results

I have a navigation bar which has a drop-down menu item Log Out which calls the ngPostLogOut() function.
In app.js
.when("/logout", {
controller: 'AuthController',
templateUrl: "client/html/auth/logout.html"
});
AuthController
$scope.ngPOSTLogOut = function() {
if ($rootScope.user) {
$rootScope.user = null;
}
if ($window.sessionStorage) {
$window.sessionStorage.clear();
alert('Entered..');
}
alert('Before HTTP');
$http.post('server/auth/logout.php')
.then(function(result) {
$scope.logout = result.data;
});
alert('After HTTP');
/*
$timeout(function() {
$location.path('/');
}, 10000);
*/
};
logout.html
<div ng-controller="AuthController as auth">
<p ng-show='user == null' class="text-center">{{logout}}</p>
<br>
<button ng-click='ngPOSTLogOut()' class="btn btn-default btn-block">Angular To PHP</button>
Now, if a person clicks the Log Out item from the drop-down in the navbar then the function is called. I know this because I have set up alerts and they do pop up. But, the 'echo' from the login.php doesn't get featured. But, the odd thing is is that if I press the Angular to PHP button which also calls the ngPostLogOut() function, the function completes perfectly and as intended.
My guess
My guess is that ngRoute forces Angular to prioritize the HTML template switch making it so that the ngPOSTLogOut() function's parametres get ignored or dismissed.
The entire project on GitHub
https://github.com/AquaSolid/RAMA_Angular_PHP
Change this:
<li ng-click='ngPOSTLogOut()' ng-show='user != null'>Log Out</li>
to this:
<li ng-show="user != null"><a ng-click="ngPOSTLogOut()">Log Out</a></li>
And consider using ng-if rather than ng-show.

calling Angular js file with partial doesn't work for first time

I am trying to load following js with partial, using $http . my problem is when i run code firest time get controller undefined type error,
where as on second click it works fine.
JAVASCRIPT::
$scope.loadPage = function(testurl) {
$scope.testpage = testurl;
var element = angular.element($("#data_template"));
$http.get(testurl).success(function(data) {
element.html(data);
$compile(element.contents())($rootScope);
$('.div1').slideUp('slow');
$('#data_template').slideDown('slow');
});
};
HTML::
<div class="movie-listing movie-listing-step"
ng-controller="ProductAddController">
<!-- all DOm PArt -->
</div>
mt js comes from s3 bucket, so may be js taking long time to come and $compile starts before js load . how to solve this problem ??
Here I have used $viewContentLoaded
app.controller('ProductAddController', function ($scope, $timeout) {
$scope.loadPage = function(testurl) {
$scope.testpage = testurl;
var element = angular.element($("#data_template"));
$http.get(testurl).success(function (data) {
element.html(data);
$compile(element.contents())($rootScope);
$('.div1').slideUp('slow');
$('#data_template').slideDown('slow');
});
}
$scope.$on('$viewContentLoaded', function(event) {
$timeout(function() {
$scope.loadPage(testurl);
},0);
});

Backbone | Script for document ready

There is a script(js) which I wish to run on like $(document).ready(). There is a way to write the script in template(e.g. home_tpl.html) file. But I am sure this is not a good way.
I am loading the html from a backbone view. I am not using any other wrapper like marionate. Here I wish to run some script when a template is loaded(DOM is loaded). In which way can I write the script?
Here is the rendering of view
reset: function(key, email){
require(['js/views/reset_password', 'js/models/forgot_password'], function(ResetView, ResetModel){
var resetModel = new ResetModel();
resetModel.set('key', key);
resetModel.set('email', email);
$('body').html(new ResetView({model: resetModel}).render().el);
});
},
Here is the view code
define(['text!tpl/reset_passwordtpl.html'],function(Template){
return Backbone.View.extend({
template: _.template(Template),
render: function(){
$(this.el).html(this.template());
return this;
},
events: {
"click #btn_reset_password": "reset"
},
reset: function(){
if($('#reset_password').val() != $('#confirm_reset_password').val()){
$('#error_message').text('Passwords mismatched').show();
}
else{
$.ajax({
url: server_url + 'reset',
type:'POST',
dataType:"json",
data: {'id': this.model.get('email'), 'key': this.model.get('key'), 'new_password': $('#reset_password').val()},
success:function (data) {
if(data.error) { // If there is an error, show the error messages
$('.alert-error').text(data.error.text).show();
}
else { // If not, send them back to the home page
$("#content").html("<h6>Your password is reset. Click <a href='#login'>here</a> to login.</h6>");
}
}
});
}
}
});
});
thanks
Somewhere you should have a main view. Where you also include stylesheets etc. At the bottom of the page just before the body closing tag. Within some script tags just do the document.ready thing. Unless that is also in a template in which case I would consider using a different structure when it comes to views.
If you just want to do this when one template is ready loading I would use succes with a anonymous function.

Get specific page from URL and get the data with AJAX

window.onload= function(){
var page = window.location.hash;
if(window.location.hash != ""){
page = page.replace('#page:', '');
getdata('src/'.page);
}
}
After the window loads, i want the page to look in the URL, see if there is a # is set, and if so, i want to grab the page and display it inside a DIV. So for example, a link would be link. So when somenone clicks on the link, the page thinks and grabs the data from contact.php, and puts it inside the div. But now, this isn't working. No errors, no warnings, no nothing. Help please? Thanks!
Edit: Getdata:
function getdata(file){
openloading(); // loading message
$('#content').fadeOut('slow', function () { // Content is the div where all the content must be in
$.get(file, function(data) {
$('#content').html(data);
$('#content').fadeIn('slow');
})
})
updateusersonline();
}
And updateusersonline() directly too:
function updateusersonline(){
$.get('src/usersonline.php', function(data3) {
$('#usersonline').html(data3);
})
getdata('src/'.page); should be getdata('src/' + page);

Categories