I'm working on an ionic app, which I would like to integrate with firebase. I have the following code in my home.ts file:
export class HomePage {
UHSGetMonths$: Observable < any[] > ;
constructor(public navCtrl: NavController,
public platform: Platform,
private screenOrientation: ScreenOrientation,
private UHSMonths: UHSGetMonthsService,
public actionSheetCtrl: ActionSheetController,
private localNotifications: LocalNotifications,
public alertCtrl: AlertController) {
this.platform.ready().then((ready) => {
this.localNotifications.on('tap', (notification, state) => {
let json = JSON.parse(notification.data);
let alert = this.alertCtrl.create({
title: notification.title,
subTitle: json.fullMsq
});
alert.present();
});
});
//this.screenOrientation.lock(this.screenOrientation.ORIENTATIONS.PORTRAIT);
this.UHSGetMonths$ = this.UHSMonths
.getUHSMonthsList() // DB LIST
.snapshotChanges() // Give access to both Key and Value
.map(changes => {
return changes.map(c => ({
key: c.payload.key,
...c.payload.val(),
}));
});
}
}
I can successfully retrieve the data in my template files but how do get access a value in firebase database from the home.ts? In Firebase, I have meeting names and times for each month. E.g. for July, the team briefing takes place at 10am. How can I get the value 10am to use and manipulate in my home.ts?
Thanks
Firebase JSON file snippet:
[ {
"days" : [ {
"StaffBriefing" : "10:00",
"Team A Meeting" : "11:30",
"Team B Meeting" : "13:00",
"Team C Meeting" : "15:30",
"Date" : "01"
}, {
"StaffBriefing" : "14:00",
"Team A Meeting" : "12:45",
"Team B Meeting" : "14:00",
"Team C Meeting" : "16:30",
"Date" : "02"
}, {
"StaffBriefing" : "09:00",
"Team A Meeting" : "14:00",
"Team B Meeting" : "11:00",
"Team C Meeting" : "15:30",
"Date" : "03"
} ],
"monthName" : "January"
} ]
Update - 03/08/2018
Yes, I added the subscription code after the this.UHSGetMonths$. However, the following code worked:
`this.JubileeMonths
.getJubileeMonthsList() // DB LIST
.valueChanges()
.subscribe(data => {
console.log(data);
});`
And the console.log(data) displays:
If I do console.log(data[0]); I get this, which is fine.
However, If I try doing console.log(data[0].monthName); I get an error in my code editor (Atom) i.e. **Property 'monthName' does not exist on type '{}'` but in the console I get the correct value of January.
Why the error in the code editor or am I doing this all wrong?
Thanks.
UHSGetMonthsService
import { Injectable } from '#angular/core';
import { AngularFireDatabase } from 'angularfire2/database';
import * as moment from 'moment';
#Injectable()
export class UHSGetMonthsService {
private UHSGetMonthsRef$ = this.fbDB.list('UHS/Calendar/months');
constructor(private fbDB: AngularFireDatabase) {
}
getUHSMonthsList() {
return this.UHSGetMonthsRef$;
}
}
Given your database structure, you could do this after UHSGetMonths$ is set:
this.UHSGetMonths$
.subscribe(months => {
if (months && months.length) {
let month = months.find(m => m.monthName === 'January');
let day = month.days.find(d => d.Date === '02');
console.log(day['Team C Meeting']);
}
});
If you wanted to get the current month's name for the .find(), you'd need to either use this post's solution or momentjs.
If you wanted to get the current day of the month, you can use new Date().getDate() or momentjs again.
Update:
You're getting the error because you haven't defined the "shape" of the return data, so as far as your IDE knows, it's just a generic object. To fix this, create an interface that matches what the data looks like and use it on your list reference.
import { Injectable } from '#angular/core';
import { AngularFireDatabase } from 'angularfire2/database';
import * as moment from 'moment';
export interface Month {
monthName: string;
days: any[];
}
#Injectable()
export class UHSGetMonthsService {
private UHSGetMonthsRef = this.fbDB.list<Month>('UHS/Calendar/months');
constructor(private fbDB: AngularFireDatabase) {
}
getUHSMonthsList() {
return this.UHSGetMonthsRef;
}
}
Related
I am currently working on a Angular project that makes it possible to create lobbies for different web games. The idea is that the application already gathers players so a web game can be started immediately.
But right now I am running into a problem that is caused by getting data from my Springboot Java API.
The Angular application gets the data correctly but when i try to convert the observable into a normal Game[] after subscribing ofcourse. It makes all the properties of the elements in the Game[] undefined. What is causing this to happen?
The Game Service:
//Returns a list of all games known to the API
getAllGames() :Observable<Game[]>
{
return this.httpClient.get<Game[]>(this.connectionService.getConnectionString()+"/games",this.httpOptions)
}
The Game class:
export class Game {
public Id : String;
public Name: String;
public RedirectURI : String;
public MinUserCount : Number;
public MaxUserCount : Number;
constructor(Id : String,Name : String,RedirectURI : String,MinUserCount : Number,MaxUserCount : Number)
{
this.Id = Id;
this.Name = Name;
this.RedirectURI = RedirectURI;
this.MinUserCount = MinUserCount;
this.MaxUserCount = MaxUserCount;
}
}
The Component:
games: Game[];
//Get all games known to the API
this.gameService.getAllGames().subscribe( elements => this.games = elements )
//This doesn't work all the elements of this.games are undefined.
I have also tried to work with a foreach of the array that gets returned.
With no effect either
games: Game[];
//Get all games known to the API
this.gameService.getAllGames().subscribe(elements => {
elements.forEach(item => {
var game = new Game(item.Id, item.Name, item.RedirectURI, item.MinUserCount, item.MaxUserCount)
this.games.push(game)
})
})
The JSON Result for the GetRequest
[
{
"name": "QuizGame",
"id": "dg217d65126b5e31v6d5v5d15v564d",
"maxUserCount": 4,
"redirectURI": "http://localhost:8082",
"minUserCount": 1
},
{
"name": "RPG",
"id": "dt76TQWR127367125SDYATFHa32615",
"maxUserCount": 10,
"redirectURI": "http://localhost:8083",
"minUserCount": 0
},
{
"name": "Scribble Clone",
"id": "378167e86dsahdgahkj312DJKHDg2d",
"maxUserCount": 9,
"redirectURI": "http://localhost:8084",
"minUserCount": 1
},
{
"name": "WebPonker",
"id": "0o00dhsnvkjzbcxhgjyg23v2gh3dvg",
"maxUserCount": 4,
"redirectURI": "http://localhost:8085",
"minUserCount": 4
}
]
The properties in your JSON response start with a lowercase.
In your Game class, you use properties that start with an uppercase.
I believe the parsing from JSON to a typescript object is case sensitive. Could you try to change the first letter of your properties to lowercase?
In MongoDB, this is the simplified structure of my account document:
{
"_id" : ObjectId("5a70a60ca7fbc476caea5e59"),
"templates" : [
{
"name" : "Password Reset",
"content" : "AAAAAAAA"
},
{
"name" : "Welcome Message",
"content" : "BBBBBB"
}
]
}
There's a similar default_templates collection
let accnt = await Account.findOne({ _id: req.account._id }, { templates: 1 });
let defaults = await DefaultTemplate.find({}).lean();
My goal is to find the missing templates under account and grab them from defaults. (a) I need to upsert templates if it doesn't exist in an account and (b) I don't want to update a template if it already exists in an account.
I've tried the following:
if (!accnt.templates || accnt.templates.length < defaults.length) {
const accountTemplates = _.filter(accnt.templates, 'name');
const templateNames = _.map(accountTemplates, 'name');
Account.update({ _id: req.account._id, 'templates.name' : { $nin: templateNames } },
{ '$push': { 'templates': { '$each' : defaults } } }, { 'upsert' : true },
function(err, result) {
Logger.error('error %o', err);
Logger.debug('result %o', result);
}
);
}
This succeeds at the upsert but it will enter all default templates even if there's a matching name in templateNames. I've verified that templateNames array is correct and I've also tried using $addToSet instead of $push, so I must not understand Mongo subdoc queries.
Any ideas on what I'm doing wrong?
Edit: I've gotten this to work by simply removing elements from the defaults array before updating, but I'd still like to know how this could be accomplished with Mongoose.
You can try with bulkWrite operation in mongodb
Account.bulkWrite(
req.body.accountTemplates.map((data) =>
({
updateOne: {
filter: { _id: req.account._id, 'templates.name' : { $ne: data.name } },
update: { $push: { templates: { $each : data } } },
upsert : true
}
})
)
})
I'm confused with string arrays using angular 2 and mongodb.
my class
import { CollectionObject } from './collection-object.model';
export interface Prox extends CollectionObject{
location_id: string;
nearby_locations: string[];
}
After inserting, my mongo looks like this
{ "_id" : "9JrBYBCmPSZ7PLpt7", "location_id" : "1", "nearby_locations" : [ { "location" : "2" }, { "location" : "3" } ] }
{ "_id" : "ha7CRD35pXwBkN4Cx", "location_id" : "2", "nearby_locations" : [ { "location" : "1" }, { "location" : "3" } ] }
{ "_id" : "zLTpYGYWguv9gbnCC", "location_id" : "3", "nearby_locations" : [ { "location" : "2" }, { "location" : "1" } ] }
How do I retrieve and looping through nearby_locations?
this doesn't work:
let myprox = Proxs.findOne({});
for (let map of myprox.nearby_locations)
{
alert(map);
//map is an object, not a string!
}
the following code does work, but visual studio will complain there is an error because 'location' is not defined in my type script.
let myprox = Proxs.findOne({});
for (let map of myprox.nearby_locations)
{
alert(map.location);
}
Is there a more correct way of doing it so that visual studio doesnt complain?
How about:
let myprox = Proxs.findOne({}) as Prox;
myprox.nearby_locations.forEach(obj => {
console.log(obj.location);
});
Edit
My bad.
Your definition isn't correct, it should be:
export interface Prox extends CollectionObject {
location_id: string;
nearby_locations: { location: string }[];
}
Or another way to write the same thing:
interface Location {
location: string;
}
export interface Prox extends CollectionObject {
location_id: string;
nearby_locations: Location[];
}
Or a third way:
type Location = {
location: string;
}
export interface Prox extends CollectionObject {
location_id: string;
nearby_locations: Location[];
}
try this i think it will help you:
alert(map[0].location);
my schema looks like this:
var exampleSchema = newSchema({
profile:{
experience :[{
exp : String
}]
}
});
this is the codes to update experience in profile collection:
exampleSchema.statics.experience = function (id,experience, callback){
var update = {
$push: {
'profile.experience': experience
}
}
this.findByIdAndUpdate(id,update,function(err) {
if (err) {
callback(err);
} else {
callback(null);
}
})
I was getting error like The field 'profile.experience' must be an array but is of type String in document {_id: ObjectId('5653f1d852cf7b4c0bfeb54a')}[object Object]
console.log(experience) is equal to
{ exp: 'jlkjlkjlk' }
my collection should look like this:
experience:[
{
exp : "YYYY"
},
{
exp:"xxxx"}
]
Imagine that you have this collection:
/* 1 */
{
"_id" : ObjectId("565425e862760dfe14339ba8"),
"profile" : {
"experience" : [
{
"exp" : "Experto"
}
]
}
}
/* 2 */
{
"_id" : ObjectId("565425f562760dfe14339ba9"),
"profile" : {
"experience" : {
"exp" : "Experto"
}
}
}
/* 3 */
{
"_id" : ObjectId("5654260662760dfe14339baa"),
"profile" : {
"experience" : "Experto"
}
}
If you try (update doc /* 2 */):
db.profile.update(
{ _id: ObjectId("565425f562760dfe14339ba9") },
{ $push: { "profile.experience" : { exp : "Intermediate" } } }
)
You get this error:
The field 'profile.experience' must be an array but is of type Object
in document {_id: ObjectId('565425f562760dfe14339ba9')}
And if you try (update doc /* 3 */):
db.profile.update(
{ _id: ObjectId("5654260662760dfe14339baa") },
{ $push: { "profile.experience" : { exp : "Intermediate" } } }
)
You will get:
The field 'profile.experience' must be an array but is of type String
in document {_id: ObjectId('5654260662760dfe14339baa')}
i changed Schema like this
experience : [{type:String,exp:String}],
my update object looks like this
var update = {
$push: {
'profile.experience': san.exp
}
};
san looks like this :{ exp: 'YYY' }
Inside mongoose collectionlooks like this used RoboMongo
"experience" : [
"experienced in XXX",
"YYY"
],
$push: {
'profile.experience': experience
}
Remove .exp.
First you have to check you declared your field as an array like this(look at field products):
shop = {
'name': "Apple Store",
'description': "",
'direction': "",
'contact': "",
'products':[]
}
Now if you want to add something to the field products using $push
product = {
'name': "Iphone 6",
'description': "Iphone model 6, 64GB",
'price': 700,
'count': 3
}
myquery = { "name" : "Apple Store" }
obj ={"$push":{"products":{"$each": [product]}}}
db.collection.update_one(myquery,obj)
This code is provided for PyMongo framework. To use in MongoDB directly replace update_one by update. Mongo resource
You may use $set instead of $push which might work.
$set: {
'profile.experience': experience
}
are you searching for adding multiple values into single field then use this one.
write this one your model or schema:
arrayremarks:[{remark: String}]
then write in your controller:
module.exports.addingremarks = (req, res) => {
let casenum=JSON.parse(JSON.stringify(req.body.casenum).replace(/"\s+|\s+"/g,'"'))
var rem={remark:"Suman macha"}
Inwart.update( { 'casenum': casenum },{ $push: { arrayremarks:rem} } ,function (err, inwarts) {
if (err)
return console.error(err);
res.send(inwarts);
}
)
}
I would like to create an array with JSON-Builder.
Expected format:
{
"Header": {
"SomeKey" : "SomeValue"
}
"Data": [
{
"SomeKey" : "SomeValue"
},
{
"SomeKey" : "SomeValue"
}
]
}
My Code:
def builder = new groovy.json.JsonBuilder()
def root = builder {
Header {
"Typ" "update"
"Code" "UTF-8"
"TransaktionsNr" item.transactionNumber
"DatumZeit" new Date().format("dd.MM.yyyy HH:mm")
}
customers.each ({ customer->
"Data" {
"Email" customer.code
"Newsletter" customer.newsletterSubscribed
}
})
However whatever I do I only get one element in the Data section. I tried using [] instead of {}, but I still only get one element, what am I doing wrong?
That's duplicate key for JSON structure. There should not be duplicate key in the same hierarchy or they will override each other:
class Customer { String code; boolean newsletterSubscribed }
customers = [
new Customer(code:"11111", newsletterSubscribed:true),
new Customer(code:"22222", newsletterSubscribed:false)
]
def builder = new groovy.json.JsonBuilder()
def root = builder {
Header {
"Typ" "update"
"Code" "UTF-8"
"TransaktionsNr" 987
"DatumZeit" new Date().format("dd.MM.yyyy HH:mm")
}
customers customers.collect { customer ->
["Email":customer.code,
"Newsletter":customer.newsletterSubscribed]
}
}
assert builder.toString() == {"Header":{"Typ":"update","Code":"UTF-8","TransaktionsNr":987,"DatumZeit":"21.12.2012 13:38"},"Data":{"Email":"22222","Newsletter":false},"customers":[{"Email":"11111","Newsletter":true},{"Email":"22222","Newsletter":false}]}