How to check string in json array - angularjs

console.log($scope.filteredOffers);hi to all want to check string in json like that string coming form params now want to check in whole json and display only data which is related to that . Kindly check my code .. in other words want to display data according to the params which is coming form url (which is coming ).
.controller('mixCtrl', function($scope,$http,$stateParams) {
$http.get("http://tools.vcommission.com/api/coupons.php?apikey=e159f64e3dd49fddc3bb21dcda70f10c6670ea91aac30c7cb1d4ed37b20c45b8").then(function (response) {
$scope.myData = response.data;
$scope.offerName = ''; //set initially
$scope.selectedIndex = -1;
$scope.filteredOffers = [];
// $scope.link1 = [];
$scope.da = $stateParams.offer_name;
var a = $scope.da;
console.log(a);
$scope.filteredOffers = $scope.myData.filter(function(a) {
for (var i=0;i<$scope.myData.length;i++)
{
$link =$scope.myData[i].offer_name;
if (a==$link)
{
return a ;
console.log(a );
}
//console.log(a );
}
// return offer.offer_name == $scope.da;
console.log($scope.da);
});
});
/*
$scope.showData = function(offer_name, index) {
$scope.offerName = offer_name;
$scope.filteredOffers = $scope.myData.filter(function(offer) {
return offer.offer_name == $scope.offerName;
});
$scope.selectedIndex = index;
}*/
$scope.dealopen = function(a){
for (var i=0;i<$scope.myData.length;i++)
{
//console.log($scope.data[i].name);
$link=$scope.data[i].name;
console.log($link);
if ($link==$a)
{
$window.open($link,"_self","location=yes");
//console.log($a);
}
}
}
})
Html
<div ng-repeat="offer in filteredOffers">
<div class="couponCode">{{offer.coupon_code}}</div>
<div class="couponTitle">{{offer.coupon_title}}</div>
<div class="couponDescription">{{offer.coupon_Description}}</div>
</div>

You are use the Array.filter() function wrongly!
Before :
$scope.filteredOffers = $scope.myData.filter(function(a) {
for (var i=0;i<$scope.myData.length;i++)
{
$link =$scope.myData[i].offer_name;
if (a==$link)
{
return a ;
console.log(a );
}
//console.log(a );
}
// return offer.offer_name == $scope.da;
console.log($scope.da);
});
After (According to correct syntax) :
$scope.filteredOffers = $scope.myData.filter(function(a) {
if (check condition)
{
return true ;// when true is returned the json held in a gets pushed into the filteredOffers array
}
else{
return false;//when false is returned, the json held in 'a' is ignored and not pushed into the filteredOffers array
}
});
Array.filter's Doc Link
But there is something wrong with the logic that you have used. If you can tell me exactly what you are trying to do, I might be able to help you out.

If you are processing json and arrays frequently in your application, then it's better to integrate loadash or underscore in you application.
Add below code to your HTML before loading the controller file.
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
After looking the response of http://tools.vcommission.com/api/coupons.php?apikey=e159f64e3dd49fddc3bb21dcda70f10c6670ea91aac30c7cb1d4ed37b20c45b8, below code will give you the array that matches the offer_name.
$http.get("http://tools.vcommission.com/api/coupons.php?apikey=e159f64e3dd49fddc3bb21dcda70f10c6670ea91aac30c7cb1d4ed37b20c45b8").then(function (response) {
$scope.filteredOffers = [];
var offerName = $stateParams.offer_name;
$scope.filteredOffers = _.filter(response.data, ["offer_name",offerName]);
})

Related

dealing with an array of objects with promises

