sub array and push data - javascript

hello I am trying to create a dynamic array, but I am having problems, I have an onclick event to create invoice so when clicked is launched and I have it
var $boletos=new Array();
function onclick(value){
if($invoice.length==0){
$invoice.push({"items":{}});
$invoice[0].items[0]={"ID":this.person.ID,"other":value};
}else{
//here i do a "for" to create new invoice index, or new item
....
}
}
the result I want is something like
Invoice{
0:{ items{
0:{ ID:"123",other:"xxx"}
1:{ ID:"234",other:"xxx"}
2:{ ID:"233",other:"xxx"}
}
}
1:{ items{
0:{ ID:"1323",other:"yyy"}
1:{ ID:"1323",other:"xyyxx"}
2:{ ID:"1213",other:"yyyy"}
}
}
2:{ items{
0:{ ID:"12323",other:"zz"}
1:{ ID:"1223",other:"zz"}
2:{ ID:"1123",other:"zz"}
}
}
}
but i can do only an object, i can't call a push event, and is because is an object, and not an array, so maybe I need to do something like
$invoice[0].items[0].push({"ID":this.person.ID,"other":value}); please help me

I don't entirely understand the logic you're using here, but basically you should be using push() to add new items to the array, and not numeric indices. The items property should also be an array, not an object:
var $boletos = [];
function onclick(value){
if($boletos.length === 0 || shouldStartANewInvoice) {
$boletos.push({ items: [] });
}
$boletos[$boletos.length - 1].items.push({
ID: this.person.ID,
other:value
});
}

Just to add context and example to #JLRishe's answer.
There are really 2 ways you could do this depending on your use case for the Invoice. If I were submitting it server side in C#, for example, I would structure it more like an object (#2). Otherwise, the array approach works just fine (#1).
As he suggested where Items is an array: http://jsfiddle.net/nv76sd9s/1/
An alternative is to have Items be an object with the ID as the key and the value as the value: http://jsfiddle.net/nv76sd9s/3/
The difference here is the structure of the final object and how you plan to use it. In my #2 link, the object is more structured. It also affects how you iterate through them. Example:
var items = Invoice.Items;
for (k in items) {
var item = items[k];
for (k in item) {
console.log(k +': '+item[k]);
}
}

Related

How to get an array from an array in Meteor.js

everyone. I would like the students who enroll a subject are shown in a table when this subject is selected in a dropdown list. The ID of these students is stored in an array. The problem is that this ID array retrieved from the document looks kind of strange. seem like there is an array in an array.
Like this shown in the console:
shown in console
{enrollment: Array(2)}
enrollment: Array(2)
0: "b1602231"
1: "B1560124"
length: 2
__proto__: Array(0)
__proto__: Object
And it throwed an error: Exception in template helper: Error: $in needs an array
So how could I solve this? I would really appreciate it if someone can give me some idea.
Below is the event handler and helper.
Template.subject.events({
‘change #dropdown’: function(event, template) {
var selectedValue = $(event.target).val();
var array = subject.findOne( { subjectCode:selectedValue }, { fields:{ _id:0, enrollment:1 } } );
Session.set(‘studentEnrolled’,array);
}
});
Template.student.helpers({
student: function() {
var listOfStudent = Session.get( ‘studentEnrolled’ );
return student.find( { studentID: { $in:listOfStudent } } );
}
});
//HTML
<template name="student">
{{#each student}}
<tr>
<td>{{name}}</td>
</tr>
{{/each}}
</template>
Copying my answer from the forums:
First of all, you are taking the whole subject document (and after the first answer, wrapping that array into another array) here:
Session.set('studentEnrolled',[array]);
Which means when you search here:
return student.find({studentID:{$in:listOfStudent}});
You are passing an array with a document in it, instead of the enrollments array.
What you want to do is store the enrollments in the session:
Session.set('studentEnrolled', array.enrollments);
I'd also recommend renaming the variable array since it's not an array, and that probably contributed to your confusion
Find get one records from data. u can convert in array using [data]
var array = subject.findOne({subjectCode:selectedValue}, {fields:{_id:0, enrollment:1}});
Session.set(‘studentEnrolled’,[array]);
}
// For async update
More: https://blog.meteor.com/using-promises-and-async-await-in-meteor-8f6f4a04f998
Template.hello.onCreated(function helloOnCreated() {
this.list = new ReactiveVar([]);
Meteor.call('getHobbits', (error, result) => {
this.list.set(result);
});
});
Template.hello.helpers({
hobbits() {
return Template.instance().list.get();
},
});

parsing Objects in a loop in javascript

I have a string which I get from an api call and then I parse it into an object using JSON.parse(meetResponse)
meetResponse = {
"returncode":"SUCCESS",
"meetingName":"bbb meeting",
"meetingID":"712",
"createTime":"1457969919738",
"createDate":"Mon Mar 14 11:38:39 EDT 2016",
"voiceBridge":"35014",
"dialNumber":"613-555-1234",
"attendeePW":"PDmAJD4n",
"moderatorPW":"mpassword",
"running":"true",
"duration":"0",
"hasUserJoined":"true",
"recording":"true",
"hasBeenForciblyEnded":"false",
"startTime":"1457969919743",
"endTime":"0","participantCount":"2",
"maxUsers":"20",
"moderatorCount":"2",
"attendees":{
"attendee":[
{
"userID":"10005655",
"fullName":"Snedden Gonsalves",
"role":"MODERATOR",
"customdata":{}
},{
"userID":"10005656",
"fullName":"SneddenReg Gonsalves",
"role":"MODERATOR",
"customdata":{}
}
]
},
"metadata":{},
"messageKey":{},
"message":{}
}
I want to parse 'attendee' under 'attendees' to see who is present
The logic I use right now is :
//check if current user is already present in the meeting
for (var key in meetInfo.attendees.attendee){
console.log('key:',meetInfo.attendees.attendee[key]);
console.log(meetInfo.attendees.attendee[key].userID+"==="+user_id);
if(meetInfo.attendees.attendee[key].userID===user_id){
console.log('in meeting..');
inMeeting=true;
break;
}
else{
inMeeting=false;
}
}
Note:meetInfo is the Whole object
This works is there are more than one attendee but for one attendee it fails.
I am looking for something which would work for any number of 'attendees'.
Also I tried meetInfo.attendees.length instead of Object.keys(meetInfo.attendees).length but it didn't like it
It sounds like your attendees.attendee property could be either an array if multiple, or an object if singular. When it is an array your key variable in the for..in block will be populated the index. When it is an object, it will be populated with the property key.
Two things. First, you can make sure you are always working with an array by concatenating the value with an empty array:
var attendeeList = [].concat(meetInfo.attendees.attendee);
Second, you should not use for..in for iterate through an array. Use a classic for loop instead:
for (var idx= 0; idx < attendeeList.length; idx++)
console.log('key:',attendeeList[idx]);
console.log(attendeeList[idx].userID+"==="+user_id);
if(attendeeList[idx].userID===user_id){
console.log('in meeting..');
inMeeting=true;
break;
} else{
inMeeting=false;
}
}
Bonus, this loop is setting a variable true if any of the items in the array match. There is a special Array function for this:
inMeeting = [].concat(meetInfo.attendees.attendee)
.some(function(a){
return a.userID === user_id;
});

