Why can't I display data from Mongodb with Angular - angularjs

and I am trying to display a collection called books in mongodb but for some reason I run into an ng-repeat dupes error. Also the data retrieved from my $http.get operation returns the HTML syntax of the entire page for some reason instead of accessing the data from the books collection. Thing is I created other programs prior to this where I had absolutely no problem with ng-repeat and they still work, the difference being the angular version is older. I am thinking that is the problem. If you have any insight on what I am doing wrong I would appreciate it. Thank you
Error:
Error: [ngRepeat:dupes]
http://errors.angularjs.org/1.3.14/ngRepeat/dupes?p0=book%20in%20library&p1=string%3A%3C&p2=%3C
Controller code:
var app = angular.module("myApp", []);
app.controller("bookCtrl", function($scope, $http) {
var refresh=function(){
$http.get('http://localhost:3000/storeHome').success(function(response){
console.log("I got the data I requested");
console.log(response); //returns HTML of the page instead of an object
$scope.library = response;
$scope.book="";
});
};
refresh();
});
Route code:
var express = require('express');
var router = express.Router();
var Book =require('../../models/book');
router.get('/', function(req, res) {
res.render('bookStore/storeHome');
});
//get all books from the database
router.get('/',function(req,res,next){
Book.find(function(err, books) {
if (err)
res.send(err);
console.log(books);
res.json(books);
});
});
Book model:
var mongoose = require('mongoose');
var BookSchema = new mongoose.Schema({
title: String,
author: String,
publisher: String,
year: Number
});
module.exports=mongoose.model('Book', BookSchema);
HTML
<div class="container" ng-app="myApp" ng-controller="bookCtrl">
<table class="table">
<!--omitted code in between -->
<tr ng-repeat="book in library"> <!-- I tried track by $index and it didn't work-->
<td>{{book.title}} </td>
</tr>
</div>

I think the nodejs response is wrong. The res.json...try another options please.
EDIT: LIke this: res.status(200).send({myBooksList:list})
or this: res.send(200,{myBooksList:list})
Im still not sure :D, sorry.

Change your template's ng-repeat to :
<tr ng-repeat="book in library track by $index">
It doesn't handle duplicate data very well as it tries to find an identifier that is unique for every item. But since there's duplicates in the data angular is unable to do so... We can use the assigned repeat index to track the item by.

This might work:
Book.find(function(err, books) {
if (err)
res.send(err);
res.end(JSON.stringify(books));
}
}));

Related

Unable to bind Json Data with Table Header using AngularJS