I am trying to make a node express app where I fetch data from different url's making a call to node-fetch to pull the body of some pages and other information about certain url endpoints. I want to then render a html table to display this data through an array of information. I am having trouble with the call to render the information as all the functions are asynchronous making it difficult to make sure all the promise calls have been resolved before making my call to render the page. I have been looking into using bluebird and other promise calls of .finally() and .all() but they don't seem to work on my data as it is not an array of promise calls, but an array of objects. Each object was 4 promise calls to fetch data relating to a column of my table all in one row. Is there a function or specific way to render the page after all promises are resolved?
var express = require('express');
var fetch = require('node-fetch');
fetch.Promise = require('bluebird');
var router = express.Router();
const client = require('../platform-support-tools');
function makeArray() {
var registry = client.getDirectory();
var data_arr = [];
for (var i = 0; i < registry.length; i++) {
var firstUp = 0;
for (var j = 0; i < registry[i]; j++) {
if (registry[i][j]['status'] == 'UP') {
firstUp = j;
break;
}
}
var object = registry[i][firstUp];
data_arr.push({
'name': object['app'],
'status': object['status'],
'swagUrl': object['homePageUrl'] + 'swagger-ui.html',
'swag': getSwag(object),
'version': getVersion(object['statusPageUrl']),
'timestamp': getTimestamp(object['statusPageUrl']),
'description': getDescription(object['healthCheckUrl'])
});
}
return data_arr;
}
function getSwag(object_in) {
var homeUrl = object_in['homePageUrl'];
if (homeUrl[homeUrl.length - 1] != '/'){
homeUrl += '/';
}
var datum = fetch(homeUrl + 'swagger-ui.html')
.then(function (res) {
return res.ok;
}).catch(function (err) {
return 'none';
});
return datum;
}
function getVersion(url_in) {
var version = fetch(url_in)
.then(function(res) {
return res.json();
}).then(function(body) {
return body['version'];
}).catch(function (error) {
return 'none';
});
return version;
}
function getTimestamp(url_in) {
var timestamp = fetch(url_in)
.then(function(res) {
return res.json();
}).then(function(body) {
return body['timestamp'];
}).then(function (res) {
return body['version'];
}).catch(function (error) {
return 'none';
});
return timestamp;
}
function getDescription(url_in) {
var des = fetch(url_in)
.then(function(res) {
return res.json();
}).then(function(body) {
return body['description'];
}).catch(function (error) {
return 'none';
});
return des;
}
/* GET home page. */
router.get('/', function (req, res, next) {
var data_arr = makeArray();
Promise.all(data_arr)
.then(function (response) {
//sorting by app name alphabetically
response.sort(function (a, b) {
return (a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0);
});
res.render('registry', {title: 'Service Registry', arr: response})
}).catch(function (err) {
console.log('There was an error loading the page: '+err);
});
});
To wait on all those promises, you will have to put them into an array so you can use Promise.all() on them. You can do that like this:
let promises = [];
for (item of data_arr) {
promises.push(item.swag);
promises.push(item.version);
promises.push(item.timestamp);
promises.push(item.description);
}
Promise.all(promises).then(function(results) {
// all promises done here
})
If you want the values from all those promises, back into the object that's a bit more work.
let promises = [];
for (item of data_arr) {
promises.push(item.swag);
promises.push(item.version);
promises.push(item.timestamp);
promises.push(item.description);
}
Promise.all(promises).then(function(results) {
// replace promises with their resolved values
let index = 0;
for (let i = 0; i < results.length; i += 4) {
data_arr[index].swag = results[i];
data_arr[index].version = results[i + 1];
data_arr[index].timestamp = results[i + 2];
data_arr[index].description = results[i + 3];
++index;
});
return data_arr;
}).then(function(data_arr) {
// process results here in the array of objects
});
If you had to do this more often that just this once, you could remove the hard coding of property names and could iterate all the properties, collect the property names that contain promises and automatically process just those.
And, here's a more general version that takes an array of objects where some properties on the objects are promises. This implementation modifies the promise properties on the objects in place (it does not copy the array of the objects).
function promiseAllProps(arrayOfObjects) {
let datum = [];
let promises = [];
arrayOfObjects.forEach(function(obj, index) {
Object.keys(obj).forEach(function(prop) {
let val = obj[prop];
// if it smells like a promise, lets track it
if (val && val.then) {
promises.push(val);
// and keep track of where it came from
datum.push({obj: obj, prop: prop});
}
});
});
return Promise.all(promises).then(function(results) {
// now put all the results back in original arrayOfObjects in place of the promises
// so now instead of promises, the actaul values are there
results.forEach(function(val, index) {
// get the info for this index
let info = datum[index];
// use that info to know which object and which property this value belongs to
info.obj[info.prop] = val;
});
// make resolved value be our original (now modified) array of objects
return arrayOfObjects;
});
}
You would use this like this:
// data_arr is array of objects where some properties are promises
promiseAllProps(data_arr).then(function(r) {
// r is a modified data_arr where all promises in the
// array of objects were replaced with their resolved values
}).catch(function(err) {
// handle error
});
Using the Bluebird promise library, you can make use of both Promise.map() and Promise.props() and the above function would simply be this:
function promiseAllProps(arrayOfObjects) {
return Promise.map(arrayOfObjects, function(obj) {
return Promise.props(obj);
});
}
Promise.props() iterates an object to find all properties that have promises as values and uses Promise.all() to await all those promises and it returns a new object with all the original properties, but the promises replaced by the resolved values. Since we have an array of objects, we use Promise.map() to iterate and await the whole array of those.

