AngularJS: Getting siblings of routed item - angularjs

Ok so I'm using routing to drill down into a specific item based on it's ID (but also capturing it's category)
$http.get('http://something.co.uk/?category='+$routeParams.storyCat+'&id='+$routeParams.storyID)
This gives a URL of http://website.co.uk/index.html#/category/103 with the story details coming from the data on the server based on the ID of the item you clicked.
The following functions are then run on swipe (using angular-touch) which increase or decrease the ID by one, showing the next or previous story.
$scope.nextStory = function () {
var storyID = Number($routeParams.storyID);
var storyCat = $routeParams.storyCat;
var path = '/' + storyCat + '/' + (storyID + 1 );
$location.path(path);
};
$scope.previousStory = function () {
var storyID = Number($routeParams.storyID);
var storyCat = $routeParams.storyCat;
var path = '/' + storyCat + '/' + (storyID - 1 );
$location.path(path);
};
The problem with this is that it literally just goes up and down the ID's. I need it to only go through ID's which match the Category of the item you are on.
For example if you click into story ID 95, which is in a category called "Bags" and then you swipe left, I need it to not simply show story 96 which might be in a different category, but instead find the next story within "Bags" and show that one.
Can this even be done using AngularJS and routing or do I need a completely different approach?

Related

Can't get .foreach iterator to post multiple lines

function myFunction() {
/////////////////////////////////////Fill planning/decor package
var managementSheet = SpreadsheetApp.openById("1P3EF4Edu0efzJVV1Sx-0ayAPaAAiRK8Sl0Y1qZHmcf4");
var packageSheet = managementSheet.getSheetByName("Order Contents");
//Order Contents iterater
var c = packageSheet.getMaxColumns();
var n = packageSheet.getLastRow();
var items = packageSheet.getRange(2,1,n,c).getValues();
var filteredItems = items.filter(function(row) {
if(row[2].toString().includes(firstName +" "+lastName))
{
var results =new Array();
var info = new Array();
info[0]=row[3];
info[1]=row[5];
info[2]=row[9];
info[3]=row[14];
info[4]=row[15];
info[5]=row[16];
results[0]= info;
// result = results.every().valueOf();
Logger.log(results)
var row=22
results.forEach(function(value, index) {
Logger.log("The value at index " + index + " is " + value + ".");
generatedInvoice.getRange(22,1,1,7).setValues([[info[0],,info[1],info[2],info[3],info[4],info[5]]])
row= index + 22+1
})}})
}
Hello. First off, I'm new to appscript/javascript/script in general... Secondly, I'm the worst at explaining things and am so over this as I've been working on it for 2 days with only a few food/water/sleep breaks and just can't figure it out.
I'm trying to take rows from one sheet and copy only some of that row's values to a template...
Customer orders are on one sheet.
Order CONTENTS(for all customers' orders) are on another sheet.
I want to generate an invoice containing everything that the customer has ordered. The code I have currently lists only the final row of the "results" array into my template sheet. I want all of the items that the customer ordered to be added to the invoice. I'm trying to figure out how to use "index" to move to the next line and add the next set of values, but I'm not sure what I'm doing wrong. By logging info, I see that everything is being called correctly and adding to the correct spot in the template. The problem is that it only adds the final line of data into the template when I want all of the lines that match a customer's name.

$scope.watch in two different views

I am working on an Footballing angular JS webb app using Firebase as the backend. Below is the JS of one view:
databaseService.users.child(user.uid).once('value', function(usersSnapshot){
var users = usersSnapshot.val();
var selection = users.selection;
var team = users.teamname;
var week1 = users.week1;
var week2 = users.week2;
var week3 = users.week3;
var week4 = users.week4;
var week5 = users.week5;
var week6 = users.week6;
var week7 = users.week7;
var week8 = users.week8;
var week9 = users.week9;
var week10 = users.week10;
var week11 = users.week11;
var week12 = users.week12;
$scope.$watch('players', function (newValue, oldValue) {
$scope.totalPoints =(newValue, 'goals');
firebase.database().ref("users").child(user.uid).child("week12");.set($scope.totalPoints);
},true);
So basically the player weekly goals are watched and reflected in the view, after which the updated goal tally of a player is $set to a firebase node.
Below are the lines of code used to then update the the season goal tally:
var addition = week1 + week2 + week3 + week4 + week5 + week6 + week7 + week8 + week9 + week10 + week11 + week12;
var seasonTotal = firebase.database().ref("users").child(user.uid).child("total");
seasonTotal.set(addition);
on the Second view, I have the following code to show the value of firebase.database().ref("users").child(user.uid).child("total"); :
databaseService.users.child(user.uid).on('value', function(usersSnapshot){
var users = usersSnapshot.val();
var total = users.total;
$scope.total = total;
My Issue
My issue is that when i change the goal tally of a player in my firebase databse weekly node directly (As would be done each week), the goal update is reflected in the first view in real time. However, when I am on the second view, and I make the change in my database, the change update does not reflect in real time (the total goal tally for the weeks); the page needs to be refreshed or i need to return to the first view AND THEN go back to the second view.
I understand that this is because the code that adds up the weekly goals is in the first JS and not the JS for the second view. But is there a way to get the season total to update irrespective of the page the user is on?

AngularJS : Why the data is not displayed in view may I use $scope.apply?

I am getting data from service and display on view using ng-repeat .Actually I am getting event when user scroll to bottom mean when user reached to bottom I will do something.When It reached to bottom I am changing the contend of my array .I am getting the correct contend in ng-repeat array (display array) but it is not reflect on view why ? May I use $scope.apply() or $scope.digest()
Here is my code
http://plnkr.co/edit/XgOxJnPXZk4DneJonlKV?p=preview
Here I am changing the contend of my display array which is not reflect on view
if (container[0].offsetHeight + container[0].scrollTop >= container[0].scrollHeight) {
if(scope.var<scope.arrays.length)
scope.display=[];
var nextvar =++counter;
var increment=counter+1
console.log("nextvar:"+nextvar+"increment:"+increment)
scope.display=scope.arrays[nextvar].concat(scope.arrays[increment]);
console.log(scope.display)
}
As #Claies mentioned you should use apply(). Though the digest() would probably have worked as well.apply() calls digest() internally. He also mentioned that your variable that seems to be storing the page number gets reset to 0 each time you scroll. You should store that in a scope variable outside that handler.
I tried to fix with minimum change
http://plnkr.co/edit/izV3Dd7raviCt4j7C8wu?p=preview
.directive("scrollable", function() {
return function(scope, element, attrs) {
var container = angular.element(element);
container.bind("scroll", function(evt) {
console.log('scroll called'+container[0].scrollTop);
var counter = scope.page;
if (container[0].scrollTop <= 0) {
if (scope.var > 0)
scope.display = scope.arrays[--scope.var].concat(scope.arrays[scope.var+1]);
}
if (container[0].offsetHeight + container[0].scrollTop >= container[0].scrollHeight) {
if (scope.var < scope.arrays.length)
scope.display = [];
var nextvar = ++counter;
var increment = counter + 1
console.log("nextvar:" + nextvar + "increment:" + increment)
scope.display = scope.arrays[nextvar].concat(scope.arrays[increment]);
console.log(scope.display)
scope.page = counter;
}
scope.$apply();
});
};
})
generally I would have implemented this differently. For example by having a spinning wheel on the bottom of the list that when displayed you get the rest of data.
It is difficult to give you a full working plunker. Probably you should have multiple JSON files in the plunker, each containing the data for one page so that we can add the data to the bottom of the display list.
After you modify display array you just have to call scope.$apply() so that it runs the $digest cycle and updates the view. Also you need the initialize scope.var either in your controller or the directive and modify it conditionally.
I dont if this is what you want. I have modified the plunker take a look.
http://plnkr.co/edit/J89VDMQGIXvFnK86JUxx?p=preview

Firebase - Lazy Loading List of Data

I have a requirement where I want to display say the first 10 entries in a list and once the user scrolls down I would like to append the next 10 entries. I am currently using Angularfire and all the documentation specifies that I should not do array operations on a $FirebaseArray:
This array should not be directly manipulated. Methods like splice(), push(), pop(), and unshift() will cause the data to become out of sync with server.
So my options are to load the next 10 entries and:
Use $add(), which would write them to the server again (think this could cause some nasty recursion)
Use concat, in which case my data will get out of sync with the server
Get the list again but adjust the limit to be 20, which I think would cause all the data to be reloaded defeating the purpose of lazy loading.
Here is the code that initially loads the list (based on the Angularfire seed app):
var lastKey = null;
var firstKey = null;
$scope.messages = fbutil.syncArray(userMessages,{'limit':10});
$scope.messages.$loaded(function(data){
lastKey = data.$keyAt(data.length-1);
firstKey = data.$keyAt(0);
});
And here is the code that is triggered when the user scrolls down:
$document.on('scroll', function() {
if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
var newMessages = fbutil.syncArray(messagePath,{'limit':10,'startAt':lastKey});
newMessages.$loaded(function(data){
lastKey = data.$keyAt(data.length-1);
firstKey = data.$keyAt(0);
$scope.messages.concat(newMessages);// this is probably a bad idea
});
}
});
Based on Kato's comment the following is the best solution given the current API.
var limit= 10;
$scope.messages = fbutil.syncArray(messagePath,{'limit':limit});
And the scroll trigger
$document.on('scroll', function() {
if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
limit += 10;
$scope.messages = fbutil.syncArray(messagePath,{'limit':limit});
}
});

How to do service request with pagination inside ng-repeat in AngularJS

I have a list of items displayed with ng-repeat at my web app, to get the items I call a service (rest) with pagination enabled, at the moment I am able to display just the first page. Now I need to implement some mechanics to make futher calls to load page 2, 3 ... as soon as the user scroll to the end of the current page.
For example, if pages are 20 items long and I am at the first page and I scroll down till item number 20, app will call page 2 and the items array will be expanded with the new items.
To top it all, it would be also very nice if there is a "pre-load" area which is not yet visible but elements are already there, ready to be shown to provide a smooth navigation, similar to "PageAdaptar" in Android.
What the best approach to do this in angular-js?
Thank you !
That is what finally I've done
I am using jquery to detect when I am at 300 px or less close to the bottom, in that case I call onScrollBottomEvent() from my controller, notice that this function may be called n times during scroll if user is inside of the 300px margin and he keeps going down.
<script type="text/javascript">
var lastScrollTop = 0;
$(window).scroll(function(event) {
scrolled = $(window).scrollTop() + $(window).height();
scrollMax = $('#container').height() + 50;
if(scrolled >= (scrollMax-300)) {
angular.element('#container').scope().onScrollBottomEvent();
}
});
</script>
then onScrollBottomEvent() calls loadNextPage() using apply() [important!]
Inside loadNextPage I set the flag onLoadMoreRequested to true, because I just need to call just once in order to load the next page instead of calling on every pixel scroll
$scope.onScrollBottomEvent = function(){
$log.log("onScrollBottomEvent()");
$scope.$apply(loadNextPage);
}
function loadNextPage(){
$log.log("loadNextPage()");
// execute only if there is other request on fly
if (!$scope.onLoadMoreRequested){
$scope.onLoadMoreRequested = true;
$scope.appendNewItems($scope.search.data, $scope.lastLoadedPage + 1);
}
}
finally I call the method to invoke the service
$scope.appendNewItems = function(search, page){
$log.log("Loading items request for page " + page);
$scope.footerProgressVisible = true;
if ($scope.lastSearch != $scope.search.data){
page = 0; // if search has changed, set page to zero
}
srvItems.getItems(search, function(result, page){
$scope.footerProgressVisible = false;
if (result!=null){
$scope.items.push.apply($scope.items, result);
$scope.lastLoadedPage = page;
$scope.onLoadMoreRequested = false;
$scope.lastSearch = $scope.search.data;
}
},
$scope.currentCategoryId,
page);
};
The key line is
$scope.items.push.apply($scope.items, result);
which will expand my ng-repeat automatically

Resources