AngularJS and JSON returns undefined - angularjs

Hi I have got a data in LocalStorage as JSON string:
[
{"Date":"28/04/2016","Time":"08:00","Title":"Title 1"},
{"Date":"28/04/2016","Time":"08:30","Title":"Title 2"}
]
And my module.factory looks like:
module.factory('$schedule', function() {
var schedule = {};
var result = JSON.parse(localStorage.getItem('myAgenda'));
schedule.items = [{
title: result.Title,
date: result.Date,
time: result.Time
}];
return schedule;
});
When I am trying to get data it returns undefined. When I try to get a specific object like:
console.log(result[0].Title);
It works fine and shows only the first element. I guess I missing each definition but don't know how to do it. Please help me to get all results in my schedule.items.
And I am passing the result as items into:
module.controller('ScheduleController', function($scope, $schedule) {
$scope.items = $schedule.items;
});
Many thanks.

You are trying to access fields in an array without mentioning wich array element you want to access. If you want to enumerate all agenda entries and add them to your array, it should look something like this:
module.factory('$schedule', function () {
var schedule = [];
var result = JSON.parse(localStorage.getItem('myAgenda'));
result.forEach(function (date) {
schedule.push({
title: date.Title,
date: date.Date,
time: date.Time
})
})
return schedule;
});

You should use .map over array, also add missing } in your last element of array.
var schedule = [];
//assuming result returns an array.
schedule = result.map(function(value){
return {
title: value.Title,
date: value.Date,
time: value.Time
};
})

Not familiar with module.factory, but it looks like result is an array of objects and you're accessing it like a single object when creating schedule.items.
You might have to iterate over the array and create an item per object in result.

Related

Iterating through array of objects to group all data by date

I have my json file as below:
{
"components":{
"record1":
[
{
"date":1619038000,
"name":"Susan",
"status":"true"
},
{
"date":1419038000,
"name":"Vinay",
"status":"false"
},
{
"date":1419038000,
"name":"Ajay",
"status":"true"
}
],
"record2":[
{
"date":1419037000,
"name":"Soumya",
"status":"false"
},
{
"date":1619038000,
"name":"Savio",
"status":"true"
},
{
"date":1326439320,
"name":"Thereza",
"status":"false"
}
]
}
}
This is my js file:
var app = angular.module("myApp",[]);
app.controller("Control",function($scope,$http){
$http.get('myData.json').
success(function(data){
$scope.tableData = data.components;
});
});
I want to group data from both arrays and display them in such a way that data having similar dates are grouped together. Maybe if I have more record inside then how wud I do it.Please do help me in this. I want to group them as follows:
date name status 17th april Susan true
Soumya false 19th april Vinay false
Ajay true 20th april Thereza false
I am not sure I understood the question well, but this is how you can gather elements having the same date:
function group(inputs, groupClause) {
var g = {};
for (var key in inputs) {
for (var innerKey in inputs[key]) {
if (inputs[key][innerKey]) {
if (!g[inputs[key][innerKey][groupClause]]) g[inputs[key][innerKey][groupClause]] = [];
g[inputs[key][innerKey][groupClause]].push(inputs[key]);
}
}
}
return g;
}
You can call it like this:
var myGroup = group([myobject["components"]["record1"], myobject["components"]], "date");
If you do not know in advance how many records will be, then you can do something like this:
var input = [];
var index = 1;
while (myobject["components"]["record" + index]) {
input.push(myobject["components"]["record" + index]);
index++;
}
var myGroup = group(input, "date");
Have a look at angular-filter , You add that and you get a bunch of filters which includes groupBy too which can group contents of an array according to the index you specify .
A solution using lodash groupby. Let's say the object is stored in variable called obj. Then you can:
var arr = obj.components.record1.concat(obj.components.record2);
var a = _.groupBy(arr, function(n) {
return n.date;
});
Running this code with the object given in the question, will give something like:
Object { 1326439320: Array[1], 1419037000: Array[1], 1419038000: Array[2], 1619038000: Array[2] }
If you want to loop through one of the groups, just select it bey key:
a["1419038000"].forEach(x => console.log(x))
which will produce:
Object { date: 1419038000, name: "Vinay", status: "false" }
Object {
date: 1419038000, name: "Ajay", status: "true" }

Mongoose doesn't create subdocument from JSON array

