AngularJS Load more function - javascript

So I am trying to make load more function.I am fetching data from twitch API and it comes as array of objects.
$scope.loadData = function () {
$http.get("https://api.twitch.tv/kraken/streams?limit=9&offset=" + $scope.x).then(function(response) {
$scope.myName = response.data.streams;
$scope.link="http://player.twitch.tv/?channel=";
return $scope.x=$scope.x + 9; }); };
//initial load
$scope.loadData();
$scope.myName is array in which data is stored and it is used in ng-repeat.
$scope.x is variable used for offset and after clicking button it is incremented and is used to fetch new streams.So when I click button it removes old 9 streams and loads new 9 streams.I want to keep my old 9 streams and to just add 9 more everytime button is clicked.
See here: https://plnkr.co/edit/TbOf9hkPILJn2snW8D7A Thanks.

If I understood problem well, you should just append your data array instead of replacing it:
$scope.myName = [];
$scope.loadData = function () {
$http.get("https://api.twitch.tv/kraken/streams?limit=9&offset=" + $scope.x).then(function(response) {
// add streams to existing array
Array.prototype.push.apply($scope.myName, response.data.streams);
$scope.link="http://player.twitch.tv/?channel=";
return $scope.x=$scope.x + 9; }); };
//initial load
$scope.loadData();

HERE IS THE SOLUTION OF PLNKR
I've modified Streamovi controller and added load more button at the bottom so you can trigger loading more
app.controller('Streamovi', function($scope, $http) {
var ITEMS_PER_LOAD = 9;
var offset = 0;
$scope.myName = [];
function loadStreams(){
$http.get("https://api.twitch.tv/kraken/streams?limit="+ITEMS_PER_LOAD+'&offset='+offset).then(function(response) {
$scope.myName = $scope.myName.concat(response.data.streams);
$scope.link="http://player.twitch.tv/?channel=";
offset+=ITEMS_PER_LOAD;
});
}
//handler for the "Load More" button in the view.
$scope.loadMore = function(){
loadStreams();
}
//initial Loading
loadStreams();
});

Related

Load data from Firebase using AngularJS immediately

I am trying to make a comments section on my website. I have properly linked all my files and getting data from Firebase is working. But, the comments only load after I either click on something or enter text in the "Add comment" field; it does not show the comments instantly when the page loads. Does anyone know why?
Relevant code: (placed at the top of my controller)
$scope.comments = {};
database.ref('comments').on('value', function(items) {
$scope.comments = items.val();
});
$scope.comment = function() {
database.ref('comments').push($scope.newComment);
$scope.newComment = "";
};
Use $scope.$apply
$scope.comments = {};
database.ref('comments').on('value', function(items) {
$scope.$apply(function () {
$scope.comments = items.val();
});
});
$scope.comment = function() {
database.ref('comments').push($scope.newComment);
$scope.newComment = "";
};

AngularJS - Change data in ngRepeat after load

