This is my jade file (basically # stand for id and . for class) and I want to send this to mongodb and save user.activity
textarea#post-form.form-control(
rows="4",
placeholder="Share to world of LinkMe",
ng-model='user.activity'
)
button#post-btn.btn.btn-primary.pull-right(ng-click="post(user)") Link
Here is my code for the controller:
$scope.post = function(user){
auth.post(user).then(function(){
$scope.activity = user.activity;
})
}
And the auth.post function :
post: function(user){
var deferred = $q.defer();
var updatedUser = new UsersResource(user);
updatedUser._id = identity.currentUser._id;
updatedUser.$update().then(
function(){
identity.currentUser.activity = updatedUser.activity;
deferred.resolve();
},
function(response){
deferred.reject(response);
}
);
return deferred.promise;
}
Good thing is I see the change when this happens, but it is not saved in the database.
This is the userSchema:
var userSchema = mongoose.Schema({
username: {type: String, require: '{PATH} is required' , unique: true},
firstName: {type: String, require: '{PATH} is required'},
lastName: {type: String, require: '{PATH} is required'},
profilePic: {type: String, default: 'imgs/default.jpg'},
activity: String,
salt: String,
hashPass: String,
roles: [String]
});
I really appreciate help :)
P.P. I have this on server now :
app.put('/collections/:collectionName/:id', function(req, res, next) {
req.collection.updateById(req.params.id, {$set:req.body}, {safe:true, multi:false}, function(e, result){
if (e) return next(e)
res.send((result===1)?{msg:'success'}:{msg:'error'})
})
})
Problem now is that I have model of User from userSchema but I didn't declare any collections. What should I do ?
You'll need a REST interface on the server side to work with Mongo, take a look at this:
http://docs.mongodb.org/ecosystem/tools/http-interfaces/#HttpInterface-RESTInterfaces
Let's say you are using Node.js with Express and Mongoose, you will have to set up a REST api along the lines of:
var app = express();
var mongoose = require('mongoose');
var database_url = "mongodb://localhost:27017/Database";
var listen_port = 8080; // example port
var collections = ["collection1",...];
mongoose.connect(database_url);
var Model1 = mongoose.model('collection1', userSchema); // <--- your user schema
// example of a getter by id
app.get('/api/get/:id', function(req, res) {
Model1.find({ _id: req.params.id }, function(err, post){
res.send(post);
});
});
app.listen(listen_port);
and set up dependencies in your package.json file, like for instance
"dependencies" : {
"express" : "~3.4.4",
"mongoose" : "~3.6.2"
}
And then make use of Angular $http service in order to perform async calls to the API.
https://docs.angularjs.org/api/ng/service/$http
Related
I am working on angular firebase web app, in which as soon as admin login, he can create users by his own.
When admin log in , he is authenticated with firebase.auth()
But what is happening is, as admin creates a new user, the current auth details(admin) gets replaced by newly created user. I want the user creation without creating a newer session
Have a look at my controller:
app.controller('UserAdd', ['$scope','$sessionStorage','$http','$firebaseAuth', '$firebaseArray', '$location' ,'$firebaseObject', 'FBURL', function($scope,$sessionStorage,$http,$firebaseAuth,$firebaseArray, $location ,$firebaseObject, FBURL){
var user = firebase.database().ref().child("users");
$scope.user_auth_data = firebase.auth().currentUser;
$sessionStorage.uID = $scope.user_auth_data.uid ;
$scope.access_points= [];
$scope.teams = [];
$scope.org_details = [];
user.child($sessionStorage.uID).child("OrganizationId").on('value',function(org_id){
$sessionStorage.org_id = org_id.val();
})
user.child($sessionStorage.uID).child("ImagePath").on('value',function(img){
$scope.user_image = img.val();
})
//access points
firebase.database().ref().child("organization").child($sessionStorage.org_id).child("access_points").on('value',function(access_points){
angular.forEach(access_points.val(),function(ap,key){
$scope.access_points.push({id:key,ssid:ap.SSID,bssid:ap.BSSID,display_name:ap.DisplayName,lat:ap.Latitude,lng:ap.Longitude});
})
});
var obj = $firebaseArray(firebase.database().ref().child("organization").child($sessionStorage.org_id).child("access_points"));
obj.$loaded(
function(data) {
},
function(error) {
console.error("Error:", error);
}
);
firebase.database().ref().child("organization").child($sessionStorage.org_id).child("teams").on('value',function(teams){
angular.forEach(teams.val(),function(team,key){
$scope.teams.push({id:key,team_name:team.TeamName,team_leader:team.TeamLeader,channel_name:team.ChannelName});
})
});
var obj = $firebaseArray(firebase.database().ref().child("organization").child($sessionStorage.org_id).child("teams"));
obj.$loaded(
function(data) {
},
function(error) {
console.error("Error:", error);
}
);
$scope.selectItem = function(){
};
//add user
$scope.addUser = function() {
firebase.auth().createUserWithEmailAndPassword($scope.Email, $scope.Password)
.then(function(user) {
//adding single values in user node
var ref = firebase.database().ref().child("users").child(user.uid);
ref.set({
EmployeeId: $scope.emp_id,
Contact: $scope.Contact,
DOB: $scope.date_of_birth,
Designation: $scope.Designation,
Email: $scope.Email,
FirstName: $scope.FirstName,
LastName: $scope.LastName,
OrganizationId: $sessionStorage.org_id,
Gender: $scope.selectedGender,
IsAdmin: false
});
$scope.selectedAccess.forEach(function(access_values){ //adding nested access_points
var ref1 = firebase.database().ref().child("users").child(user.uid).child("AccessPoint").child(access_values.id);
ref1.set({
SSID: access_values.ssid,
BSSID: access_values.bssid,
DisplayName: access_values.display_name,
Latitude: access_values.lat,
Longitude: access_values.lng
});
});
$scope.selectedTeam.forEach(function(team_values){ //adding nested team
var ref2 = firebase.database().ref().child("users").child(user.uid).child("team").child(team_values.id);
ref2.set({
ChannelName: team_values.channel_name,
TeamName: team_values.team_name,
TeamLeader: team_values.team_leader
});
});
$scope.teams.forEach(function(team_values){
var ref3 = firebase.database().ref().child("organization").child($sessionStorage.org_id).child("channels").child(team_values.channel_name).child("info").child("users");
ref3.child(user.uid).set($scope.FirstName+" "+$scope.LastName);
var ref4 = firebase.database().ref().child("organization").child($sessionStorage.org_id).child("user_team").child(team_values.team_name).child(user.uid);
ref4.set($scope.FirstName+" "+$scope.LastName);
});
firebase.auth().sendPasswordResetEmail(user.email);
$location.path('/user_list');
}).catch(function(error) {
console.log(error);
});
};
}]);
Whats needs to be done to remain in same admin session instead of a new one?
I am developing a MEAN stack application. I am trying to simply create a record in MongoDB from a form. I have verified in the debugger that the data binding is working between the view and the controller. In the server side controller code, checking the req.body before trying to save the record returns "undefined" (see below in the code). In the Angular controller, I have examined the "results" value in the callback when the announcement.$save function is executed and it shows the heading and details values to be populated as they should. However, the data is not persisted to the database and I get the following error:
{ [ValidationError: Announcement validation failed]
message: 'Announcement validation failed',
name: 'ValidationError',
errors:
{ details:
{ [ValidatorError: Path `details` is required.]
properties: [Object],
message: 'Path `details` is required.',
name: 'ValidatorError',
kind: 'required',
path: 'details',
value: undefined },
heading:
{ [ValidatorError: Path `heading` is required.]
properties: [Object],
message: 'Path `heading` is required.',
name: 'ValidatorError',
kind: 'required',
path: 'heading',
value: undefined } } }
What am I missing? Here is my code:
The form in my html file:
<form ng-submit="AnnouncementsVm.createAnnouncement()">
<fieldset class="form-group">
<label for="heading">Heading:</label>
<textarea class="form-control" id="heading" rows="1"
ng-model="AnnouncementsVm.announcementHeading"></textarea>
</fieldset>
<fieldset class="form-group">
<label for="details">Details:</label>
<textarea class="form-control" id="details" rows="3"
ng-model="AnnouncementsVm.announcementDetails"></textarea>
</fieldset>
<p><input type="submit" value="Submit →"><p>
</form>
The angular route for this page partial is defined as:
$routeProvider.
when('/announcements', {
templateUrl: '/views/partials/announcements.html',
controller: 'Announcements.Controller',
controllerAs: 'AnnouncementsVm'
});
Here is my controller code:
angular.module('app').
controller('Announcements.Controller', AnnouncementsCtrl);
function AnnouncementsCtrl($log, $resource) {
$log.debug('Executing AnnouncementsCtrl');
var vm = this;
var Announcement = $resource('/api/announcements');
Announcement.query( function(results) {
vm.announcements = results;
});
vm.announcements = [];
vm.createAnnouncement = function() {
var announcement = new Announcement({
heading: vm.announcementHeading,
details: vm.announcementDetails
});
announcement.$save( function(result) {
vm.announcements.push(result);
vm.announcementHeading = '';
vm.announcementDetails = '';
});
};
}
The REST API route is defined as:
app.post('/api/announcements', announcementsController.create);
The server side controller (announcements-controller.js):
'use strict';
var Announcement = require('../models/Announcement.js');
module.exports.create = function(req, res) {
var announcement = new Announcement(req.body);
console.log(req.body); // returns "undefined"
announcement.save( function(err, result) {
if (err) console.log(err);
console.log('Save Announcement Result: ' + result);
res.json(result);
});
};
module.exports.list = function(req, res) {
Announcement.find({}, function (err, results) {
if (err) throw err;
res.json(results);
});
};
And finally, I am using this Mongoose model (Announcements.js)
'use strict';
var mongoose = require('mongoose');
var AnnouncementSchema = new mongoose.Schema({
heading: {type: String, required: true},
details: {type: String, required: true},
image: {type: String, required: false}
});
module.exports = mongoose.model('Announcement', AnnouncementSchema);
How is configured your routes in Angular? Are you passing the controller as 'AnnouncementsVm'?
Have you tried to access the values of the ng-models announcementHeading and announcementDetails from the controller?
Try to put
vm.createAnnouncement = function() {
$log.log(vm.announcementHeading);
$log.log(vm.announcementDetails);
});
};
And check if you are getting the correct values
Problem solved. I had not integrated the body-parser for the route so the request wasn't being populated correctly. Here is the updated ExpressJS route:
'use strict';
var bodyParser = require('body-parser');
var path = require('path');
var announcementsController = require('../controllers/announcements-controller.js');
module.exports = function(app) {
// create application/json parser
var jsonParser = bodyParser.json();
// create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false });
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, '../../client/views/index.html'));
});
// REST API
app.get('/api/announcements', announcementsController.list);
app.post('/api/announcements', jsonParser, announcementsController.create);
};
I am trying to query all inventory.products that are of inventory.product.type computers. I am not sure how to do this. I have read the documentation and have tried a few but it seems like: db.inventory.products.find({type: { code: {$in: ['computers'] } } }) would be the proper way but never get back any products of the type.
The reason I am building my query in mongo prompt is so I can move it to my service when I have success.
Any advice?
Inventory.Product
'use strict';
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ProductSchema = new Schema({
name: {
type: String,
required: 'Name is required'
},
type: {
type: Schema.ObjectId,
ref: 'Inventory.Product.Type',
required: 'Product type is required'
},
});
mongoose.model('Inventory.Product', ProductSchema);
Inventory.Product.Type
'use strict';
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ProductTypeSchema = new Schema({
code: {
type: String,
trim: true
},
name: {
type: String,
required: 'Please enter name',
trim: true
},
});
mongoose.model('Inventory.Product.Type', ProductTypeSchema);
The solution was to create a method in my service like so:
service.autoCompleteType = function(query) {
var productList = null;
var products = [];
return Product
.find()
.populate('type')
.exec()
.then(function(products){
productList = products;
})
.then(function(quantities){
for (var i in productList) {
if (productList[i].type.code === query) {
products.push(productList[i]);
}
}
return products;
});
};
This allowed me to query type.code as required and returned everything matching query
I am having trouble using Restangular to update an existing document (products) within my Mongodb database with a new object reviews. So far I am able to add a review to the front-end with no issues, but I am having trouble posting the review details to my database. Currently when I submit a new review my code creates a new key within my products collection, but does not save the details of the review. How would I push the review to the server? Please let me know if I need to provide any additional details, or clarifications. Any help will be greatly appreciated.
Sample JSON of a product
{"_id":"xxxxx","name":"Product 1","description":"Product 1 Description","price":"1299.99","createdOn":"143767117903", "reviews":[{}]}
After adding a review this what my JSON output of my new review
{"__v":0,"_id":"xxxxxx"}
This is what I am expecting to see within my JSON output
{"__v":0,"_id":"xxxxxx","stars":4,"body":"Test review","author":"example#domain.com","createdOn":143767117903}
Project details
I used the Yeoman angular generator so I have a server and a client directories. I am using MongoDB, MongooseJS,ExpressJS, AngularJS, and NodeJS. As far as I know my server routes for my products are working as I am able to view all products, add a product, view a product (include any reviews associated with the product), and at least add a blank review.
I have a products schema that includes an Embedded Document to a reviews schema.
Products Schema
/**
* Schema for Products
*/
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var productSchema = new Schema({
name: {
type: String,
require: true,
},
description: {
type: String,
require: true,
},
shine: {
type: Number,
require: true,
},
price: {
type: Number,
require: true,
},
rarity: {
type: Number,
require: true,
},
color: {
type: String,
require: true,
},
faces: {
type: Number,
require: true,
},
images: {},
reviews: [{type: mongoose.Schema.Types.ObjectId, ref: 'Review'}],
createdOn: {
type: Date
}
});
var Product = mongoose.model('Product', productSchema);
module.exports = Product;
Reviews schema
/**
* Schema for Product Reviews
*/
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var reviewSchema = new Schema({
stars: {
type: Number
},
review: {
type: String
},
author: {
type: String
},
createdOn: {
type: Date
}
});
var Review = mongoose.model('Review', reviewSchema);
module.exports = Review;
Products Reviews Controller
(function() {
'use strict';
/**
* #ngdoc function
* #name gemStoreApp.controller:ReviewCtrl
* #description
* # ReviewCtrl
* Controller of the gemStoreApp
*/
angular.module('gemStoreApp')
.controller("ReviewCtrl", ['$scope', 'Restangular', 'productsService', function ($scope, Restangular, productsService) {
this.review();
this.addReview = function(product){
this.review.createdOn = Date.now();
var productReview = Restangular.all('/products/' + product._id + '/reviews');
productReview.post(product).then(function(newResource){
});
};
})();
Products Service
(function() {
'use strict';
/**
* #ngdoc service
* #name gemStoreApp.productService
* #description
* # productService
*/
angular.module('gemStoreApp.productService',['ngResource'])
.factory('productsService', function($resource) {
return $resource('/products/:id', {id:'#id'},{
'update': { method: 'PUT'}
});
});
})();
The solution which was provided by a co-worker is to edit the server routes for my product/reviews routed.
updated products review controller
angular.module('gemStoreApp')
.controller('ReviewCtrl', ["$scope, ,'$resource', '$Restangular', 'productsService', function ($scope, $resource, Restangular, productsService) {
this.review = {};
this.addReview = function(product){
this.review.createdOn = Date.now();
var productReview = Restangular.all('/products/' + product._id + '/reviews');
var updatedProduct = product;
productReview.post(this.review).then(function(newResource){
product.reviews.push(newResource);
});
this.review = {};
};
}]);
updated reviews route
...
router.post('/:product/reviews', function (req, res, next) {
var time = moment().formated('MMMM Do YYYY, h:mm:ss a');
var body = req.review;
var review = new Review(req.body);
review.product = req.product
review.save(function (err, review){
if (err) {return next(err);}
req.product.reviews.push(review);
req.products.save(function (err, product) {
if (err) {return next(err);}
res.json(review);
res.status(201).json({
'message': review.review + 'created'
});
});
});
...
I will also post the direct URL to the files on my GitHub project once I commit my changes.
I am connecting AngularJS with MongoLab and trying to update the "users" collection.
AngularJS resource service:
angular.module("myApp.services", ["ngResource"])
.constant({
DB_URL: "https://api.mongolab.com/api/1/databases/mydb/collections/users/:id",
API_KEY: "[SOME_RANDOM_KEY]"
})
.factory("UsersService", ["$resource", "DB_URL", "API_KEY", function($resource, DB_URL, API_KEY) {
return $resource(DB_URL, { apiKey: API_KEY, id: "#_id.$oid" }, { update: { method: "PUT" }});
}]);
This is how I am trying to update my users collection:
angular.module("myApp", ["myApp.services"])
.controller("AppController", ["$scope", "UsersService", function($scope, UsersService) {
$scope.users = [];
$scope.getAllUsers = function() {
$scope.users = UsersService.query();
};
$scope.updateUser = function(user) { // user: firstName, lastName, email
//delete user._id;
UsersService.update({}, user, function() {
$scope.users = UsersService.query();
console.log("Users updated successfully");
}, function() {
console.log("Some problems updating the user", arguments);
});
};
}]);
When I try to update the user information, it throws an exception stating:
{ "message" : "cannot change _id of a document old:{ _id: ObjectId('[SOME_RANDOM_KEY]'), firstName: \"Anup\", lastName: \"Vasudeva\", email: \"anup.vasudeva#emal.com\" } new:{ _id: {}, firstName: \"Anup\", lastName: \"Vasudeva\", email: \"anup.vasudeva#email.com\" }"
I am new to MongoDB, so I don't understand why it is creating an empty _id object for the new user instance?
Try changing your $scope.updateUser function to the following:
$scope.updateUser = function (user) {
var userId = user._id.$oid;
user._id = undefined;
UsersService.update({id: userId}, user, function () {
$scope.users = UsersService.query();
console.log("Users updated successfully");
}, function () {
console.log("Some problems updating the user", arguments);
});
};
The update/replacement object ('user'), should not contain the _id property when being passed to UsersService.update(). Mongo will not replace the _id value, so the id will stay the same after the update.
One other thing that's changed in this function is that we're passing the user id as the first parameter of the UsersService.update() function so that mongo knows which document to update.