Angularjs polling API to check for empty array in JSON - javascript

Im trying to create a service that polls an API and checks to see if the response has an empty arrary. If it does, I want it to keep checking every second until the array from the response is filled. For instace if the array is empty the JSON will return:
{
choices: [ ]
}
To set this up I've created the service like so. The issue is that data.response.choices.length seems to be undefined and I'm not exacly sure how to check for the array being empty. The rest of the code seems to work fine. Ideas?
angular.module('help')
.factory('Poller', function($http, $timeout) {
var data = { response: {}, calls: 0 };
var poller = function() {
if (data.response.choices.length === 0) {
$http.get('menu.json').then(function(r) {
data.response = r.data;
data.calls++;
$timeout(poller, 1000);
});
console.log('success');
} else {
$http.get('menu.json').then(function(r) {
data.response = r.data;
});
console.log('damnit');
}
};
poller();
return {
data: data
};
});

data.response is set to an empty object, so the first time poller is called, data.response.choices is guaranteed to be undefined.
I think the code can be simplified to this...
angular.module('help')
.factory('Poller', function($http, $timeout) {
var data = { response: {}, calls: 0 };
var poller = function() {
$http.get('menu.json').then(function(r) {
data.response = r.data;
data.calls++;
if (r.data.choices.length === 0) {
$timeout(poller, 1000);
}
});
};
poller();
return {
data: data
};
});

You can use this:
<!-- Image Gallery -->
<div class="gallery" ng-show="product.images.length">

Related

AngularJS make a call to the database only after the user enters one character

I created an angular material autocomplete. Everything is working fine but now I am trying to modify the code and make a call to the database only after the user enter one character in the autocomplete box. The getEmployees function is making the http call to the database. I tried this but I am getting the error that seachText is undefined. Further on I am trying to pass the first letter from the autocomplete to the getEmployees. I created a project in Plunker: https://plnkr.co/edit/gLX5Tu0Jlvxh6T7HE6O3?p=preview
if(searchText != undefined || searchText != null)
{
getEmployees().then(function (users)
{
vm.employees = employees
})
}
in your code md-item-text="item.name" is there, but 'name' key is not there in your json.. use md-item-text="item.FirstName".. it will work
The code below is a bit rough, not DRY, but it essentially works so hopefully it may point you in the right direction
angular
.module('AutocompleteApp', ['ngMaterial'])
.controller('AutocompleteController', function($scope, $http, $filter) {
var vm = this;
// data for autocomplete
vm.getMatches = function(searchText) {
if (!vm.employees) {
getEmployees().then(function(employees) {
vm.employees = employees;
var term = searchText && searchText.toLowerCase();
if (!term) {
return [];
} else {
return $filter('filter')(vm.employees, term);
}
});
} else {
var term = searchText && searchText.toLowerCase();
if (!term) {
return [];
} else {
return $filter('filter')(vm.employees, term);
}
}
};
// how we get employee data
function getEmployees() {
return $http.get('employees.json').then(function(response) {
return response.data;
}, function failureCallback(response) {
reject("Error!");
});
}
});
https://plnkr.co/edit/QfHaZ6b3vFW57KeKBLhx?p=preview

When I use $scope.watch in angular, I have an issue in passing data

I use $scope.watch and set and get to pass one data from one controller to another. This works fine, but when I do this with different html files, data is not transferred in my first click. because browser is refreshed. But when I click go back arrow in chrome and set a value and clicked, I can get the value in my second page. How can I resolve this. Please tell me solution.
var data = {
Quantity: ''
};
return {
getQuantity: function() {
return data.Quantity;
},
setQuantity: function(quantity) {
data.Quantity = quantity;
}
};
.controller('DetailsCtrl', function($scope, $http, Data) {
$scope.quantity = '';
$scope.$watch('quantity', function(newValue50, oldValue50) {
if (newValue50 !== oldValue50)
Data.setQuantity(newValue50);
});
})
.controller('FifthCtrl', function($scope, $http, Data) {
$scope.$watch(function() {
return Data.getQuantity();
}, function(newValue50, oldValue50) {
if (newValue50 !== oldValue50)
$scope.quantity = newValue50;
});
})
If you want to store the value between different sessions in the browser you could add the quantity value to the local storage.
Here's an angularjs service/factory example
app.factory('Data', function () {
var data = {
Quantity: ''
};
return {
getQuantity: function () {
if (localStorage.getItem("data") === null) {
data.Quantity = 0;
} else {
var jsonData = localStorage.getItem('data');
data.Quantity = JSON.parse(jsonData);
}
return data.Quantity;
},
setQuantity: function (quantity) {
data.Quantity = quantity;
localStorage.setItem("data", JSON.stringify(data));
}
};
});
Note 1: You actually don't need the object 'data' in this case as you store the value in the storage but I let it stand as is.
Note 2: The localStorage can't store complext types such as objects and you need to make strings of them before you store them, thats why the JSON.stringify() is used.

Filtering list in controller doesn't work

