GET request format using mongoose and angular - angularjs

In regard to the getRooms function, I expected to console.log, on partial page load (/rooms) , an array of objects containing roomName, moderator, and description as outlined by my mongoose model (Room) and data in the db, so that I could render some of this information to the page. Instead I am console logging what appears to be my index.html code as response on the client side and the server is never reached. My POST and PUT requests are working, and although this is rudimentary, it seems I am not understanding how to properly go about making this GET request. If someone could inform me as to how this is done properly, I would appreciate it.
//roomController.js
angular.module('chatApp').controller('roomController', ['$scope','$http','$location', '$cookies', function($scope, $http, $location, $cookies){
// $scope.rooms = [
// {'name': 'Biology', 'description': 'Discuss the wonders of Bio'},
// {'name': 'Literature', 'description': 'From Steinbeck to Shakespeare'},
// {'name': 'Dark Souls 3', 'description': 'Discuss gameplay from DS3'},
// {'name': 'The Life of Pablo', 'description': "Discuss Kanye West\'s the Life of Pablo"},
// {'name': 'Daredevil', 'description': 'Discuss the Netflix original Daredevil'},
// {'name': 'React JS', 'description': 'Discuss ReactJS projects'}
// ];
$scope.getRooms = function(){
$http.get('/rooms').then(function(response){
$scope.roomCount = response.data.length;
console.log(response.data.length);
console.log(response);
});
};
$scope.createRoom = function(){
var newRoom = {
roomName: $scope.roomName,
moderator: $cookies.get('currentUser'),
description: $scope.roomDescription
};
$http.post('/createRoom', newRoom).then(function(){
$scope.roomName = '';
$scope.moderator = '';
$scope.description = '';
$location.path('/createRoom');
bootbox.alert('Sucessfully created Room.');
});
};
}]);
//server side route
//get rooms
app.get('/rooms', function(req,res){
Room.find({}, function (err, rooms) {
res.send(rooms);
console.log(rooms);
});
});
//relevant part of partial page
<div class="container-fluid" id="roomsPage" data-ng-init="getRooms()">

check your serverside routes. youre logging the index.html page because your request isnt hitting any express routes. so instead it hits the app.get(*) route and its returning the html of your index.html page. make sure everything is spelled right and youre using a get on the other end instead of a post unless you mean to

Related

I'm trying to send emails from an AngularJS app based upon a date/firebase value

I'm currently working on a site for a client that needs an email reminder to be sent if a database entry is untouched for 2 days.
Example:
- Referral enters the system and is submitted to firebase
Documents must the be sent in and uploaded by one of the team. If the files haven't been uploaded within 2 days an email reminder needs to be sent to the relevant people.
I am using Firebase, Express, Node and Angular as well as nodemailer, although I am open to chanbge as I really need to get this working! Any help is much appreciated, I'm really struggling on how to get this to work, so thank you in advance!
Here is the code from my refCollection function that is sending the data to Firebase:
materialAdmin.factory('refCollection', ['$rootScope', '$firebaseAuth', 'FIREBASE_URL', '$state', '$firebaseObject', '$http', 'growlService', function($rootScope, $firebaseAuth, FIREBASE_URL, $state, $firebaseObject, $http, growlService){
var enqRef = new Firebase(FIREBASE_URL + 'tenants');
var enqObject = {
tenantRef: function(user) {
var enqRef = new Firebase(FIREBASE_URL + 'tenants')
.push({
date: Firebase.ServerValue.TIMESTAMP,
status: "amber",
refName: user.refName,
refLastName: user.refLastName,
refNum: user.refNum,
refEmail: user.refEmail,
tenName: user.tenName,
tenLastName: user.tenLastName,
tenNum: user.tenNum,
tenEmail: user.tenEmail
}); //user info
// Add UID to lead as a key/value pair
var enqId = enqRef.key();
var addIdRef = new Firebase(FIREBASE_URL + 'tenants/').child(enqId).update({
id: enqId
});
growlService.growl('Referral Added!', 'inverse');
},
addOwner: function(ref, uid) {
var noteRef = new Firebase(FIREBASE_URL + 'tenants/' + ref).update({
dateStatusChanged: Firebase.ServerValue.TIMESTAMP,
owner: uid,
status: 'green'
})
}
}//leadObj
return enqObject;
}]); //factory
I need to send an email once that date value in the enqRef variable that is pushing the array to Firebase gets more than 48 hrs ago.

