I have a set of data within a users profile which holds the UID of all the posts they have liked. I am using a data snapshot to show these images within the users profile, but I would like to load it lazy or use ionic infinite scroll to load more items as the user scrolls.
I tried by making two duplicate snap shots. First one intialises the feed upon the page loading, and then I wanted the second one to load by using ionic infinite scroller.
But it doesn't work.
Does anyone know of a better way to do this?
service.js
getWardrobeFeed: function(){
var defered = $q.defer();
var user = User.getLoggedInUser();
var wardrobeKeyRef = new Firebase(FIREBASE_URL + '/userProfile/' + user.uid + '/wardrobe');
wardrobeKeyRef.orderByKey().limitToLast(2).on('child_added', function (snap) {
var imageId = snap.key();
userImageRef.child(imageId).on('value', function (snap) {
$timeout(function () {
if (snap.val() === null) {
delete userWardrobeFeed[imageId];
} else {
userWardrobeFeed[imageId] = snap.val();
}
});
});
});
wardrobeKeyRef.orderByKey().limitToLast(2).on('child_removed', function (snap) {
var imageId = snap.key();
$timeout(function () {
delete userWardrobeFeed[imageId];
});
});
defered.resolve(userWardrobeFeed);
return defered.promise;
},
getWardrobeItems: function(){
var defered = $q.defer();
var user = User.getLoggedInUser();
var wardrobeKeyRef = new Firebase(FIREBASE_URL + '/userProfile/' + user.uid + '/wardrobe');
wardrobeKeyRef.orderByKey().limitToFirst(2).on('child_added', function (snap) {
var imageId = snap.key();
userImageRef.child(imageId).on('value', function (snap) {
$timeout(function () {
if (snap.val() === null) {
delete userWardrobe[imageId];
} else {
userWardrobe[imageId] = snap.val();
}
});
});
});
wardrobeKeyRef.orderByKey().on('child_removed', function (snap) {
var imageId = snap.key();
$timeout(function () {
delete userWardrobe[imageId];
});
});
defered.resolve(userWardrobe);
return defered.promise;
},
controller.js
$scope.userWardrobe = [];
Service.getWardrobeFeed().then(function(items){
$scope.userWardrobe = items;
});
$scope.loadMore = function() {
Service.getWardrobeItems().then(function(items){
$scope.userWardrobe = $scope.userWardrobe.concat(items);
$scope.$broadcast('scroll.infiniteScrollComplete');
});
};
Related
I have code like this
(function (app) {
app.controller('productListController', productListController)
productListController.$inject = ['$scope', 'apiService', 'notificationService', '$ngBootbox', '$filter'];
function productListController($scope, apiService, notificationService, $ngBootbox, $filter) {
$scope.products = [];
$scope.page = 0;
$scope.pagesCount = 0;
$scope.getProducts = getProducts;
$scope.keyword = '';
$scope.search = search;
$scope.deleteProduct = deleteProduct;
$scope.selectAll = selectAll;
$scope.deleteMultiple = deleteMultiple;
function deleteMultiple() {
var listId = [];
$.each($scope.selected, function (i, item) {
listId.push(item.ID);
});
var config = {
params: {
checkedProducts: JSON.stringify(listId)
}
}
apiService.del('/api/product/deletemulti', config, function (result) {
notificationService.displaySuccess('Deleted successfully ' + result.data + 'record(s).');
search();
}, function (error) {
notificationService.displayError('Can not delete product.');
});
}
$scope.isAll = false;
function selectAll() {
if ($scope.isAll === false) {
angular.forEach($scope.products, function (item) {
item.checked = true;
});
$scope.isAll = true;
} else {
angular.forEach($scope.products, function (item) {
item.checked = false;
});
$scope.isAll = false;
}
}
$scope.$watch("products", function (n, o) {
var checked = $filter("filter")(n, { checked: true });
if (checked.length) {
$scope.selected = checked;
$('#btnDelete').removeAttr('disabled');
} else {
$('#btnDelete').attr('disabled', 'disabled');
}
}, true);
function deleteProduct(id) {
$ngBootbox.confirm('Are you sure to detele?').then(function () {
var config = {
params: {
id: id
}
}
apiService.del('/api/product/delete', config, function () {
notificationService.displaySuccess('The product hase been deleted successfully!');
search();
}, function () {
notificationService.displayError('Can not delete product');
})
});
}
function search() {
getProducts();
}
function getProducts(page) {
page = page || 0;
var config = {
params: {
keyword: $scope.keyword,
page: page,
pageSize: 20
}
}
apiService.get('/api/product/getall', config, function (result) {
if (result.data.TotalCount == 0) {
notificationService.displayWarning('Can not find any record.');
}
$scope.products = result.data.Items;
$scope.page = result.data.Page;
$scope.pagesCount = result.data.TotalPages;
$scope.totalCount = result.data.TotalCount;
}, function () {
console.log('Load product failed.');
});
}
$scope.getProducts();
}
})(angular.module('THTCMS.products'));
So my problem is when i loading data the application take me some time to load data.
I need load data as soon as
Is the any solution for this?
Since you are loading data via api call, there will be a delay. To handle this delay, you should display a loading screen. Once the data is loaded, the loading screen gets hidden and your main screen is visible. You can achieve this using $http interceptors.
See : Showing Spinner GIF during $http request in angular
The api-call is almost certainly causing the delay. Data may be received slowly via the api-call so you could display any sort of loading text/image to notify the use that the data is being loaded.
If u want the data ready at the time when controller inits, u can add a resolve param and pass the api call as a $promise in the route configuration for this route.
I am using promises in my controller, and most of the times it works well. But sometimes it just loads forever and the WordPress.getAllCategories() function does not even get called.
This is my controller:
var mod = angular.module('app.controllers.home', []);
mod.controller('HomeCtrl', function ($scope, $q, $sce, $ionicPlatform, WordPress, Loading) {
console.log('HomeCtrl init');
$scope.$on('$ionicView.enter', function () {
Loading.show();
WordPress.getAllCategories()
.then(function (cats) {
console.info(angular.toJson(cats));
console.info('cats ^');
$q.all(cats.data.map(function (cat) {
var d = $q.defer();
console.error(cat.name);
WordPress.getLatestPostOfCategory(cat.id)
.then(function (post) {
console.debug(post.data.title.rendered);
WordPress.getMediaById(post.data.featured_media)
.then(function (media) {
console.log(media.data.source_url);
cat.firstPost = {};
cat.firstPost.id = post.data.id;
cat.firstPost.title = post.data.title.rendered;
cat.firstPost.content = post.data.content.rendered;
if (cat.firstPost.title.length > 50) {
cat.firstPost.title = cat.firstPost.title + '...';
}
if (cat.firstPost.content.length > 70) {
cat.firstPost.content = cat.firstPost.content.substr(0, 60) + '...';
}
cat.firstPost.thumbnail = media.data.source_url;
d.resolve(cat);
}, function (err) {
console.error(angular.toJson(err));
});
});
return d.promise;
})).then(function (cats) {
console.log('Loaded all articles and for main page.');
$scope.homeCategories = cats;
Loading.hide();
});
});
});
});
Is there anything wrong in my controller?
P.S. I also debug all the WordPress service functions and they work just fine, and provide the needed data.
EDIT:
Sometimes when it loads forever, I see the console.error(cat.name); debug message only logs 3 messages. But still proceeds to the next function...
This is how I solved it, by Bergi's advice.
Source for help: Promise anti pattern by Gorgi Kosev (bluebird)
var categories = [];
function sort() {
return WordPress.getAllCategories()
.then(function (cats) {
console.log('thens');
return $q.all(cats.data.map(function (cat) {
console.info('cat: ' + cat.name);
var category = {};
category.name = cat.name;
return WordPress.getLatestPostOfCategory(cat.id)
.then(function (post) {
var post = post.data;
category.post = {};
category.post.id = post.id;
category.post.title = post.title.rendered;
category.post.content = post.content.rendered;
console.log('ID: ' + category.post.id + ', title: ' + category.post.title);
return WordPress.getMediaById(post.featured_media);
}).then(function (media) {
category.post.thumbnail = media.data.source_url;
categories.push(category);
console.log('Pushed category "' + category.name + '"');
});
}));
}, function (err) {
console.error('ERR1');
console.error(angular.toJson(err));
});
}
sort()
.then(function () {
console.info('LOADED ALL CATEGORIES');
$scope.categories = categories;
}, function (err) {
console.error('err:' + angular.toJson(err));
});
When i check all lists in table, and press delete button, A DELETE SERVICE will be called.(Using AngularJS)
Problem is, i am using a loop, and on successful delete and unsuccessful delete, i am getting alert multiple times.(No. of selection times)
And its not working properly, if place it out of loop because its Async Task.
Here is the code,
This is a controller which initiates a service.
$scope.confirmAction = function() {
var costsToDelete = [];
angular.forEach($scope.objects, function(cost) {
if (cost.selected == true) {
costsToDelete.push(cost);
}
});
$scope.deleted = true;
//need to put confirmation dialog here.
//URL: specific to timesheet deletion. it will be prefixed with constant url
var delRequestUrl = URLs.costsUrl + '/';
deleteService.deleteRecord($scope.objects, costsToDelete, delRequestUrl);
};
This is a service.
.service('deleteService', ['dataService', 'Constant.urls', 'Constants','$q','alerts',function(dataService, URLs, Constants, $q, alerts) {
var deleteService = {};
deleteService.deleteRecord = function(records, listOfRecordsToDelete, url) {
while (listOfRecordsToDelete.length > 0) {
var recordToBeDeleted = listOfRecordsToDelete.pop();
var index = listOfRecordsToDelete.indexOf(recordToBeDeleted);
var delRequestUrl = url + recordToBeDeleted.id;
var result = dataService.deleteObject(delRequestUrl);
result.success(function(data) {
Alert('success');
records.splice(index, 1);
});
result.error(function(data, status, headers, config) {
dataService.handleError(status,data);
Alert('error');
});
}
};
return deleteService; }])
I need a result like: Alert should display only once.
If all items are successfully deleted, then success or failure message.
Why dont you just create a boolean bit var status= false;//default value to true inside success callback handler and false inside error callback handler,
so once all calls are complete based on this bit you can alert success or failure
Angular JS Code:
.service('deleteService', ['dataService', 'Constant.urls', 'Constants','$q','alerts',function(dataService, URLs, Constants, $q, alerts) {
var statusBit = false; // status tracker
var deleteService = {};
deleteService.deleteRecord = function(records, listOfRecordsToDelete, url) {
while (listOfRecordsToDelete.length > 0) {
var recordToBeDeleted = listOfRecordsToDelete.pop();
var index = listOfRecordsToDelete.indexOf(recordToBeDeleted);
var delRequestUrl = url + recordToBeDeleted.id;
var result = dataService.deleteObject(delRequestUrl);
result.success(function(data) {
// Alert('success');
statusBit = true;
records.splice(index, 1);
});
result.error(function(data, status, headers, config) {
dataService.handleError(status,data);
//Alert('error');
statusBit = false;
});
if(statusBit){
Alert('success'); //console.log('successfully deleted');
}
else {
Alert('error'); // console.log('error while deleting');
}
};
return deleteService; }])
.service('deleteService', ['dataService', 'Constant.urls', 'Constants','$q','alerts',function(dataService, URLs, Constants, $q, alerts) {
var deleteService = {};
deleteService.deleteRecord = function(records, listOfRecordsToDelete, url) {
var overallResult = true;
while (listOfRecordsToDelete.length > 0) {
var recordToBeDeleted = listOfRecordsToDelete.pop();
var index = listOfRecordsToDelete.indexOf(recordToBeDeleted);
var delRequestUrl = url + recordToBeDeleted.id;
var result = dataService.deleteObject(delRequestUrl);
result.success(function(data) {
records.splice(index, 1);
});
result.error(function(data, status, headers, config) {
dataService.handleError(status,data);
overallResult = false ;
});
}
};
return deleteService; }])
I'm running a protractor tests and filling in a form with dropdowns. How can I ensure that each dropdown has a promise that is resolved before moving onto the next one? Right now I'm using sleeps and know that can't be the right way.
Describe('Filling site utility form', function() {
beforeEach(function(){
var input_monthly = by.linkText('Input Monthly');
browser.wait(function() {
return browser.isElementPresent(input_monthly);
});
var field1 = element(by.id('field1'));
Test.dropdown(field1, 1);
var field2 = element(by.id('field2'));
Test.dropdown(field2, 1);
});
My dropdown function is:
dropdown = function(element, index, milliseconds) {
element.findElements(by.tagName('option'))
.then(function(options) {
options[index].click();
});
if (typeof milliseconds !== 'undefined') {
browser.sleep(milliseconds);
}
}
Not 100% sure what you mean but I suspect what you're interested in is this:
describe('Filling site utility form', function() {
beforeEach(function(){
var input_monthly = by.linkText('Input Monthly');
browser.wait(function() {
return browser.isElementPresent(input_monthly);
});
var promise1 = element(by.id('field1')).all(by.tagName('option')).get(1).click();
var promise2 = element(by.id('field2')).all(by.tagName('option')).get(1).click();
protractor.promise.all([promise1, promise2]).then(function() {
//what do you want to do next?
});
});
});
I have a service that handles "episodes": creating, deleting and updating them. It looks like this:
app.service('Episode', ['$firebase', 'FIREBASE_URL', function($firebase, FIREBASE_URL) {
var ref = new Firebase(FIREBASE_URL);
var episodes = $firebase(ref);
return {
all: episodes,
create: function(episode) {
location.reload();
//Add to firebase db
return episodes.$add(episode);
},
delete: function(episodeId) {
location.reload();
return episodes.$remove(episodeId);
},
update: function(episode) {
location.reload();
return episodes.$save(episode);
}
};
}]);
Inside my controller:
app.controller('AdminCtrl', ['$scope', 'Episode', function ($scope, Episode) {
$scope.episodes = Episode.all;
$scope.createEpisode = function(){
Episode.create($scope.episode).then(function(data){
$scope.episode.name = '';
$scope.episode.title = '';
$scope.episode.description = '';
$scope.episode.time = '';
$scope.episode.img = '';
});
};
$scope.deleteEpisode = function(episodeId){
if(confirm('Are you sure you want to delete this episode?') === true) {
Episode.delete(episodeId).then(function(data){
console.log('Episode successfully deleted!');
});
}
};
$scope.updateEpisode = function(episode) {
Episode.update($scope.episode).then(function(data) {
console.log('Episode successfully updated.');
});
};
The only example of uploading images to Firebase from AngularJS I've seen online is this: https://github.com/firebase/firepano
How am I able to incorporate this into an object based addition/update instead of finding it's index/link?