How to implement bi-directional connection between two arrays?

In my app I have an ItemsService which gets Items from Server and stores them as JSON objects in its cache variable. Items can be present in many places, e.g. in table or in graph/chart and so on.
For example, when I initialize a table - I need to pick only specific Items from cache, e.g. 1st, 3rd, 7th.
How to implement bi-directional connection between them? Basically I want table to contain references to specific items from cache so when I change an Item either in cache or in table - its state will be in sync all the time because it's the same Item.
Also when I delete Item from table - it needs to be removed from cache.
Here's example of table and cache structures:
Table:
table: {
"36": { // it's a name of a row
"72": [items], // it's a name of a column with corresponding items
"73": [items],
"74": [items]
},
"37": {
"72": [],
"73": [items],
"74": [items]
},
"38": {
"72": [],
"73": [],
"74": []
}
}
ItemsService cache (simplified version):
ItemsService = {
cache: [items]
};
Item structure:
{
id: 3,
parent_id: 1,
name: 'First Item',
siblings: [1,2,3],
active_users: [{user_id: 1, avatar_url: 'http://...'}, ...],
// 50 more fields :)
}
Also need to point out that I use angular-ui-sortable plugin to allow dragging of Items between columns/rows and I need to provide ng-model with array(I think). Here's how it looks right now:
<td ui-sortable="vm.sortableOptions"
ng-model="vm.table[row.id][column.id]">
<sb-item itemid={{item.id}}
ng-repeat="item in vm.table[row.id][column.id]">
</sb-item>
</td>
Unless for some reason you have to use two separate arrays, have you considered using a filter?
Your best bet would be objects. Variables that hold objects in javascript aren't really holding the object but a reference to said object. When you pass that variable into another one, the reference value gets copied so both variables point toward the same object.
var a = { 0: 'Property 0' };
var b = a;
b[0] = 'Property 0!'; //a[0] also the same.
delete b[0]; //a[0] nor b[0] exist anymore.
Using objects (rather than JSON) would work.
Then your cache and your table both point to same item objects. If you change something in the object, it is reflected at both ends.
var cacheArray = [{ item: 1 }, { item: 2}];
table[0][0] = cacheArray[0];
console.log(table[0][0].item); // 1
cacheArray[0].item = 9;
console.log(table[0][0].item); // 9.
Please note that the array and the table have not changed. They still point to the same objects.

Enumerate JSON master detail arrays