Angular template won't load. Even with $loaded. Data resolves after Load

Using AngularFire, Angular, Firebase.
I load a list of users from a Firebase Database. I use $loaded to ensure it waits until data loads.
I take this list, compare it against another firebase database of groups and push the results into two arrays.
Based on the console.logs the data sorts correctly. However, inside my template I get a blank page (I think this is because the page loads before the data is sorted).
Thoughts?
let userLoggedIn = AuthFactory.getUser();
var allUsersArray = $firebaseArray(ConnectFactory.fbUserDb);
var x = firebase.database().ref('groups');
var friendArr = [];
var notFriendArr = [];
allUsersArray.$loaded().then(function(){
angular.forEach(allUsersArray, function(user, i) {
var haveIAdded = x.child(userLoggedIn).child(allUsersArray[i].uid).once('value').then(function (snap) {
if (snap.val() !== null) {
return true;
} else {
return false;
}
});
var haveTheyAdded = x.child(allUsersArray[i].uid).child(userLoggedIn).once('value').then(function (snap) {
if (snap.val() !== null) {
return true;
} else {
return false;
}
});
Promise.all([haveIAdded, haveTheyAdded]).then(function([you, they]) {
if (you && they) {
console.log('We Are Friends', allUsersArray[i]);
friendArr.push(allUsersArray[i]);
} else {
console.log('not a friend ', allUsersArray[i]);
notFriendArr.push(allUsersArray[i]);
}
});
});
$scope.friendList = friendArr;
$scope.notFriendList = notFriendArr;
});
Alright, this time I tried to actually read the question before attempting to answer. ;-)
When you set your $scope.friendList and $scope.notFriendList within the $loaded promise, your Promise.all may (and most likely) havn't resolved yet when those are called, since angular.forEach doesn't wait for the promises to finish before moving on to the next statement in the function. So you'll have to build an array of promises and wait for them all to resolve outside of the loop before attempting to set your $scope variables.
allUsersArray.$loaded().then(function(){
var promises = [];
var friendArr = [];
var notFriendArr = [];
angular.forEach(allUsersArray, function(user, i) {
... // Same as before
promises.push(
Promise.all([haveIAdded, haveTheyAdded]).then(function([you, they]) {
if (you && they) {
console.log('We Are Friends', allUsersArray[i]);
friendArr.push(allUsersArray[i]);
} else {
console.log('not a friend ', allUsersArray[i]);
notFriendArr.push(allUsersArray[i]);
}
})
);
});
Promise.all(promises).then(function(){
$scope.friendList = friendArr;
$scope.notFriendList = notFriendArr;
});
});

How to push a JSON object to an array in AngularJS