I'm trying to write a JSON object that contains both first-level data along with arrays into MongoDB.
What happens instead is all first-level data is stored, but anything contained in an array isn't. When logging the data the server receives, I see the entire object, which leads me to believe there's something wrong with my Mongoose code.
So for example if I send something like this:
issueId: "test1",
issueTitle: "testtest",
rows: [
{order:1,data: [object]},
{order:2,data: [object]},
]
Only the following gets stored:
issueId: "test1",
issueTitle: "testtest",
lastUpdated: Date,
I have the following model for Mongo:
//model.js
var mongoose = require('mongoose');
var model = mongoose.Schema({
issueId : String,
issueTitle : String,
lastUpdated : {type: Date, default : Date.now},
rows : [{
order : Number,
data : [
{
title : String,
text : String,
link : String,
}
]
}]
});
module.exports = mongoose.model('Model', model);
And the routing code, where I believe the problem likely is:
//routes.js
const mongoose = require('mongoose');
const Model = require('./model.js');
...
app.post('/api/data/update', function(req, res) {
let theData = req.body.dataToInsert;
console.log(JSON.stringify(theData,null,4));
Model.findOneAndUpdate(
{issueId : theData.issueId},
{theData},
{upsert: true},
function(err,doc){
if(err) throw err;
console.log(doc);
});
});
As well, here's the part of the Angular controller storing the data. I don't think there's any problem here.
pushToServer = function() {
$http.post('/api/data/update',{
dataToInsert : $scope.dataObject,
}).then(function successCallback(res){
console.log("all good", JSON.stringify(res,null,3));
}, function errorCallback(res){
console.log("arg" + res);
});
}
Look at the first question in the mongoose FAQ:
http://mongoosejs.com/docs/faq.html
Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to use MongooseArray#set available in Mongoose >= 3.2.0.
// query the document you want to update
// set the individual indexes you want to update
// save the document
doc.array.set(3, 'changed');
doc.save();
EDIT
I think this would work to update all of the rows. I'd be interested to know if it does work.
let rowQueries = [];
theData.rows.forEach(row => {
let query = Model.findOneAndUpdate({
issueId: theData.issueId,
'row._id': row._id
}, {
$set: {
'row.$': row
}
});
rowQueries.push(query.exec());
});
Promise.all(rowQueries).then(updatedDocs => {
// updated
});

Elasticsearch query parse failure

Why does this ES multi-match query return a 400 error (bad request)?
"query": {
"multi_match": {
"query": searchTerms,
"fields": ["content", "title"],
"operator": "and"
}
},
size: 100,
from: 0,
highlight: {
fields: {
"title": {number_of_fragments: 0},
"content": {number_of_fragments: 10,fragment_size: 300}
}
}
}
I'm using this query in conjunction with AngularJS UI Bootstrap Typeahead code like this
uib-typeahead="query as query._source.ymme for query in getSuggestions($viewValue)" typeahead-on-select="search($item)"
This is my search() function
$scope.search = function() {
console.log($scope.searchTerms);
$scope.currentPage = 0;
$scope.results.documents = [];
$scope.isSearching = true;
return searchService.search($scope.searchTerms, $scope.currentPage).then(function(es_return) {
var totalItems = es_return.hits.total;
var totalTime = es_return.took;
var numPages = Math.ceil(es_return.hits.total / $scope.itemsPerPage);
$scope.results.pagination = [];
for (var i = 1; i <= 100; i++) {
if(totalItems > 0)
$scope.results.totalItems = totalItems;
$scope.results.queryTime = totalTime;
$scope.results.pagination = searchService.formatResults(es_return.hits.hits);
$scope.results.documents = $scope.results.pagination.slice($scope.currentPage, $scope.itemsPerPage);
}
}
),
function(error){
console.log('ERROR: ', error.message);
$scope.isSearching = false;
}
};
I'm not quite sure what is wrong? I'm thinking it has something to do with $scope, but I'm not sure. The query works when I use it Sense plugin for ES and it also works if I just type in a search term instead of selecting it from the autocomplete dropdown.
If it is $scope, what am I missing?
UPDATE
All shards failed for phase: [query_fetch]
org.elasticsearch.search.SearchParseException: [hugetestindex][0]: from[-1],size[-1]: Parse Failure [Failed to parse source [{"query":{"multi_match":{"query":{"_index":"hugetestindex","_type":"doc","_id":"57","_score":3.877801,"_source":{"ymme":"bourne supremacy"}},"fields":["content","title"],"operator":"and"}},"size":100,"from":0,"highlight":{"fields":{"title":{"number_of_fragments":0},"content":{"number_of_fragments":10,"fragment_size":300}}}}]]
UPDATE 2 Object {_index: "hugetestindex", _type: "doc", _id: "56", _score: 2.5276248, _source: Object}
I think that is the problem, instead of a search terms, its receiving "Object"....?
UPDATE 3So basically it goes like this,
[Object, Object, Object, Object, Object]
0: Object
_id: "229"
_index: "hugetestindex"
_score: 3.3071127
_source: Object
ymme: "bourne supremacy"
__proto__: Object
_type: "doc"
__proto__:
Object1:
Object2:
Object3:
Object4:
Object
length: 5
__proto__: Array[0]
where "bourne supremacy" is the value of the ymme field in the _source Object, the array at the top with the 5 objects is the es return, es_return.hits.hits - this last hits, is the array.
The way you deconstruct your object is by doing something like the following:
object.data.hits.hits._source.field_name;
The above is only a notation to get the value of a single field, you might need to do a loop for each of those values so maybe something like:
$scope.list = []
for hit in object.data.hits.hits {
$scope.list.push(hit._source.field);
}
console.log(list);
Then from your HTML you want to use this list by doing an ng-repeat with it or something similar to get each of the terms in the list.
<div ng-repeat="term in list">{{term}}</div>
If you can update your question with how your object looks and what data you want from it, I can update this answer to match it exactly.
UPDATE
To match your data structure, I'm assuming you want to extract each of the ymme values from those objects. You need to do the following:
<div ng-repeat="object in es_return.hits.hits">
{{object._source.ymme}}
</div>
Just make sure "es_return" is a $scope variable so you can access it as above or just do:
$scope.es_return = es_return;
In your Angular code