I have a bunch of radio groups and a textarea elements that load in a ng-repeat controller. I want to populate all/some of those controls after the controller has finished loading them. I have tried $scope.$on. I have looked at directives, but they are really confusing.
I just want to call a function to populate the form (manipulate DOM) after the controller has finished loading. The controller currently loads (and loads a sub-controller) on the click of a button.
Here's some example code of what I have. The Risks function is what I am calling when the button is clicked.
myApp.controller('spRisks', function ($scope, $http, Service) {
$scope.getRisks = function(){
var caml = "<View><Query><Where><Eq><FieldRef Name='Owner'/><Value Type='Integer'><UserID/></Value></Eq></Where></Query></View>";
var ownerData = getDataWithCaml("Owners", caml);
ownerData.success(function (data) {
var arrayOfExpressions = [];
for (var i = 0; i < data.d.results.length; i++){
arrayOfExpressions.push(CamlBuilder.Expression().LookupMultiField("OwnerTitle").EqualTo(data.d.results[i].Title));
}
var newCaml = new CamlBuilder().View().Query().Where()
.Any(arrayOfExpressions)
.And()
.TextField("Control").IsNotNull()
.ToString();
newCaml = newCaml.replace(/"/g, '\'');
var jsonData = getDataWithCaml("Risks", newCaml);
jsonData.success(function (jsonDataResults) {
$scope.$apply(function(){$scope.Risks = jsonDataResults.d.results;});
});
jQuery('#divQs').show();
});
$scope.$on('$viewContentLoaded', function () {
alert('test');
Service.getAnswers($('#selYear').val(), $('#selMonth').val());
});
}
});

HTML/jQuery Save order

I'm using the jquery plugin called shapeshift. It's like jqueryui sortable but with better animations. The divs can be dragged and dropped. But I can't seem to figure out how to save their order so that on browser refesh the order remains the same where I left them.
Here is the jsfiddle http://jsfiddle.net/Shikhar_Srivastava/aC367/
$(".container").shapeshift({minColumns: 3});
I'm initiating the plugin as above.
Please help me on my fiddle.
Thanks.
I would create a cookie. So I would first include the jQuery Cookie script (found here: https://github.com/carhartl/jquery-cookie/blob/master/src/jquery.cookie.js), then create the cookies (one for each each .container) each time an element is moved:
/* save cookie */
$('.container').on("ss-drop-complete", function() {
var containerCookieCounter = 0;
$('.container').each(function() {
/* cookie = 12h */
var date = new Date();
date.setTime(date.getTime() + (720 * 60 * 1000));
$.cookie('savepositions' + containerCookieCounter, $(this).html(), { expires: date, path: '/' });
containerCookieCounter += 1;
});
});
Then, before initiating the shapeshift-function, check if there are existing cookies:
/* cookies... */
if ($.cookie('savepositions0')) {
var containerCounter = 0;
$('.container').each(function() {
$(this).html($.cookie('savepositions' + containerCounter));
containerCounter += 1;
});
}
Here is a working fiddle: http://jsfiddle.net/Niffler/FvUcQ/
Only one container
Fiddle
var $con=$(".container").shapeshift({
minColumns: 3
});
function getPos(id){
var p=localStorage[id];
var ro={left:100000,top:-1,unknown:true};
if(p!==undefined) ro=JSON.parse(p);
//alert('get Pos:'+id+' '+JSON.stringify(ro));
return ro;
}
function setPos(id,p){
//alert('set Pos:'+id+' '+JSON.stringify(p));
localStorage[id]=JSON.stringify(p);
}
function arrange(){
var o={};
var con=$(".container:nth-child(1)");
var els=$(".container:nth-child(1) div");
els.each(function(x){
var me=$(this);
var id=me.attr('id');
var o_=o[id]={};
o_.id=me.attr('id');
o_.p=getPos(id);
});
for(var i in o){
var oo=o[i];
var el=$('#'+oo.id);
if(!oo.unknown){
el.css('left',''+oo.p.left+'px');
}
}
}
function savePs(){
var els=$(".container:nth-child(1) div");
els.each(function(){
var me=$(this);
setPos(me.attr('id'),me.position());
});
}
var $con=$(".container:nth-child(1)");
$con.on('ss-rearranged',function(e,selected){
var id=$(selected);
setTimeout(function(){
//var me=$(selected);
savePs();
//setPos(me.attr('id'),me.position());
},500);
});
arrange();
//savePs();
Fiddle
As commenters have suggested, you need to use localStorage to store and retrieve the state, and save that state after the ss-drop-complete event.
Here is the entire JS I used in this updated jsFiddle:
$(function () {
// retrieve from localStorage if there is a saved state
var saved = localStorage.getItem('arrangement');
if (saved) {
populateArrangement($('.container').parent(), JSON.parse(saved));
}
$(".container").shapeshift({
minColumns: 3
}).on('ss-drop-complete', function () {
// get the new arrangement and serialise it to localStorage as a string
var rows = getArrangement();
localStorage.setItem('arrangement', JSON.stringify(rows));
});
// return the data needed to reconstruct the collections as an array of arrays
function getArrangement() {
var rows = [];
$('.container').each(function () {
var elementsInRow = [];
$(this).find('.ss-active-child').each(function () {
elementsInRow.push({
value: parseInt($(this).text(), 10),
colspan: $(this).data('ss-colspan') || 1
});
});
rows.push(elementsInRow);
});
return rows;
}
// use the arrangement to populate the DOM correctly
function populateArrangement(container, newArrangement) {
$(container).find('.container').remove();
$.each(newArrangement, function (index, row) {
var $container = $('<div class="container"></div>');
$container.appendTo(container);
$.each(row, function (index, element) {
var $div = $('<div></div>');
$div.text(element.value);
if (element.colspan > 1)
$div.attr('data-ss-colspan', element.colspan);
$container.append($div);
});
});
}
});
If you have some sort of server side code you can add the order to a hidden field on the ss-drop-complete function and then post this back to the server on post back. You can then just re-output the values back when the page re-renders and you can use this information in any server side code you need.
I've done something similar when working with jquery mobile and ASP.NET to save back to a database the order.
If not, the local storage option could be a good way to go.

How to implement back button in Infinite Scrolling in AngularJs?

i'm building an app with angularjs, i have implemented infinite scrolling technique because i have a lot of items to show, so it's a better experience than pagination, but the bad thing that i'm having it's that if the user clicks on item it goes to item page, but when he wants to go back he will be on the top and he should keep scrolling. that's what i want to accomplish if he hits back button he could back to his position where he were !!
Listing Items:
<div class="container" id="infinit-container" ng-controller="ArticlesController">
<div id="fixed" when-scrolled="LoadMore()">
<div ng-repeat="article in Articles">
<article-post article="article"></article-post>
</div>
</div>
</div>
here is when-scrolled directive
app.directive('whenScrolled', function () {
return function (scope, element, attrs) {
$('#fixed').height($(window).height());
var div = element[0];
element.bind('scroll', function () {
if (div.scrollTop + div.offsetHeight >= div.scrollHeight) {
scope.$apply(attrs.whenScrolled);
}
})
}
})
thats the controller
app.controller('ArticlesController', function ($scope, UserService) {
$scope.Articles = [];
var page = 0;
$scope.LoadMore = function () {
UserService.Articles(page)
.success(function (data) {
$scope.Articles.push.apply($scope.Articles, data);
});
page++;
};
$scope.LoadMore();
});
im using page number, save page number somewhere (i prefer sessionStorage) when going to see the item detail , when user is comming back to list, read page number and load the page.
it is the simple code for main page controller (list)
app.controller('ArticlesController', function($scope, UserService) {
$scope.Articles = [];
var page = 0;
$scope.LoadMore = function() {
UserService.Articles(page)
.success(function(data) {
$scope.Articles.push.apply($scope.Articles, data);
});
page++;
}
$scope.LoadArticle = function(articleId) {
sessionStorage.setItem("pageNumber", page);
/// change path to somewhere you want show your article
};
//it will load the page you coming back from
if (sessionStorage["pageNumber"]) {
page = parseInt(sessionStorage["pageNumber"]);
}
LoadMore();
});
because of using sessionStorage , it will deleted if user close the browser or page as expected.

Limit Minimum Count of Nested Fields

I have a parent model and child model.
I want to make it mandatory that at least one child is created when a new parent is created.
I am using the nested_form gem and currently using this script to limit the number of children added per record.
$(function() {
var fieldsCount,
maxFieldsCount = 4,
$addLink = $('a.add_nested_fields');
function toggleAddLink() {
$addLink.toggle(fieldsCount <= maxFieldsCount)
}
$(document).on('nested:fieldAdded', function() {
fieldsCount += 1;
toggleAddLink();
});
$(document).on('nested:fieldRemoved', function() {
fieldsCount -= 1;
toggleAddLink();
});
// count existing nested fields after page was loaded
fieldsCount = $('form .fields').length;
toggleAddLink();
})
Is there a way for me to also include a "minimum" requirement? Lets say (1) child? Basically remove the "remove link" if only (1) nested form is visible.
Here is the code I figured out on how to make sure at least one field is presented by removing the "Remove" link based on its count
$(function() {
var fieldsCount,
maxFieldsCount = 2,
$addLink = $('a.add_nested_fields');
var mfieldsCount,
minFieldsCount = 0, // placed at 0 because first object is auto built from controller
$removeLink = $('a.remove_nested_fields');
function toggleAddLink() {
$addLink.toggle(fieldsCount <= maxFieldsCount)
}
function toggleRemoveLink() {
$removeLink.toggle(mfieldsCount <= minFieldsCount)
}
$(document).on('nested:fieldAdded', function() {
fieldsCount += 1;
toggleAddLink();
});
$(document).on('nested:fieldRemoved', function() {
fieldsCount -= 1;
toggleAddLink();
});
$(document).on('nested:fieldRemoved', function() {
mfieldsCount -= 0;
toggleRemoveLink();
});
// count existing nested fields after page was loaded
fieldsCount = $('form .fields').length;
toggleAddLink();
mfieldsCount = $('form .fields').length;
toggleRemoveLink();
})
You can just call a build method inside your parent's controller in action new.
So, when you go parent/new, you will have one child already created. It's just like that:
#parent.children.build

Categories