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

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();
},
});

Related

Javascript Papaparse Select specific columns using Lodash _.pick() results in empty data

As stated in previous questions here and on Google, I've added a step function to alter the data and provide me with the specific columns I need.
Here was a comment that said to use Lodash _.pick() method: https://stackoverflow.com/a/59944480/4236332
However, when doing that I end up with a completely empty results output.
Code:
parseFile(){
Papa.parse( this.file, {
header: true,
skipEmptyLines: true,
step: (results, parser) => {
results.data = _.pick(results.data , [ 'column1', 'column2']);
return results;
},
complete: function( results ){
console.log(results.data)
this.content = results;
this.parsed = true;
}.bind(this)
});
}
Before vs. After:
First console log holds the colums in the JSON I need plus several I want to filter out, Second log is completely empty.
Tried removing it from the step function and doing it in the complete function but same output.
EDIT 1:
I have tried testing the _.pick function on results.data[0] and this does work, so something is preventing _.pick() of looping through all json records in the list results.data?
Managed to fix this issue by looping through it with a _.map() function. This way it goes through every object in the array with the ._pick() method.
results.data = _.map(results.data, obj => _.pick(obj, [ 'column1','column2']));

How to delete a key within an object in local storage with Javascript and/or Jquery?

In local storage I have an object named favourites and it contains this..
"{
"id3333":{
"URL":"somewhere.comm/page1/",
"TITLE":"Page 1 Title",
},
"id4444":{
"URL":"somewhere.comm/page2/",
"TITLE":"Page 2 Title",
}
}"
How can I delete an object based on its ID (id3333 & id4444 for examples)
I have tried the following along with some other voodoo..
localStorage.removeItem('id3333'); // no errors, no removal
localStorage.removeItem('favourites':'id3333'); // SyntaxError: missing ) after argument list
localStorage.removeItem('favourites[id3333]'); // no errors, no removal
localStorage.removeItem('id3333', JSON.stringify('id3333')); // no errors, no removal
Also, I will need to get the key name to delete based on a variable, so like this..
var postID = 'id3333';
localStorage.removeItem(postID);
or
var objectName = 'favourites';
var postID = 'id3333';
localStorage.removeItem(objectName[postID]);
Is it possible to remove a nested item directly or do I need to retrieve the full object and then delete the item and then set the object back to local storage again?
The closest I can get to deleting anything directly so far is..
localStorage.removeItem('favourites');
But that of course removes the entire object.
You have a a single key and you are acting like there are multiple keys
var obj = {
"id3333":{
"URL":"somewhere.comm/page1/",
"TITLE":"Page 1 Title",
},
"id4444":{
"URL":"somewhere.comm/page2/",
"TITLE":"Page 2 Title",
}
};
window.localStorage.favs = JSON.stringify(obj); //store object to local storage
console.log("before : ", window.localStorage.favs); //display it
var favs = JSON.parse(window.localStorage.favs || {}); //read and convert to object
var delKey = "id3333"; //key to remove
if (favs[delKey]) { //check if key exists
delete favs[delKey]; //remove the key from object
}
window.localStorage.favs = JSON.stringify(favs); //save it back
console.log("after : ", window.localStorage.favs); //display object with item removed
With localStorage.removeItem you can only remove top level keys, i.e. keys directly on localStorage.
Because id3333 is on localStorage.favourites you cannot remove it using localStorage.removeItem.
Instead try delete localStorage.favourties['id3333']
Simple, actually: you just delete it. :)
x = {
"id3333":{
"URL":"somewhere.comm/page1/",
"TITLE":"Page 1 Title",
},
"id4444":{
"URL":"somewhere.comm/page2/",
"TITLE":"Page 2 Title",
}
};
console.log(x);
delete x.id3333;
console.log(x);
delete does what you're looking for. You could also do something like delete x.id3333.TITLE if you were so inclined. Note also that delete returns true if successful and false if not.
Suppose you set a nested object in localStorage like that
const dataObj = {
uid: {
name: 'robin',
age: 24,
}
}
window.localStorage.setItem('users', JSON.stringify(dataObj));
Now you want to delete the age property. You can't remove it with removeItem native function since it allows to delete from top level.
So you need to get the data first and delete the property you want and set the data again to localStorage with updated value like that
const existingLocalStorage = JSON.parse(window.localStorage.getItem('users') || {});
if(existingLocalStorage['uid']['age']) { // if throws any error, use lodash get fucntion for getting value
delete existingLocalStorage['uid']['age'];
}
window.localStorage.setItem('users', JSON.stringify(existingLocalStorage));

