I am working on an angular application with a node.js backend where my architecture goes like this:
front-end => angular.service => node backend => mLab DB
Currently, I'm trying to push an object into the DB provided that it does not exist yet. If it already does, it should update. This function would be accessible via a button from the cards in my front-end.
to give a clearer understanding here's some of my code.
front-end: admin-edit-home.component.html
<a mdbBtn class='btn btn-md btn-primary' mdbWavesEffect (click)="addCard()">Add</a>
the code above is a button where I can add a card to the interface. The TS below shows how the code works.
front-end: admin-edit-home.component.ts
addCard() {
this.carousels.push(this.carousels.length);
}
To give an explanation of the TS code, 'carousels' is an array that I use to do an *ngFor loop in my HTML wherein it presents the data in a card format. It is declared as:
carousels: any = [];
So in pushing a length to the 'carousels' array, it present an empty card with no collected data but still possessing the HTML elements from the original card which contains the supposed update function that I would like to have.
My problem is, how do I do the checking of the object existence from the back-end and present the results back to the front-end? I have tried this,
back-end: api.js
router.route('/carousel/update/:id').put(function(req,res) {
var data = req.body;
const myquery = { _id: ObjectId(req.params.id) };
db.collection('home').updateOne(myquery, {
$set: {
"header" : data.header,
"subheader" : data.subheader,
"img" : data.img
}
})
if (myquery === -1) {
arr.push(obj);
} else {
arr[myquery] = obj
}
}
I know my back-end code is wrong and non-functional but I just wanted to let you guys have a visualisation of what my logic is trying to achieve.
Furthermore, this back-end code should now be accessible by my angular service through this chunk of code below:
home.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable ({
providedIn: 'root'
})
export class HomeService {
constructor(private http: HttpClient) {}
updateCard(id: string, header: string, subheader: string, img: string) {
var json = {id: id, header: header, subheader: subheader, img: img}
return this.http.put<any[]>(`./api/carousel/update/${id}`, json);
}
}
After trying these things, to sum up my problem in a more concise manner, I need to check from the database if the object is already existing via ObjectId and then update it through my input fields but if not, the updateCard() should create another object in my database. I hope to get help!
EDIT
router.route('/carousel/update/:id').put(function (req, res) {
var data = req.body;
const myquery = { "_id": ObjectId };
// console.log('header: ' + data.header + " id: " + data.id)
console.log(req.params)
db.collection("home").updateMany(myquery, {
$set: {
"img" : data.img,
"header" : data.header,
"subheader": data.subheader
}
}, (err, results) => {
res.status(200).json({status: "ok"})
})
})
This is the new api.js. Please refer.
Related
I'm trying to write a website with angular and firebase.
The site works so that different users can be created (I added auth.service.ts)
And any registered user will be able to add a contact to the firestore.
The problem: I'm unable to get the added contact information to appear on the screen.
The error I keep getting in the console is:
core.js:6241 ERROR FirebaseError: Function CollectionReference.doc() cannot be called with an empty path.
my firestore design:
collection name "users"-> containing document for each user->each user has "contacts" collection-> each contact containing the email,name,phone contacts attributes.
The following code is from the crud.service.ts file:
export class CrudService {
constructor(private authservice: AuthService, public fireservices:AngularFirestore) { }
//create_NewContact adds to the 'contacts' collection in firebase, the contact that the user entered as input
create_NewContact(Record)
{
return this.fireservices.collection('users').doc(this.authservice.currentUserId).collection('contacts').add(Record);
}
//get_AllContacts gets the 'contacts' collection from firebase
get_AllContacts()
{
return this.fireservices.collection('users').doc(this.authservice.currentUserId).collection('contacts').snapshotChanges();
}
.
.
.
}
The following code is from the contact-list.component.ts file:
export class ContactListComponent implements OnInit {
contact: any;
contactName: string;
contactEmail: string;
contactPhone: string;
message:string;
constructor(private authservice: AuthService,public crudservice:CrudService) { }
ngOnInit() {
this.crudservice.get_AllContacts().subscribe(data => {
this.contact = data.map(c => {
return {
id: c.payload.doc.id,
isEdit: false,
name: c.payload.doc.data()['name'],
email: c.payload.doc.data()['email'],
phone: c.payload.doc.data()['phone'],
};
})
console.log(this.contact);
});
}
/*CreateRecord() will fire after the user press the "Create Contact" btn*/
CreateRecord()
{
//The function stores within the relevant fields in "Record" variable, the user's input
let Record = {};
Record['name'] = this.contactName;
Record['email'] = this.contactEmail;
Record['phone'] = this.contactPhone;
//create_NewContact is defined in crud.service.ts file
this.crudservice.create_NewContact(Record).then(res => {
this.contactName = "";
this.contactEmail = "";
this.contactPhone = "";
console.log(res);
this.message = "Contact data save done";
}).catch(error => {
console.log(error);
})
}
.
.
.
}
Do you have ideas how to fix this problem? Thank you!
The error message indicates that the value passed to the doc() method is an empty string.
The problem most probably comes from the fact that, at the moment you call this method, this.authservice.currentUserId is null. currentUserId is probably null because the authservice object has not finished initializing: see the doc for more details.
You should either use the onAuthStateChanged observer or check that this.authservice.currentUserId is not null.
So right now I have a homepage, made by using html.
I want to add some divs, where I show the newest blogs I posted on my WIX page.
<div layout="row" layout-align="center center">
<md-card flex="60" class="pad-md md-body-1 border-1" md-colors="{"borderColor": "epprimary1-500", "color": "epsecondary6"}">
{{blog headline}}
Open Blog<md-icon>open_in_new</md-icon>
</md-card>
</div>
On the Wix platform, I know where they store the data in a so called dataset:
Now I need to know how to access these data from my other website.
I figured it out, finally!!
You can get the data you need via an http request.
Therefore, first of all, you need to add a javascript in your backend folder in Wix and name it "http-functions.js", delete it's content and add the folowing code.
Note: get_blogEntry() is method_functionName()
Blog/Posts is the DB I used, you can use any DB you have on wix.
import {ok, notFound, serverError} from 'wix-http-functions';
import wixData from 'wix-data';
export function get_blogEntry() {
let options = {
"headers": {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
}
};
// query a collection to find matching items
return wixData.query("Blog/Posts")
.find()
.then( (results) => {
// matching items were found
if(results.items.length > 0) {
let itemOne = results.items[0];
let itemTwo = results.items[1];
options.body = {
"blogOneTitle": itemOne.title,
"blogOneUrl": "https://etaplus.energy" + itemOne.postPageUrl,
"blogTwoTitle": itemTwo.title,
"blogTwoUrl": "https://etaplus.energy" + itemTwo.postPageUrl
}
return ok(options);
}
})
// something went wrong
.catch( (error) => {
options.body = {
"error": error
};
return serverError(options);
} );
}
After you added this code in your backend, then you can access the data via the following URL:
"https://YOURWEBSITEURL/_functions/blogEntryor whatever your function name is"
I have a very basic feathers service which stores data in mongoose using the feathers-mongoose package. The issue is with the get functionality. My model is as follows:
module.exports = function (app) {
const mongooseClient = app.get('mongooseClient');
const { Schema } = mongooseClient;
const messages = new Schema({
message: { type: String, required: true }
}, {
timestamps: true
});
return mongooseClient.model('messages', messages);
};
When the a user runs a GET command :
curl http://localhost:3030/messages/test
I have the following requirements
This essentially tries to convert test to ObjectID. What i would
like it to do is to run a query against the message attribute
{message : "test"} , i am not sure how i can achieve this. There is
not enough documentation for to understand to write or change this
in the hooks. Can some one please help
I want to return a custom error code (http) when a row is not found or does not match some of my criterias. How can i achive this?
Thanks
In a Feathers before hook you can set context.result in which case the original database call will be skipped. So the flow is
In a before get hook, try to find the message by name
If it exists set context.result to what was found
Otherwise do nothing which will return the original get by id
This is how it looks:
async context => {
const messages = context.service.find({
...context.params,
query: {
$limit: 1,
name: context.id
}
});
if (messages.total > 0) {
context.result = messages.data[0];
}
return context;
}
How to create custom errors and set the error code is documented in the Errors API.
I'm building a simple chat app backed by this Firebase Database structure:
messages: {
"-KTjL_oLrKOboa2su2zk": {
name: "puf",
text: "Look I'm smiling :-)"
},
"-KTjNfaNem752ChFBcnC": {
name: "puf",
text: "And now I'm not smiling"
}
}
I'm using Angular2 and AngularFire2 to generate the HTML. I have a simple list of messages from the Firebase Database in my controller:
export class AppComponent {
messages: FirebaseListObservable<any[]>;
constructor(public af: AngularFire) {
this.messages = af.database.list('messages');
}
}
I want to detect certain conditions in each message and translate that into an emoji in my HTML. Since this is purely display information derived from the existing content, I don't want to store it in the database.
My HTML template:
<li class="text" *ngFor="let message of messages | async">
{{message.name}} {{message.emoji}}: {{message.text}}
</li>
In the Firebase JavaScript SDK, this would be akin to:
ref.on('child_added', function(snapshot) {
var message = snapshot.val();
if (message.text.indexOf(':-)') >= 0) {
message.emoji = '🙂';
}
addMessageToHTML(message);
});
How should I do such client-side enrichment in AngularFire2?
Not sure how things work in JSSDK, but when you subscribe (with async pipe) to FirebaseListObservable you are disconnected from Firebase (upstrem); you will still get updates (downstrem). So you can just chain map() to the observable, and add property in the client:
import 'rxjs/add/operator/map'
export class AppComponent {
messages: FirebaseListObservable<any[]>;
constructor(public af: AngularFire) {
this.messages = af.database.list('messages')
.map(messages => messages.map(message => {
if (message.text.indexOf(':-)') >= 0) {
message.emoji = '🙂';
}
return message;
}))
}
}
UPDATE: working example
If you update data with 3rd record on the server side, template should update. You can't however add new message to the this.messages on the client, you have to recreate reference and update the server that way:
af.database.list('messages').push({
name: "new",
text: "Now I'm sad :-("
}
}
I'm trying to consume a REST webservice, responding with a JSON String containing a fairly "complex" schema.
I created a model that contains every fields sent by the webservice.
Here are the relevant codes that should be a problem :
public getUser(user_id: number): PlanDeCharge.Modeles.User {
var toto;
this.UserRest.get({ user_id: user_id }, function(){}, function(err){
this.$window.location.href = "http://localhost:8080/myapp_webapp/login.do";
}).$promise.then(function(data){
toto = data;
});
return toto;
}
-
this.userConnecte = this.gestionUserService.getUser(759);
-
export function userRest($resource: ng.resource.IResourceService, $cookies: ng.cookies.ICookiesService): PlanDeCharge.Modeles.IUserResource {
this.key = $cookies.get("encodedKey");
var urlService: string = "http://localhost:8080/teambox_webapp/resource-rest/V1_1/users/:user_id";
return <PlanDeCharge.Modeles.IUserResource> $resource(urlService, {user_id: "#user_id"}, {
get:{
headers:{"key" : this.key}
}
});
}
app.factory("UserRest", ["$resource", "$cookies", userRest]);
I did a lot of modifications, trying to fix the call without success... The request actually get a response containing the JSON string, but I can't put it inside an object to be use (like user['id'] = 2)
Thanks in advance
I deleted the last post and made this new one, the first one wasn't clear enough and people were confused
When working with promises you should let Angular handle the resolvement.
Am I right, if you are actually using AngularJS 1 and not ng2 as the question is tagged? The syntax is ng1 anyways.
Some notes on the getUser method. Return the reference created by $resource instead of creating one your self. Further more, use the fat-arrow syntax on the callbacks to bind this to the proper context. See this article for more on this.
To remove even more code use TypeScripts object initialization and init the user id object with just { user_id }. This creates a JavaScript object with a property user_id with the value of user_id.
public getUser(user_id: number): SomeModel {
return this.UserRest
.get({ user_id }, () => { }, () => {
this.$window.location.href = "http://localhost:8080/myapp_webapp/login.do";
});
}
In your component or controller access
this.userConnecte = this.gestionUserService.getUser(759);
Lastly, the factory/service.
Use the fact that $resource is generic and set your variables as constants when not changed.
export function userRest(
$resource: ng.resource.IResourceService,
$cookies: ng.cookies.ICookiesService
): ng.resource.IResourceClass<PlanDeCharge.Modeles.IUserResource> {
this.key = $cookies.get("encodedKey");
const urlService = "http://localhost:8080/teambox_webapp/resource-rest/V1_1/users/:user_id";
return $resource<PlanDeCharge.Modeles.IUserResource>(urlService, { user_id: "#user_id" }, {
get: {
headers: { "key": this.key }
}
});
}
This should fix your problems and make to code more readable. :)