Im getting data in this format from api, but when i try binding it to table using angularjs it is creating empty space instead of values. Im also getting more then one table from some Api's please explain who to bind different datatables in different tables too. thanks
{"Table":
[{
"SchoolId":1,
"schoolname":"Microsoft",
"SCHOOLCODE":"29911583",
"WEBSITE":"JLR",
"USEREMAIL":"faucibus#aliquamiaculislacus.org",
"PHONE":"841-9331",
"ADDRESS1":"682-5760 Felis Street",
"ISACTIVE":0,
"PLANTYPE":3
}]
}
Angular Controller
SMSApp.factory('GetStudentService', function ($http) {
studobj = {};
studobj.getAll = function () {
var stud=[];
stud = $http({ method: 'Get', url: 'http://localhost:58545/api/Student?Studentid=1' }).
then(function (response) {
return response.data;
});
return stud;
};
return studobj;
});
SMSApp.controller('studentController', function ($scope, GetStudentService) {
$scope.msg = "Welcome from Controller";
GetStudentService.getAll().then(function (result) {
$scope.school = result;
console.log(result);
});
});
HTML Code
<tbody ng-controller="studentController">
<tr ng-repeat="schools in school track by $index">
<td>{{schools.SchoolId}}</td>
<td>{{schools.schoolname}}</td>
<td>{{schools.SCHOOLCODE}}</td>
<td>{{schools.WEBSITE}}</td>
<td>{{schools.USEREMAIL}}</td>
</tr>
</tbody>
WHAT I GET
Change in your Angular Controller :
SMSApp.controller('studentController', function ($scope, GetStudentService) {
$scope.msg = "Welcome from Controller";
GetStudentService.getAll().then(function (result) {
/********************* Changed Here ********************/
$scope.school = JSON.parse(result._body); // Or only JSON.parse(result)
$scope.school = $scope.school.table;
});
});
And your HTML Code :
<tbody ng-controller="studentController">
<tr ng-repeat="schools in school track by $index">
<td>{{schools.SchoolId}}</td>
<td>{{schools.schoolname}}</td>
<td>{{schools.SCHOOLCODE}}</td>
<td>{{schools.WEBSITE}}</td>
<td>{{schools.USEREMAIL}}</td>
</tr>
</tbody>
Naming the data school is confusing. Do instead:
GetStudentService.getAll().then(function (data) {
$scope.tableObj = data;
console.log(data);
});
<tbody ng-controller="studentController">
<tr ng-repeat="school in tableObj.Table track by school.SchoolId">
<td>{{school.SchoolId}}</td>
<td>{{school.schoolname}}</td>
<td>{{school.SCHOOLCODE}}</td>
<td>{{school.WEBSITE}}</td>
<td>{{school.USEREMAIL}}</td>
</tr>
</tbody>
From the Docs:
Best Practice: If you are working with objects that have a unique identifier property, you should track by this identifier instead of the object instance, e.g. item in items track by item.id. Should you reload your data later, ngRepeat will not have to rebuild the DOM elements for items it has already rendered, even if the JavaScript objects in the collection have been substituted for new ones. For large collections, this significantly improves rendering performance.
— AngularJS ng-repeat API Reference
Just replace your result with result.Table in your controller because if you properly see your response it is inside "Table" named array. Try this you should be able to see your records
SMSApp.controller('studentController', function ($scope, GetStudentService) {
$scope.msg = "Welcome from Controller";
GetStudentService.getAll().then(function (result) {
$scope.school = result.Table;
console.log(result);
});
});
Note: I have replaced your API call in the jsfiddle link with the response mentioned in the question.
JSFiddle Link : http://jsfiddle.net/zu8q7go6/9/

Angular JS ng-repeat doesn´t showing data correctly

I have a strange problem when using ng-repeat.
Only as additional information, I am using ui-router as well.
I did a test with a simple markup that query some data in my local node server and shows with ng-repeat.
To make the test, I click a button to add a new row to server and next, I query the server again to get the new rows updated.
The problem is that the server return correctly all data with the new row added included, but ng-repeat is no showing the rows just added.
Here is more details of the problem.
Firstly, when the page is loaded I have
RowId
1
2
After I click the "Add and Refresh Row" button, I´d expect to have on the screen:
RowId
1
2
5
But I still have only:
RowId
1
2
In console,I checked the return data from my server after I add a row and the data returned is:
{id:1,name:'John Doe'},
{id:2,name:'Mary Doe'}
{id:5,name:'teste'}
where item id=5 is the row just added, buit it doesn´t appears with ng-repeat.
What am I doing wrong?
//markup
<div ng-controller="configClinicaClinicaCtrl">
<a class="btn btn-sm btn-success" ng-click="saveClinica()">Add and Refresh Row</a>
<div>RowId</div>
<div ng-repeat="row in dados track by $index">
{{row.id}}
</div>
</div>
//local server with server.js script at node.js
var clinicas=[
{id:1,name:'John Doe'},
{id:2,name:'Mary Doe'}
];
//get clinicas
app.get('/clinicas', function(req, res) {
res.json(clinicas);
});
//insert clinica
app.post('/clinicas', function(req, res) {
clinicas.push(req.body);
res.json(true);
});
//controller
angular.module("clinang").controller('configClinicaClinicaCtrl',['$scope','$http', '$state', function($scope,$http, $state) {
$scope.dados={};
$scope.clinica={};
var refreshData=function(){
$http.get('/clinicas').then(function(response){
$scope.dados=response.data;
}, function(error){
console.log(error)
});
}
refreshData();
$scope.saveClinica=function(){
$scope.clinica.id=5;
$scope.clinica.nome='teste';
var clinica=$scope.clinica;
$http.post('/clinicas',{clinica}).then(function(response){
refreshData();
}, function(error){
console.log(error)
})
}
}]);
Whenever you do some form of operation outside of AngularJS, such as doing an API call you need to let AngularJS know to update itself. Try this,
var refreshData=function(){
$http.get('/clinicas').then(function(response){
$scope.dados=response.data;
$scope.$apply();
}, function(error){
console.log(error)
});
}