Turn Observable Array into nested JSON

I'm having a problem getting an array of information stored properly as JSON.
I made a fiddle to illustrate the problem. Enter a set of tags and take a look at the console to see the output.
More explanation:
So I have an input that takes in a comma-separated list of tags, which I then format.
function createTagArray() {
// given an input value of 'tag1, tag2, tag3'
// returns array = ['tag1', 'tag2', 'tag3']
}
I thought what I needed to do next was the following:
loop over the array and create a 'tag' object for each item which also includes an id for the tag and the id of the contact the tag is associated with.
Each object is pushed to tags, an observable array.
function single_tag(id, contactId, tagLabel) {
var self = this;
self.id = id;
self.contactId = contactId;
self.tagLabel = tagLabel;
}
function createTags() {
var array = createTagArray();
for (var i = 0; i < array.length; i++) {
self.tags().push(new single_tag(uuid.generate(), self.contactId, array[i]));
}
}
Then, I converted it into JSON
self.contactInformation = function() {
return ko.toJS({
"id": self.contactId,
"firstname": self.firstname(),
"lastname": self.lastname(),
... other fields ...
"tags": self.tags(),
})
}
But, when I inspect the console output of calling this function, tags is a collection of arrays, not a nice json object.
How do I get it formatted correctly?
I tried this suggestion, and the tag json is structured correctly, but it is stored with escaped quotes, so that seems wrong.
Thanks for all the help!
I would recommend you knockout.mapping plugin for KO, it allow map complicated JSON structure to view model, even without declarations.
From the documentation
Let’s say you have a JavaScript object that looks like this:
var data = {
name: 'Scot',
children: [
{ id : 1, name : 'Alicw' }
]
}
You can map this to a view model without any problems:
var viewModel = ko.mapping.fromJS(data);
Now, let’s say the data is updated to be without any typos:
var data = {
name: 'Scott',
children: [
{ id : 1, name : 'Alice' }
]
}
Two things have happened here: name was changed from Scot to Scott and children[0].name was changed from Alicw to the typo-free Alice. You can update viewModel based on this new data:
ko.mapping.fromJS(data, viewModel);
And name would have changed as expected. However, in the children array, the child (Alicw) would have been completely removed and a new one (Alice) added. This is not completely what you would have expected. Instead, you would have expected that only the name property of the child was updated from Alicw to Alice, not that the entire child was replaced!
...
To solve this, you can specify which key the mapping plugin should use to determine if an object is new or old. You would set it up like this:
var mapping = {
'children': {
key: function(data) {
return ko.utils.unwrapObservable(data.id);
}
}
}
var viewModel = ko.mapping.fromJS(data, mapping);
In the jsfiddle you were using Knockout 3.0 which doesn't have support for textInput. This was added in 3.2. To use version 3.2 you need to use a cdn such as this: http://cdnjs.com/libraries/knockout
There was typeo in your binding. sumbit should be submit.
There was a problem with your constructor for single_tag. id was not used so I removed it:
function single_tag(contactId, tagLabel) {
var self = this;
self.contactId = contactId;
self.tagLabel = tagLabel;
}
Currently also contactId is not set because the observable has not been set to a value.
To convert to JSON you need to use ko.toJSON instead of ko.toJS:
self.contactInformation = function() {
return ko.toJSON({
"firstname": self.firstname(),
"tags": self.tags(),
})
}
Now when the console writes out an array appears:
{
"firstname":"test",
"tags":[
{"tagLabel":"test1"},
{"tagLabel":"test2"},
{"tagLabel":"test3"}
]
}
JsFiddle
So my problem was more basic than I was realizing. I'm using JSON Server to serve up my data, and I was pulling information from two parts of the database (contacts & tags).
When I tried to update my tags, I was trying to apply them to a property that didn't exist on the contact JSON in my database. Posting the tags separately worked though.

sub array and push data

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]);
}
}

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