Query MongoDB with Mongoose within Angular App

I have an app that needs to query my Mongo Database and return all items that match the specified criteria so they can be rendered to the DOM. I have tested the database with both postman and locally through my app, due to this I have determined that all information is being stored correctly. My problem is that I don't entirely know where the query should take place within my app.
The user will use a drop down to specify a type of business, once this is done all business that match this type should populate the DOM. Below is the code that I have so far:
This is the user controller:
angular.module('UserCtrl', [])
.controller('UserSelectController', function($scope, queryFactory) {
//list out all of our specialty types of food in the below array -- this will populate in our dropdown selection for our user_BusDirectory.html view
$scope.listOfTypes = ['Type 1', 'Type 2', 'Type 3', 'Type 4', 'Type 5', 'Type 6', 'Type 7', 'Type 8'];
//invoke function to call a GET request to get business with that type of specialty
$scope.getBusiness = function(){
console.log('You selected: ', $scope.selectedType);
queryFactory.queryType($scope.selectedType);
};
});
The following resides in my factory:
angular.module('queryService', [])
.factory('queryFactory', function($http){
var queryType = function(type){
console.log('What is the type that has been passed in: ',type)
var query = businesses.find({specialty: type}).exec(function(err, businessMatches){
if(err){
console.log(err);
return res.send({ errorMessage : err})
}else{
res.json(businessMatches);
}
});
console.log("Did query recieve all the types? :", query);
}
return {
queryType: queryType
}
});
Within my Mongo database businesses is the name of the collection that I would like to query. I keep getting ReferenceError: businesses is not defined when I try to test the function which leads me to believe that my approach is misguided.
I spent some time to give you and idea what you structure should look like.
Your API handler on the server should look like this:
app.get('api/businesses', function(req, res) {
Businesses.find({specialty: req.query.type})
.then(function(businesses){
res.json(businesses);
})
.catch(function(error){
console.log("There was error retrieving businesses" + error);
});
});
and on the Front End the factory that makes http call should look like:
angular.module('queryService', [])
.factory('queryFactory', function($http){
var getBusinesses = function(type) {
return $http({
method: 'GET',
url: 'api/businesses?type=' + type
})
};
return {
getBusinesses: getBusinesses
}
});
and Controller has to do something with data after response comes back:
angular.module('UserCtrl', [])
.controller('UserSelectController', function($scope, queryFactory) {
$scope.listOfTypes = ['Type 1', 'Type 2', 'Type 3', 'Type 4', 'Type 5', 'Type 6', 'Type 7', 'Type 8'];
$scope.getBusiness = function(){
queryFactory.getBusinesses($scope.selectedType)
.then(function(response){
// do something with response.data
// put it on $scope.businesses
});
};
});
'businesses' is undefined because it has not been assigned. Your code is missing any server calls to retrieve the data. You need:
A REST call to get the data
Suggest passing 'type' in the server call so the endpoint returns only the data needed.
queryType should return a promise ($q) that is resolved when the data is returned.

Use a custom filter with a controller