AngularJS: Trying to clean up an API Feed by processing $http response is not working

I have an API Feed of global variables to be used throughout an application. The raw feed looks like this:
[
{
id: "1",
var: "g_crop_year",
val: "2015"
},
{
id: "2",
var: "g_season",
val: "F"
}
]
To me, that is awkward to work with throughout an application and I would prefer it look like this:
[
{ g_crop_year: "2015" },
{ g_season: "F" }
]
I tried this:
$http.get('/globals')
.success(function(globals){
var simpleGlobals = [];
for(var g=0; g<globals.length;g++){
var glo = {
globals[g].var: globals[g].val
};
simpleGlobals.push(glo);
}
$scope.globals = simpleGlobals;
});
My thoughts were to loop through the returned data, create the structure I want and push to a new array which I assign to $scope. But I am wrong. I get a blank page and an unexpected token in the globals[g].var: globals[g].val line.
This will not work as you expect:
var glo = {
globals[g].var: globals[g].val
};
They key of the glo object is attempting be the literal text globals[g].var; change that, instead, to:
var glo = {};
glo[globals[g].var] = globals[g].val;
As a side note, you may want to assign to $rootScope or a Service to make these globals available to all of your controllers.
This is not the right approach to create your designated approach.
var glo = {
globals[g].var: globals[g].val
};
The string globals[g].var is actually being considered as the key rather than interpreting it as a value.
You should instead create a blank object first and then use the array annotation to assign a particular value to the key.
var glo = {};
glo[globals[g].var] = globals[g].val;

How to filter object from array by value and using the value to omit another array or objects?

I have a array, which has the bunch of object, i would like to filter the object by 'name' value, again i would like to omit those object from another array of object using underscore.
I know that we can do using earch, but i am not getting the proper approach to do this both..
any one help me to do this?
example :
incoming array:
var incomingArray = [
{"name":"apple"},
{"name":"orange"},
{"name":"dog"},
{"name":"cat"},
{"name":"egle"}
];
filter keys:
var omit = ['orange' ,'dog'];
//i need to check whether 'orange' or 'dog' are exist, if so..
var filtered = _.filter(incomingArray, function(obj, i){
return obj.name === omit[i]['name'];//this is wrong i need to loop again how?
});
var anotherArray = [
{"name":"apple"},
{"name":"orange"},
{"name":"dog"},
{"name":"cat"},
{"name":"egle"}
]
return only the array without the omit like this:
var outgoingArray = [
{"name":"apple"},
{"name":"cat"},
{"name":"egle"} ]
how we could achieve this with proper approach?
demo
You were nearly there! Use indexOf to check that the name does not belong in the omit array:
var filtered = _.filter(incomingArray, function(obj) {
return omit.indexOf(obj.name) == -1;
});

Resources