I have application on AngularJs.
I have variable in scope, which is initialized with data from API. $scope.receivedRequests = CurrentUserData.incomeRequests();
Cause request to API takes some time, $scope.receivedRequests is empty at start.
$scope.receivedRequests I've used with ng-repeat
<div class="full-row" ng-repeat="row in receivedRequests | filterByStatus:[State.PENDING] | partition:3 track by $index">
This data is also filtered.
But when I tried to replace this filtering into controller, like
$scope.filterByStatus = function (statuses) {
return $filter('filterByStatus')($scope.receivedRequests, statuses);
};
$scope.pendingRequests = $scope.filterByStatus([State.PENDING]);
$scope.pendingRequests were always empty.
How can I filter data in the controller?
.filter('filterByStatus', function () {
return function(arr, statuses) {
if (!arr) { return; }
return arr.filter(function(value) {
return statuses.some(function(val) {
return value.status == val;
});
});
};
});
$scope.receivedRequests is just array of elements, that have string property status (alos id, date etc.) as example : status : "Pending"
In that case I would use promises and split the code like this.
Factory service
app.factory('myService', function($http){
return {
getRequests: function(){
return $http.get('http://someurl');
}
}
})
Controller
app.controller('myController', function(myService){
$scope.filteredArray = [];
myService.getRequests()
.then( function(data){
$scope.filteredArray = $scope.filterFunction(data);
})
$scope.filterFunction = function(array){
//function logic
//...
}
})
Notes:
The trick here is done by calling the filtering function inside the then() function. This way you are sure the data from the API is been already fetched and after that you can filter it.
I am not sure how your $scope.recievedRequests object look, can you try the below... why don't you send the State.pending value with an associated key for your array.
$scope.filterByStatus = function (statuses) {
return $filter('filterByStatus')($scope.receivedRequests, statuses);
};
$scope.pendingRequests = $scope.filterByStatus({key: State.PENDING})[0];

How can I display the data created?

I'm sending a data ...
....
// upload on file select or drop
$scope.upload = function (file, id) {
id = typeof id !== 'undefined' ? id : null;
Upload.base64DataUrl(file).then(function(base64){
//auth
var fbAuth = FirebaseURL.getAuth();
//Ref
var ref = FirebaseURL.child("users_photos");
ref.push({'image': base64,'removed': true, 'user_id': fbAuth.uid, 'dt_created':Firebase.ServerValue.TIMESTAMP ,'dt_updated':Firebase.ServerValue.TIMESTAMP}, function(error){
if (error) {
alert('Error');
} else {
var newID = ref.key();
//I would like display data insert here?
console.log(DATA RESULT INSERT);
}
});
});
I would like display data inserted.
It is possible to display the last inserted object without query by the key?
Use AngularFire for synchronized collections.
Create a query using limitToLast(1) to always sync the last inserted object.
angular.module('app', ['firebase'])
.constant('FirebaseUrl', '<my-firebase-app>')
.service('rootRef', ['FirebaseUrl', Firebase)
.factory('userItems', UserItems)
.controller('MyCtrl', MyController);
function UserItems($firebaseArray, rootRef) {
return function userItems(uid) {
var itemRef = rootRef.child('items');
var query = itemRef.orderyByChild('uid').equalTo(uid);
return $firebaseArray(query);
}
}
function MyController($scope, userItems, rootRef) {
$scope.items = userItems(rootRef.getAuth().uid);
$scope.addItem = function addItem(item) {
$scope.items.$add(item).then(function(ref) {
var record = $scope.items.$getRecord(ref.key());
// save the data to the other structure
});
};
}
See the section on Complex queries for more info.

Set factory variable from state

I am using factories to get feed data for different categories in wordpress using the Rest-API and I am wondering if I am making a complete mess of it.
I have around 13 different categories that I am making just a basic call to that look like this:
.factory('Articles1', function ($http) {
var articles1 = [];
storageKey = "articles1";
function _getCache() {
var cache = localStorage.getItem(storageKey );
if (cache)
articles = angular.fromJson(cache);
}
return {
all: function () {
return $http.get("http://www.example.com/wp-json/posts?filter[category_name]=category1").then(function (response) {
articles1 = response.data;
console.log(response.data);
return articles1;
});
},
get: function (articleId) {
if (!articles1.length)
_getCache();
for (var i = 0; i < articles1.length; i++) {
if (parseInt(articles1[i].ID) === parseInt(article1Id)) {
return articles1[i];
}
}
return null;
}
}
})
there is a separate call for each of the 13 categories to get articles.
Is there a way to set the [category_name] to a variable, possibly the state name or something to that I can just make 1 call to wordpress and the url will rely on what state the user has chosen? I have been trying to learn angular and from what I have seen I am sure there must be a more elegant way of doing something like this?
Inject the Angular $location provider and you will have access to every part of your current URL (you can also use it to listen to the state changes). Then just build the URL to Wordpress dynamically:
.factory('Articles1', function ($http, $location) {
// ...
return {
all: function () {
var currentCategory = $location.path().split('/')[1]; // Assuming the category is part of the path and at the second place
var wpUrl = 'http://www.example.com/wp-json/posts?filter[category_name]=' + currentCategory;
return $http.get(wpUrl).then(function (response) { // ...

Categories

Resources