I need to push a JSON object to AngularJS and need to check before if the value for one of the objects exist. I need to overwrite the data.
$scope.setData = function(survey, choice) {
keepAllData.push({
'surveyId': survey.id,
'choiceId': choice.id
});
console.log(keepAllData);
toArray(keepAllData);
alert(JSON.stringify(toArray(keepAllData)));
$scope.keepAllDatas.push({
'surveyId': survey.id,
'choiceId': choice.id
});
var items = ($filter('filter')(keepAllDatas, {
surveyId: survey.id
}));
}
function toArray(obj) {
var result = [];
for (var prop in obj) {
var value = obj[prop];
console.log(prop);
if (typeof value === 'object') {
result.push(toArray(value));
console.log(result);
} else {
result.push(value);
console.log(result);
}
}
return result;
}
If the survey id exists in keepalldata, I need to change the recent value with choiceid. Is it possible to do with AngularJS?
Try with this: Before pushing data you have to check if the survey id exists or not. If it exists you have to update choice with the corresponding survey id, otherwise you can push directly.
$scope.setData = function(survey, choice) {
var item = $filter('filter')(keepAllData, {
surveyId: survey.id
});
if (!item.length) {
keepAllData.push({
'surveyId': survey.id,
'choiceId': choice.id
});
} else {
item[0].choiceId = choice.id;
}
console.log(keepAllData);
}
Demo
$scope.keepAllDatas = [];
$scope.setData = function(survey, choice) {
if($scope.keepAllDatas.length == 0) {
$scope.keepAllDatas.push({'surveyId':survey.id,'choiceId':choice.id});
}
else {
var items = ($filter('filter')( $scope.keepAllDatas, {surveyId: survey.id }));
for (var i = items.length - 1; i >= 0; i--) {
// alert(items[i].surveyId);
if(items[i].surveyId == survey.id) {
console.log($scope.keepAllDatas.indexOf(survey.id));
$scope.keepAllDatas.splice($scope.keepAllDatas.indexOf(survey.id),1);
console.log("Removed data")
}
}
$scope.keepAllDatas.push({'surveyId':survey.id, 'choiceId':choice.id});
console.log( $scope.keepAllDatas)
// alert(items[0].surveyId);
}
}

Prevent multiple submits in angularjs

I'm looking for a AngularJS-based way to prevent multiple submits per task.
I don't need buttons to be disabled after submission or close the form and wait for the task to be completed. Instead, I need requests to be unique.
To be more detailed, I need $http.get and $http.post stop sending multiple same requests.
Any Ideas?
According to this article, you can use provider decorator.
NOTE: this approach is based on angular-api
https://gist.github.com/adambuczynski/354364e2a58786e2be71
UPDATE
I've changed a little part in your suggested solution, because returned promises have lost .success and .error and .then.
Just use this edited code to have all of those functions working:
.config(["$provide", function ($provide) {
$provide.decorator('$http', function ($delegate, $q) {
var pendingRequests = {};
var $http = $delegate;
function hash(str) {
var h = 0;
var strlen = str.length;
if (strlen === 0) {
return h;
}
for (var i = 0, n; i < strlen; ++i) {
n = str.charCodeAt(i);
h = ((h << 5) - h) + n;
h = h & h;
}
return h >>> 0;
}
function getRequestIdentifier(config) {
var str = config.method + config.url;
if (config.data && typeof config.data === 'object') {
str += angular.toJson(config.data);
}
return hash(str);
}
var $duplicateRequestsFilter = function (config) {
if (config.ignoreDuplicateRequest) {
return $http(config);
}
var identifier = getRequestIdentifier(config);
if (pendingRequests[identifier]) {
if (config.rejectDuplicateRequest) {
return $q.reject({
data: '',
headers: {},
status: config.rejectDuplicateStatusCode || 400,
config: config
});
}
return pendingRequests[identifier];
}
pendingRequests[identifier] = $http(config);
$http(config).finally(function () {
delete pendingRequests[identifier];
});
return pendingRequests[identifier];
};
Object.keys($http).filter(function (key) {
return (typeof $http[key] === 'function');
}).forEach(function (key) {
$duplicateRequestsFilter[key] = $http[key];
});
return $duplicateRequestsFilter;
})
}])
It could be a performance issue but following idea could solve your problem.
Store the each request URL and DATA as key value pair on a variable. URL should be KEY. For Same URL multiple submission can be stored in a Array.
Then for any new call check the URL if it present in your stored object, then compare the data with each object thorughly (deep check, it is costly though).
If any exact match found then stop the processing. As same request came.
Other wise proceed and don't forget to store this data also.
But it is costly since need to check the data which could be havy.
Note: At the time of storing the data you could convert it to JSON String so it will be easier to compare between String.
here is the Code Algo
YourService.call(url, params) {
var Str1 = JSON.stringify(params);
if(StoredObj[url]) {
for each (StoredObj[url] as Str){
if(Str === Str1) {
return;
}
}
}
else {
StoredObj[url] = []; //new Array
}
StoredObj[url].push(Str1);
Call $http then;
}

