I have an AngularJS app that is connected to MongoDB. I have articles that I am pulling from the database that is then ng-repeated onto an article page. I have a button with Read More... that takes the user to the specific article. When the single article view becomes active I make a get request to the database to get the article._id. The get request is only working on page reload and not when I activate the view. See code below...
AngularJS Controller
app.controller('ArticleViewController', ['$scope', '$location', '$http', '$routeParams', '$window', function($scope, $location, $http, $routeParams, $window){
// $window.location.reload();
let id = $routeParams.id;
console.log(id);
$http({
cache: true,
method: 'GET',
url: '/:id'
params: { id }
}).then(function successCallback(res) {
$scope.article = res.data;
}).catch(function errorCallback(err) {
if (err) {
alert('THERE WAS AN ERROR WITH THE DATABASE');
}
});
}]);
The interesting thing is that I am getting the routeParams.id so part of the controller is working. Also, when I uncomment the $window.location.reload the article loads but it just loads the JSON object into the browser window. Thank you in advance for any help.
Routing with Express and Mongoose Schema
router.get('/:id', function(req, res, next){
Article.findById(req.params.id, function(err, article){
if(err) {
return err;
} else {
console.log(article);
res.json(article);
}
});
});
Mongoose Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var articleSchema = new Schema({
image: String,
title: String,
about: String,
article: String,
id: String
});
var Article = mongoose.model('Article', articleSchema);
module.exports = Article
Nodejs w/Express
'use strict'
const express = require('express');
const path = require('path');
// const api = require('api');
// const nodemailer = require('nodemailer');
const bodyParser = require('body-parser');
const request = require('request');
const mongoose = require('mongoose');
// const logger = require('morgan');
const env = require('./env');
const routeMw = require('./public/middleware/routing.mw');
let article = require('./public/routes/article')
let guide = require('./public/routes/guide')
const app = express();
const clientPath = path.join(__dirname, "./public");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use('/article', article);
app.use('/guide', guide)
app.use('/article/:id', article);
You have syntex error problm in http request.
You have need to change in parms paramiter i think show.
app.controller('ArticleViewController', ['$scope', '$location', '$http', '$routeParams', '$window', function($scope, $location, $http, $routeParams, $window){
// $window.location.reload();
let id = $routeParams.id;
console.log(id);
$http({
cache: true,
method: 'GET',
url: '/:id'
params:{"id": id}
}).then(function successCallback(res) {
$scope.article = res.data;
}).catch(function errorCallback(err) {
if (err) {
alert('THERE WAS AN ERROR WITH THE DATABASE');
}
});
}]);
Related
I'm trying to buld an app using files from LINK .I found that posting is where the code breaks.Has express js changed or is it syntax mistake ?
The router.post breaks once it reaches Maid.registerMaid(new Maid({... .I'm able to make it work using .save() but could anyone explain why this callback is beaking ?
Putting the code below.. sorry, i'm a beginner in M.E.A.N
API.js
var express = require('express'),
router = express.Router(),
passport = require('passport');
User = require('../models/user.js');
Maid = require('../models/maid.js');
router.post('/AddMaid', function(req, res) {
console.log(req.body, req.body.FirstName,req.body.LastName);
Maid.registerMaid(new Maid({ FirstName: req.body.FirstName }), ({LastName: req.body.LastName}), function(err, account) {
if (err) {
return res.status(500).json({err : err})
}
return res.status(200).json({status: 'Registration successful!'});
});
});
Services.js
angular.module('myApp').factory('AuthService',['$q', '$timeout', '$http', function ($q, $timeout, $http) {
var user = null;
return ({
isLoggedIn: isLoggedIn,
getUserStatus: getUserStatus,
login: login,
logout: logout,
register: register,
registerMaid: registerMaid
});
function registerMaid(Fname, Lname) {
var deferred = $q.defer();
$http.post('/maid/AddMaid', {
FirstName : Fname,
LastName : Lname
}).success(function(data, status) {
if (status === 200 && data.status) {
deferred.resolve();
} else {
deferred.reject();
}
}).error(function(data) {
debugger;
alert("Error in Services AddMaid");
deferred.reject();
});
return deferred.promise;
} }]);
Controllers.js
angular.module('myApp').controller('AddMaidController', ['$scope', '$http','$location', 'AuthService', function($scope, $http,$location, AuthService) {
console.log(AuthService.getUserStatus());
$scope.register = function () {
$scope.error = false;
$scope.disabled = true;
AuthService.registerMaid($scope.registerForm.FirstName,$scope.registerForm.LastName).then(function () {
$scope.disabled = false;
$scope.registerForm = {};
}).catch(function () {
$scope.error = true;
$scope.errorMessage = "Something went wrong!";
});
};}]);
maid.js
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var Maid = new Schema({
First_Name: String,
Last_Name: String
});
module.exports = mongoose.model('maids', Maid);
First of all you globally defined ur User and Maid modules, that is not a good practice.
Error occurs because your Maid module (Maid model on server side, i.e. Nodejs) doesnt have registerMaid method. You need to use Maid.create instead
I can't get the param of the URL which I pass when changing the state in Angular (ui router):
.state('contact.detail', {
url: '/:contactId',
templateUrl: 'detail.html',
controller: 'DetailController'
})
In Express I define an API, but the problem is in getting the param from the URL which I passed from ui router (above).
server.js
var express = require('express');
var mysql = require('mysql');
var url = require('url');
var app = express();
app.use('/', express.static('../app'));
app.use('/bower_components', express.static('../bower_components/'));
var server = require('http').createServer(app);
var bodyParser = require('body-parser');
app.jsonParser = bodyParser.json();
app.urlencodedParser = bodyParser.urlencoded({ extended: true });
//mysql connection setup
var connection = mysql.createConnection({
host : "localhost",
port: "3306",
user : "root",
password : "",
database : "db",
multipleStatements: true
});
app.get('/:id', app.urlencodedParser, function(req,res){
var id = req.params.id;
console.log(id); // => :id instead of value
connection.query('SELECT * FROM contacts WHERE contactId = ?', [id], function (error, results) {
if(error) {
throw error;
}
else {
res.end(JSON.stringify(results));
}
});
});
server.listen(3000, function () {
'use strict';
});
In log I get ":id" instead of the real value, for example "45".
I can access the API manually
Please take a look at the plunker for states details.
Since u are using ui-router (or ngRoute) , it is client side routing , if you want to call a route from your server you have to make a http call , with $http service (or $resource) , like:
//this is a example not tested.
.controller('DetailController', function($scope, $stateParams,$http){
console.log('Passed parameter contact id is:', $stateParams.contactId);
$scope.selectedContactId = $stateParams.contactId;
$http.get("localhost:3000/"+$stateParams.contactId)
.success(function(data){
//console.log(data)
})
.error(function(error,status){
})
});
I'm new to the stack and am building a test page to sort out my understanding before building my actual project. Right now, I'm just trying to take user input, save it to a database, and print it. The data should be saved in a basic Mongoose model, test. While all of the routes are open, instead of printing what the user entered it prints something in the following format:
{"_id":"55c3925b48b9dba0d896be40","__v":0}
I suspect it has something to do with the second line of this snippet from index.js:
router.post('/survey', function(req, res, next) {
var test = new Test(req.body);
test.save(function(err,test) {
if(err) {
return next(err);
}
res.json(test);
});
});
module.exports = router;
Relevent code:
All of index.js:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
//set up routes
var mongoose = require('mongoose');
var Test = mongoose.model('Test');
router.get('/survey', function(req, res, next) {
Test.find(function(err, tests) {
if(err) {
return next(err);
}
res.json(tests);
});
});
router.post('/survey', function(req, res, next) {
var test = new Test(req.body);
test.save(function(err,test) {
if(err) {
return next(err);
}
res.json(test);
});
});
module.exports = router;
Tests.js (model):
var mongoose = require('mongoose');
var TestSchema = new mongoose.Schema({
'name': String,
});
module.exports = mongoose.model('Test', TestSchema);
Relevant bits of angular code:
routerApp.factory('tests', ['$http', function($http){
var o = {
tests: []
};
o.getAll = function() {
return $http.get('/survey').success(function(data){
console.log('get all sees data as:' + data);
angular.copy(data, o.tests);
});
};
o.create = function(test) {
console.log('create sees test as' + test);
return $http.post('/survey', test).success(function(data){
o.tests.push(data);
console.log('Data:' + data);
});
};
return o;
}]);
routerApp.controller('FormCtrl', ['$scope', 'tests',
function($scope, tests){
$scope.test = tests.tests;
$scope.addTest = function(){
if(!$scope.text || $scope.text === '') { return; }
tests.create({
name: $scope.text
});
$scope.text = '';
};
}
]);
I suspect this is a matter of not understanding what kind of object req is, but I'm not entirely positive. How would I go about making this code save data in the format described in the mongoose model?
If you call .toObject() on the document object (res.json(test.toObject())), you should get a plain object back containing the data in that document.
Try to console.log(req.body). If it's empty, then try adding app.use(bodyParser.json()) somewhere before your routes are defined (and be sure to install it with npm and require it first).
When you POST some sort of JSON, it isn't available in req.body by default. You need bodyParser to parse the incoming data and make it available in req.body. See https://medium.com/#adamzerner/how-bodyparser-works-247897a93b90 for more info.
I'm trying to pull an object by its _id from the mongodb database and place it in the $scope for later use. However when I try to do so, I get every object in the database, instead of the one I requested. I'm new to the mean-stack and do not understand what I am doing wrong.
If you have any further question please let me know.
server.js
var express = require('express'),
app = module.exports = express(),
bodyParser = require('body-parser'),
mongoose = require('mongoose'),
productsController = require('./server/controllers/products-controller');
mongoose.connect('mongodb://localhost:27017/mean-demo');
app.use(bodyParser());
app.get('/', function (req, res) {
res.sendfile(__dirname + '/client/views/index.html');
});
app.get('/product/*', function (req, res) {
res.sendfile(__dirname + '/client/views/index.html');
});
app.use('/js', express.static(__dirname + '/client/js'));
app.use('/css', express.static(__dirname + '/client/css'));
app.use('/images', express.static(__dirname + '/client/images'));
app.use('/views', express.static(__dirname + '/client/views'));
//REST API
app.get('/api/products', productsController.products);
app.get('/api/products/:productId', productsController.product);
app.listen(3000, function() {
console.log('I\'m Listening...');
});
app.js
var app = angular.module('productApp', ['ngResource', 'ngRoute']);
app.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: '/views/productsoverview.html',
controller: 'productsController'
})
.when('/product/:productId', {
templateUrl: '/views/productFocus.html',
controller: 'productFocusController'
})
.otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true)
}]);
app.controller('productsController', ['$scope', '$resource',
function($scope, $resource) {
var Product = $resource('/api/products');
$scope.products = [];
Product.query(function (results) {
$scope.products = results;
});
}]);
app.controller('productFocusController', ['$routeParams', '$scope', '$resource',
function($routeParams, $scope, $resource) {
var Product = $resource('/api/products/:productId',{productId:'#productId'});
Product.productId = $routeParams.productId;
console.log(Product.productId);
Product.query(function (result) {
console.log(result);
$scope.product = result;
});
}]);
productsController
var Product = require('../models/product');
exports.products = function (req, res) {
Product.find({}, function (err, results) {
res.json(results);
});
};
exports.product = function (req, res) {
Product.findOne({_id:req.params.productId}, function (err, obj) {
res.json(obj);
});
};
You are using ngResource a bit wrong.
Try to write a single resource, e.g.
app.resource('Product', ['$resource'
function($resource) {
return $resource('/api/products/:id', {id: '#id'},
{
'update': { method:'PUT' }
});
}]);
Now you can inject this resource into your controller:
app.controller('productsController', ['$scope', 'Product',
function($scope, Product) {
$scope.products = [];
// this gets ALL products (query)
Product.query(function (results) {
$scope.products = results;
});
// this gets ONE product by id (get)
Product.get({id: 123})
.$promise.then(function(product) {
$scope.product = product;
});
});
}]);
ngResource documentation
I have a new userService that is working fine, but I would like to initialize certain vars only when a new user starts up the site.
For example, I would like ONLY fetch the user's unique session ID just once, and access that ID from any controller. My understanding is that I'll init the sessionID vars once in my service, then each time I call the service I will NOT need to make the http call again.
Would app.js serve my purposes in this case ? Again, I need to sessionID available to every controller WITHOUT the need to make an http call each time (i.e. caching the sessionID in some way).
Here's my current app.js for example :
(function () {
'use strict';
var app = angular.module('app', [
// Angular modules
'ngAnimate',
'ngRoute',
'ngSanitize',
// Custom modules
'common', // common functions, logger, spinner
'common.bootstrap', // bootstrap dialog wrapper functions
// 3rd Party Modules
'ui.bootstrap', // ui-bootstrap (ex: carousel, pagination, dialog)
'kendo.directives', // Kendo UI
'app.customcontrollers' // Language/Currency settings
]);
app.run(['$route', function ($route) {
// Include $route to kick start the router.
}]);
})();
And my userService (this.openUserSession pulls the sessionID) :
(function () {
'use strict';
var app = angular.module('app');
app.service('userService', ['$http', 'common', userService] );
function userService($http, common){
// define private vars
var _rzEnvParams = [];
var _sessionID = '';
var _rzInitStatus = '';
var _domain = '';
var _port = '' ;
var _controllerpath = '';
var _space = '';
var _env = '';
var _clariteconfig = '';
var $q = common.$q;
this.initRz = function (rzEnvParams) {
// some lines of code omitted for brevity...
var url = ... ;
var deferred = $q.defer();
deferred.notify("Getting Rage init parameters...");
var retval = [];
$http({
method: 'GET',
encoding: 'JSON',
headers: {
'Access-Control-Allow-Origin': 'true'
},
withCredentials: true,
url: url
}).success(function (data, status, headers, config) {
retval = data;
deferred.resolve(retval);
});
return deferred.promise;
}
this.openUserSession = function(domain, port, controllerpath, user, pass) {
domain = "localhost:"
port = "49479";
controllerpath = "/api/open";
user = "";
pass = "";
var url = "http://" + domain + port + controllerpath + "?userid=" + user + "&pass=" + pass;
var deferred = $q.defer();
deferred.notify("Opening user session...");
var retval = [];
$http({
method: 'GET',
encoding: 'JSON',
headers: {
'Access-Control-Allow-Origin': 'true'
},
withCredentials: true,
url: url
}).success(function (data, status, headers, config) {
retval = data;
deferred.resolve(retval);
});
return deferred.promise;
}
}
})();
I currently call openUserSession() from my dashboard.js as follows :
userService.openUserSession().then(function (data) {
response = data[0].split(",")
status = response[0];
vm.sessionID = response[1].split('"')[1];
});
but wouldn't I need to somehow session sessionID within userService so it becomes available in cache ?
thanks in advance.
Bob