I've created a filter that checks the user id and then filters out all results in a ng-repeat that don't have that user id.
If I place my filter,
UserService.getCurrentUser()
.then(function(user_id){
$scope.user_id = user_id;
});
In my controller it works fine, but I want to keep my controller as clean as possible so I want to move it out.
I created a file called "userFilter.js" and this is the code,
angular.module('addMovieseat', [])
.filter('user_filter', function() {
UserService.getCurrentUser()
.then(function(user_id){
$scope.user_id = user_id;
});
});
But when I inject the filter into my controller I get an error,
Error: [$injector:unpr] Unknown provider: user_filterProvider <- user_filter <- addMovieCtrl
Also this is my service where I get my current user id,
(function(){
"use strict";
angular.module('addMovieseat')
.factory('UserService', function($http, $q){
return{
getCurrentUser: function(){
var user_id = null,
deferred = $q.defer();
// Get the current user id and use it to filter out all movies that do not correspond to that id in the main overview.
$http.get(('/users.json'),{ cache: true}).
success(function (data, status, headers, config) {
if (status == 200) {
deferred.resolve(data.id);
} else {
deferred.resolve(false);
console.error('Error happened while getting the user list.')
}
});
return deferred.promise;
}
}
});
})();
It sounds as if you might be better served using ng-if on your repeated items. Like this
<li ng-repeat="movie in movies" ng-if="movie.user_id == user_id"></li>
Assuming $scope.user_id in your controller is the id being checked for, and your list of movies is an array. Like this:
$scope.user_id = 'Tim';
$scope.movies = [
{name: 'Movie Title 1', user_id: 'Tim'},
{name: 'Movie Title 2', user_id: 'Jane'},
{name: 'Movie Title 3', user_id: 'Bob'}
];
This will only render the movie with user_id 'Tim'.
EDIT: Documentation for ng-if
EDIT 2: Based on the comment by OP, updated code to reflect specific issue.
i actually think what your are looking for is
<li ng-repeat="movie in movies|filter:{user_id:user:id}:strict"></li>
as shown here
https://docs.angularjs.org/api/ng/filter/filter
using ng-if might lead to weird behavior under certain circunstances make sure you read https://docs.angularjs.org/api/ng/directive/ngIf

Using Express to render an .ejs template for AngularJS and use the data inside AngularJS $scope

I hope I can explain myself with this first question I post on Stack Overflow.
I am building a small test application with the MEAN stack.
The application receives variable data from Mongoose based on an Express Route I have created.
For example the url is: localhost:3000/cities/test/Paris
Based on the name of the city the response gives me the name of the city and a description. I Know how to get this data inside the .ejs template
But thats not what I want. I want to use this data inside an ngRepeat.
Maybe this is not the right way but maybe you can help me figure this out.
The reason I want to do this is because I don't want a single page application but an Angular template that can be used over and over for each city and only uses the data that gets back from the mongoose find() results and not the whole cities array.
app.js :
var cityRoutes = require('./routes/cities');
app.use('/cities', cityRoutes);
app.set('views', './views'); // specify the views directory
app.set('view engine', 'ejs'); // register the template engine
./routes/cities/cities.js :
var express = require('express');
var citiesList = require('../server/controllers/cities-controller');
var bodyParser = require('body-parser');
var urlencode = bodyParser.urlencoded({ extended: false });
var router = express.Router();
// because this file is a fallback for the route /cities inside app.js
// the route will become localhost:3000/cities/test/:name
// not to be confused by its name in this file.
router.route('/test/:name')
.get(citiesList.viewTest)
module.exports = router;
../server/controllers/cities-controller.js :
var City = require('../models/cities');
module.exports.viewTest = function(request, responce){
City.find({ stad: request.params.name }, function(err, results){
if (err) return console.error(err);
if (!results.length) {
responce.json( "404" );
} else {
responce.render('angular.ejs', { messages:results });
// through this point everything works fine
// the angular.ejs template gets rendered correctly
// Now my problem is how tho get the results from the
// response.render inside the Angular directive
// so I can use the data in a $scope
}
});
};
../models/cities.js
var mongoose = require('mongoose');
module.exports = mongoose.model('City', {
stad: { type: String, required: true },
omschrijving: String
});
AngularJS directive :
// This is where I would like to use the messages result data
// so I can create a $scope that handles data that can be different
// for each url
// so basically I am using this directive as a template
app.directive('bestelFormulier', function () {
return {
restrict: 'E',
templateUrl: '/partials/bestel-formulier.html',
controller: ['$scope', '$http', '$resource', '$cookieStore',
function($scope, $http, $resource, $cookieStore){
// at this point it would be nice that the $scope gets the
// url based results. But I don't now how to do that..
// at this point the var "Cities" gets the REST API with
// all the cities...
var Cities = $resource('/cities');
// get cities from mongodb
Cities.query(function(results){
$scope.cities = results;
//console.log($scope.products);
});
$scope.cities = {};
}],
controllerAs: 'productsCtrl'
}
});
The database is stored like this :
[
{
stad: 'Paris',
omschrijving: 'description Paris',
},
{
stad: 'Amsterdam',
omschrijving: 'description Amsterdam',
}
]
I hope these files included helps explaining my issue.
Thanks in advance for helping me out
I figured out a way to do it...
The following changes to my code fixed my issue.
in app.js
var cityRoutes = require('./routes/cities');
app.use('/', cityRoutes);
// removed the name cities
./routes/cities/cities.js :
router.route('/cities/test/:name')
.get(citiesList.viewTest)
// added this route to use as an API
router.route('/api/cities/test/:name')
.get(citiesList.viewStad)
../server/controllers/cities-controller.js :
// added this callback so that a request to this url
// only responses with the data I need
module.exports.viewStad = function(request, responce){
City.find({ stad: request.params.name }, function(err, results){
if (err) return console.error(err);
if (!results.length) {
responce.json( "404" );
} else {
responce.json( results );
}
});
};
in my AngularJS app I added the $locationDirective and changed the following in my Angular directive to :
var url = $location.url();
var Cities = $resource('/api' + url);
// now when my .ejs template gets loaded the Angular part looks at
// the current url puts /api in front of it and uses it to get the
// correct resource
That is the way how I can use it in my $scope and use al the lovely Angular functionality :-)
Hope I can help other people with this... Eventually it was a simple solution and maybe there are people out there knowing beter ways to do it. For me it works now.