Using MEAN to store data

I need help with a school project. Im making an app for creating and updating a list of issues that needs solving.
I have an input filed where im supposed to be insertingen the issue and then it should generate an ID, a status of "Open" and a datestamp.
Then the issue will show up in my output table. I have solved that i can display whats in the databas. Now i need to solve the part where im storing new data.
My plan is to use ng-click on my button AddIssue and call a function also named AddIssue. Then using $http post to send the data trough and then use moongose to store the data
HTML
<div ng-controller="inputCtrl">
<p>New issue <input class="form-control" type="text" ng-model="newIssue"></p>
<button ng-click="AddIssue()"> Add </button>
</div>
<div ng-controller="tableCtrl">
<table class="table table-striped">
<thead>
<tr>
<th>Status</th>
<th>Issue</th>
<th>Date</th>
<th>ID</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="issue in issueList">
<td>{{issue.status}}</td>
<td>{{issue.issue}}</td>
<td>{{issue.date}}</td>
<td>{{issue.id}}</td>
</tr>
</tbody>
</table>
</div>
My JS file controller.js
var myApp = angular.module('myApp', []);
// Controller for input
myApp.controller('inputCtrl', function($scope) {
// Call function when click on AddIssue btn
$scope.AddIssue = function() {
console.log("Click click....")
// Use Post to send data to database
$http.post('/issueList').sucess( function(response){
$scope.newIssue = 'New issue';
})
}
}); // End of input
server.js
/* Connect to db issues */
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/issues');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
/* Connect to MongoDB */
db.once('open', function (callback) {
console.log("Connected to db");
// Created b-schema
issueSchema = mongoose.Schema({
id: String,
issue: String,
date: String,
status: String
});
// Create Model
Issue = mongoose.model('Issue', issueSchema );
This is so far that i have come, and now i need help with first how to send data from controller.js to server.js
And second using mongoose to store it on my mongodb issues
You need to define a route in your server.js for your POST and inside it you can save your issue object in mongodb.
Something like:
//addIssue
app.post('/addIssue', function(request, response) {
var issue = new Issue({
id: request.body.id,
issue: request.body.issue,
date: request.body.date,
status: request.body.status
});
return issue.save(function(err) {
if(!err) {
return response.send(issue);
} else {
console.log("ERROR adding issue:" + err);
}
});
});
You need to install some npm packages too. For example:
body-parser (npm install body-parser)
express (npm install express)
etc.
Also you need to import them on your server.js file using:
var express = require('express');
var bodyParser = require ('body-parser');
This is just an example to clarify the idea. On a production environment the things are a little different.
Take a look at:
https://scotch.io/tutorials/setting-up-a-mean-stack-single-page-application

Not fetching data with Angular JS

I'm trying to build an app with Angular JS that fetches data from a Django REST API.
I have this script
var userListApp = angular.module('userListApp', ['ngResource']);
userListApp.factory('Classroom', function($resource) {
return $resource('/classrooms/:id/',
{'query': {method: 'GET', isArray:false}}
);
});
userListApp.controller('UsersController', function($scope, Classroom) {
Classroom.query(function(data) {
$scope.classrooms = data;
});
});
and this is the html
<div ng-app="userListApp">
<div ng-controller="UsersController">
<table class="table table-striped">
<thead>
<tr>
<th>Classroom</th>
<th>School</th>
<th>Academic year</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="classroom in classrooms">
<td>{{classroom.classroom}}</td>
<td>{{classroom.school}}</td>
<td>{{classroom.academic_year}}</td>
</tr>
</tbody>
</table>
</div>
</div>
But I'm getting this error in the console
Error: $resource:badcfg
Response does not match configured parameter
Error in resource configuration for action query. Expected response to contain an array but got an object (Request: GET /classrooms)
(from the error reference page of Angular JS)
I was looking at some answers here on stackoverflow, and came to this one, and I tried to do what they say
userListApp.factory('Classroom', function($resource) {
return $resource('/classrooms/:id/',
{method: 'classrooms', id: '*'},
{'query': {method: 'GET', isArray:false}}
);
});
And I'm getting no error, but no data either. There are, however, some tables on the webpage, like if it's trying to "catch" something, here's a screenshot
UPDATE:
I've tried to put this line
return $resource('/classrooms/?format=json',
Instead of this
return $resource('/classrooms/:id/',
on the Angular app, and there's no data, but, if I go to developer tools on Network -> XHR, I get the json data
[{"school":{"id":1,"school_name":"IPSIA F. Lampertico","address":"Viale Giangiorgio Trissino, 30","city":"Vicenza"},"academic_year":"2015/2016","classroom":"1^A","floor":0,"students":[{"classroom":1,"first_name":"Stefano","last_name":"Rossi","gender":"M","birthday":"1998-06-22"},{"classroom":1,"first_name":"Luca","last_name":"Possanzini","gender":"M","birthday":"1999-11-22"}]
but, as I said, that data is not shown on the tables in the html.
UPDATE 2:
After adding "?format=json'" to the resource url, I get the exact amount of rows (in my data I have three classrooms, so I get three rows in the HTML table), but no data in it.
UPDATE 3:
I've added this line to debug the code
userListApp.controller('UsersController', function($scope, Classroom) {
Classroom.query(function(data) {
$scope.classrooms = data;
console.log(data); <--- NEW LINE FOR THE DEBUG
});
});
and now I get this, on the console log
Your data is not in the correct format. The data you posted has missing }] in the end. Recheck your server response.
I replicated the whole scenario on my machine and your code worked perfectly fine.
HTML: Same as yours.
Script:
var userListApp = angular.module('userListApp', ['ngResource']);
userListApp.factory('Classroom', function($resource) {
return $resource('http://localhost:9000/classrooms/1', //changed this line only.
{'query': {method: 'GET', isArray:false}}
);
});
userListApp.controller('UsersController', function($scope, Classroom) {
Classroom.query(function(data) {
$scope.classrooms = data;
});
});
http://localhost:9000/classrooms/1 returns just the data that you specified with }] appended at the end.
OUTPUT:

ASP.Net WEB API AND ANGULAR Not outputting one column vs another

I was able to set up a asp.net web api and scaffolding to my sql server database. The return of the records from sql server appears to be JSON. The model has a few tables linked to each other by foreign keys and only has 2 records right now. Comp_Id = 1 and 2. The results to my local api looks like this:
[{"ASSOC_INC_OFF":[{"OFFICERINVOLVEDs":[],"AIO_ID":1,"COMP_ID":1,"OFCNUM":1,"LINK_TYPE":null}],"CRITICALINCIDENTs":[{"CIType":"Physical Force resulting in Death or Serious Bodily Injury","CINotice":null,"CIMonitorRolledOut1":null,"CIDAMonitored":null,"CIOIMQuestions":null,"CICharged":null,"CIMonitor1":null,"CIMonitor2":null,"CINotes":null,"CIOfcCharges":null,"CIOutcome":null,"COMP_ID":1,"RolledOut_DT":null,"CI_ID":1,"CINotice_DT":"2016-01-07T00:00:00","CIOIMAllegNotes":null,"CIMonitorRolledOut2":null,"CIMonitorRolledOut3":null,"CIMonitorRolledOut4":null,"CIMonitorRolledOut5":null,"CIMonitorRolledOut6":null,"CIMonitorRolledOut7":null}],"COMP_ID":1,"FileNum":"case1","Received_DT":"2016-01-21T00:00:00","Completed_DT":null,"OIMIntake_DT":null,"Status":null,"Occurred_DT":null,"ComplaintType":null,"Source":"Chiefs Office","Precinct":"District 2","AddrCity":null,"AddrState":null,"AddrZip":null,"CaseSummary":null,"IABNotified_DT":null,"ClosureLetSent_DT":null,"CaseType":null,"OIMOutcome":null,"InitialFinding":null,"ClosedFindings":null,"OIMRecFinding":null,"timestamp":null,"Department":"DSD","Address":null,"DeclineReason":null,"Filenum2":null,"Filenum3":null,"OIMDiscRev_DT":null,"OIMInvRev_DT":null,"OIMInvRoute_DT":null,"OIMDiscRoute_DT":null,"CRORoute_DT":null},{"ASSOC_INC_OFF":[],"CRITICALINCIDENTs":[{"CIType":"Officer/Deputy-Involved Shooting","CINotice":null,"CIMonitorRolledOut1":null,"CIDAMonitored":null,"CIOIMQuestions":null,"CICharged":null,"CIMonitor1":null,"CIMonitor2":null,"CINotes":null,"CIOfcCharges":null,"CIOutcome":null,"COMP_ID":2,"RolledOut_DT":null,"CI_ID":2,"CINotice_DT":null,"CIOIMAllegNotes":null,"CIMonitorRolledOut2":null,"CIMonitorRolledOut3":null,"CIMonitorRolledOut4":null,"CIMonitorRolledOut5":null,"CIMonitorRolledOut6":null,"CIMonitorRolledOut7":null}],"COMP_ID":2,"FileNum":"cw1","Received_DT":"2016-01-03T00:00:00","Completed_DT":null,"OIMIntake_DT":null,"Status":"Active","Occurred_DT":null,"ComplaintType":null,"Source":"Citizen Walk-in","Precinct":"District 7","AddrCity":null,"AddrState":null,"AddrZip":null,"CaseSummary":null,"IABNotified_DT":null,"ClosureLetSent_DT":null,"CaseType":"District-Bureau","OIMOutcome":"Satisfactory","InitialFinding":"Formal","ClosedFindings":null,"OIMRecFinding":"Decline","timestamp":null,"Department":"DSD","Address":null,"DeclineReason":"Body Worn Camera","Filenum2":null,"Filenum3":null,"OIMDiscRev_DT":null,"OIMInvRev_DT":null,"OIMInvRoute_DT":null,"OIMDiscRoute_DT":null,"CRORoute_DT":null}]
I am able to bind COMP_ID to my view but when I add in CIType, nothings appears.
console.log($scope.complaints) returns:
My Controller looks like this:
app.controller('UpdateController', function ($scope, ComplaintService) {
getCities();
function getCities() {
ComplaintService.getCities()
.success(function (complaints) {
$scope.complaints = complaints;
})
.error(function (error) {
$scope.status = 'Unable to load customer data: ' + error.message;
});
}
});
My service looks like this:
app.factory('ComplaintService', ['$http', function ($http){
var urlBase = 'http://localhost:63942/api';
var ComplaintService = {};
ComplaintService.getCities = function () {
return $http.get(urlBase+ '/complaints');
};
return ComplaintService;
}]);
and my index looks like this:
<div class="row">
<div class="col-md-3" ng-controller="UpdateController">
<table class="table">
<tr>
<th>Id</th>
<th>CI TYPE</th>
<tr ng-repeat="a in complaints">
<td>{{a.COMP_ID}}</td>
<td>{{a.CIType }}</td>
</table>
</div>
I am certainly confused about why I can render out only COMPID but not the rest of this api contents as it is all listed under localhost:###/api/complaints.
var someResultArray = [];
$scope.complaints.forEach(function(elem){
//basically checks if this exists in the object to avoid undefined issues
if(elem.ASSOC_INF_OFF){
elem.ASSOC_INF_OFF.forEach(function(assoc){
//do something with each assoc, ex: push it to another array
someResultArray.push(assoc);
});
}
});
an object in javascript can be treated by dotting yourself down, or you can also address its content by index, even though its an object. So you could write elem["ASSOC_INF_OFF"], and it would still work.

Resources