I have a view model that contains 2 related (master / detail) arrays that I want to bind to.
var ViewModel = function (data) {
var self = this;
self.CategoryList = ko.observableArray(data.CategoryList);
self.ItemList = ko.observableArray(data.ItemList);
}
Where Category is an array of { categoryID: 1, name: "Red Items" } etc
and Item is an array of { itemID: 1, categoryID: 1, name: "Red Widget" } etc
I have a handful of categories and possibly several hundred items. I am struggling with how to represent these in my view model in a way that I can enumerate categories and get to associated items or across all items and get to categories.
It doesn't seem efficient to maintain duplicate information on both lists and I don't want to be sending more data than needed over the wire.
One approach: create Item and Category objects and modify the prototype to include filtering (ko.computed) functions. category.Items() or item.Category().Name but I am not 100% how to best accomplish this within knockout.js given my need to load and save data.
I am not wed to arrays of simple JSON objects. Assuming I go the function / prototype route, how do I load and save my arrays of objects?
I think that you require a better data structure than an array, since -as you said- it's not optimal to keep duplicate information. Instead of having an array listing your categories, why don't use a hash table, or as we simply know in javascript, an object?
{
1: "Red Items",
2: "Blue Items",
3: "Green Items",
4: "Yellow Items",
}
(You can use a simple method to create the hash from the array)
var createHashFromArray = function(arr) {
var hash = {}
for (var i = 0, var len = arr.length; i < len; i++)
hash[i] = arr[i];
return hash;
}
From there, you can bind your viewModel according to the categories you need. You can even set up them as dynamic arrays using ko.computed in order to organize them in your view.
<div data-bind="foreach: redItemsOnly">
<span data-bind="text: itemId">ID</span>
<span data-bind="text: name">NAME</span>
</div>
And in your javascript...
self.redItemsOnly = ko.computed(function() {
return ko.utils.arrayFilter(self.ItemList(), function(item)
{
return self.CategoryHash[item.categoryID] === "Red Items"
});
}, self)
I'm not sure if this is what you want, but I hope this approach helps you to find other ways to come up with what you need.

How can i navigate through the json?

I have some JSON which I have in a object but I can seem to return the values a sample of the json is as follows.
{
"rootLayout":"main",
"layoutDescriptions":[
{
"id":"main",
"container" : {
"type":"Tabs",
"content":[
{
"type":"Panel",
"label":"Simple Address",
"layout":"SimpleForm",
"comment":"This form is simple name value pairs",
"content":[
{ "type":"label", "constraint":"newline", "text":"Org Name" },
{ "type":"text", "property":"propOne" },
{ "type":"label", "constraint":"newline", "text":"Address" },
{ "type":"text", "property":"addrLine1" },
{ "type":"text", "property":"addrLine2" },
{ "type":"text", "property":"addrLine3" },
{ "type":"label", "constraint":"newline", "text":"Postcode" },
{ "type":"text", "property":"postcode" }
]
},
I am trying to return the rootLayout using
obj[0].rootLayout.id
This doesn't work also I am wondering how to access the content elements.
I am new to json and I have been thrown in the deep end I think. I cannot find any good reading on the internet can anyone recommend some.
Thanks.
Some explanation because you don't seem to understand JSON
It's not as complicated as one may think. It actually represents javascript objects as if they'd be written by code.
So if you have JSON written as:
{
id : 100,
name: "Yeah baby"
}
This means that your object has two properties: id and name. The first one is numeric and the second one is string.
In your example you can see that your object has two properties: rootLayout and layoutDescriptions. The first one jsonObj.rootLayout is string and will return "main" and the second one is an array:
layoutDescriptions: [ {...}, {...},... ]
Apparently an array of objects because array elements are enclosed in curly braces. This particular array element object that you provided in your example has its own properties just like I've explained for the top level object: id (string), container (another object because it's again enclosed in curlies) etc...
I hope you understand JSON notation a bit more.
So let's go to your question then
You can get to id by accessing it via:
jsonObj.layoutDescriptions[0].id
and further getting to your content objects:
var contentObjects = jsonObj.layoutDescriptions[0].container.content[0].content;
for(var i = 0; i < contentObjects.length, i++)
{
// assign this inner object to a variable for simpler property access
var contObj = contentObjects[i];
// do with this object whatever you need to and access properties as
// contObj.type
// contObj.property
// contObj.text
// contObj.constraint
}
Mind that this will only enumerate first content object's content objects... If this makes sense... Well look at your JSON object and you'll see that you have nested content array of objects.
The object is an object, not an array, and it doesn't have a property called 0.
To get rootLayout:
obj.rootLayout
However, rootLayout is a string, not an object. It doesn't have an id. The first item in the layoutDescriptions array does.
obj.layoutDescriptions[0].id
Are you trying to get one of layoutDescriptions with id equals to obj.rootLayout?
var targetLayout = {};
for(var i = 0; i < obj.layoutDescriptions.length; i++) {
if(obj.layoutDescriptions[i].id == obj.rootLayout) {
targetLayout = obj.layoutDescriptions[i]; break;
}
}
console.log(targetLayout);

Categories

Resources