checkbox filter for json array in Angularjs

I have create a filter but this filter is not working with array inside array.
'http://plnkr.co/edit/oygy79j3xyoGJmiPHm4g?p=info'
Above plkr link is working demo.
app.filter('checkboxFilter', function($parse) {
var cache = { //create an cache in the closure
result: [],
checkboxData: {}
};
function prepareGroups(checkboxData) {
var groupedSelections = {};
Object.keys(checkboxData).forEach(function(prop) {
//console.log(prop);
if (!checkboxData[prop]) {
return;
} //no need to create a function
var ar = prop.split('=');
//console.log("ar is - "+ar);
if (ar[1] === 'true') {
ar[1] = true;
} //catch booleans
if (ar[1] === 'false') {
ar[1] = false;
} //catch booleans
/* replacing 0 with true for show all offers */
if(ar[0]=='SplOfferAvailable.text'){
ar[1]='true';
}else{
}
//make sure the selection is there!
groupedSelections[ar[0]] = groupedSelections[ar[0]] || [];
//at the value to the group.
groupedSelections[ar[0]].push(ar[1]);
});
return groupedSelections;
}
function prepareChecks(checkboxData) {
var groupedSelections = prepareGroups(checkboxData);
var checks = [];
//console.log(groupedSelections);
Object.keys(groupedSelections).forEach(function(group) {
//console.log("groupedSelections- "+groupedSelections);
//console.log("group- "+group);
var needToInclude = function(item) {
//console.log("item- "+item);
// use the angular parser to get the data for the comparson out.
var itemValue = $parse(group)(item);
var valueArr = groupedSelections[group];
//console.log("valueArr- "+valueArr);
function checkValue(value) { //helper function
return value == itemValue;
}
//check if one of the values is included.
return valueArr.some(checkValue);
};
checks.push(needToInclude); //store the function for later use
});
return checks;
}
return function(input, checkboxData, purgeCache) {
if (!purgeCache) { //can I return a previous 'run'?
// is the request the same as before, and is there an result already?
if (angular.equals(checkboxData, cache.checkboxData) && cache.result.length) {
return cache.result; //Done!
}
}
cache.checkboxData = angular.copy(checkboxData);
var result = []; // this holds the results
//prepare the checking functions just once.
var checks = prepareChecks(checkboxData);
input.every(function(item) {
if (checks.every(function(check) {
return check(item);
})) {
result.push(item);
}
return result.length < 10000000; //max out at 100 results!
});
cache.result = result; //store in chache
return result;
};
});
above code is for check box filter.
when i click on checkbox called "Availability" it does not filter the result.
Please help me out.
Thanks.
I think that the way you are navigating through json is wrong because if you put in this way it works
"Location": "Riyadh",
"AvlStatus": "AVAILABLE"
"Rooms": {.....
You have to go in some way through Rooms and right now I think you're not doing that

Resources