How to use $resource in Angular to work with a RESTful api

I'm trying to add some basic CRUD functionality to MEAN stack. I've created a RESTful service that works and I'm confused about how to wire it all up. I can get it to work, but I want to make sure I'm doing things the best way and not creating an unnecessary hack.
My api route for a single Person is like this:
// Find one person
app.get('/api/person/:id', function(req, res) {
Person.find ( {_id: req.params.id },
function(err, data){
res.json(data);
}
)});
// Find group of people
app.get('/api/person', function(req, res) {
// use mongoose to get all people in the database
Person.find(function(err, data) {
res.json(data);
});
This seems to work in that if I go to a URI with an ID, as in localhost://3000/api/person/23423434, I see JSON data like this:
[
{
"_id": "532d8a97e443e72ef3cb3e60",
"firstname": "Horace",
"lastname": "Smith",
"age": 33
}
]
This tells me the basic mechanics of my RESTful api are working. Now I'd like to display that data with angular in a template like so:
<h3>{{ person.firstname + ' ' + person.lastname }} </h3>
To do that, I just need to create a $scope.person object with get() or query(). Here's the relevant part of my app:
angular.module('crudApp', ['ngRoute', 'ngResource'])
.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/api/person/:id',
{
templateUrl: 'partials/person.html',
controller: 'PersonCtrl'
});
}])
.factory('Person', function($resource){
return $resource('api/person/:id', { id: '#_id'});
})
.controller('PersonCtrl', function($scope, $routeParams, Person){
$scope.person = Person.get( { id: $routeParams.id } ); // Having trouble here!
});
The trouble I'm having is that get() fails with an error (Error: [$resource:badcfg]). On the other hand, if I use Person.query(), I get back an array, which means I need to change my template to the following:
<h3>{{ person[0].firstname + ' ' + person[0].lastname }} </h3>
This works, but seems strange and isn't like what I've seen in angular tutorials. The only other solution I've found is to set $scope.person in a callback:
Person.query({ id: $routeParams.id }, function(person){
$scope.person = person[0];
});
This works with my original unmodified template. Is it the best or right way to work with RESTful apis like this? Is there a better way?
Answer: the answer is in comment below. My problem is that api is using Person.find() but should be using Person.findOne( { _id: req.params.id }); Using findOne() returns a single object.
Your api should look like this:
route -> '/api/person/:id'
return single person
route -> '/api/person'
return array of persons
then if you want to get by id, you shall use get method, or if you want to get all persons, you should use query method. Your mistake is that you shall return single object when getting by id

Resources