ngRepeat:dupes when trying to fetch from database - angularjs

I am constantly getting the mentioned error no matter what I try. The error stops when I comment out the "fetchCourses()" in courses.js file. I am guessing the error is somewhere in the http request but I cannot figure it out.
Here are my code snippets.
courses.js (controller)
var app = angular.module("app");
app.controller('coursesCtrl', ['$scope', 'Courses', '$routeParams', function ($scope, Courses, $routeParams) {
function fetchCourses() {
Courses.getCourses({}).then(function (res) {
$scope.courses = res.data;
}, function (err) {
console.log(err);
});
}
fetchCourses();
$scope.modal = {
title: "Modal",
btnText: "Ok",
save: function () {
if ($scope.modal.type == 'course_delete') {
Courses.deleteCourse($scope.modal.req).then(function (res) {
if (res.status == 200) {
$scope.courses.splice($scope.modal.req.index, 1);
$("#course_modal").modal("hide");
}
}, function (err) {
console.log(err);
});
} else if ($scope.modal.type == 'course_create') {
Courses.createCourse($scope.modal.req).then(function (res) {
$scope.courses.unshift(res.data);
$("#course_modal").modal("hide");
}, function (err) {
console.log(err);
});
} else if ($scope.modal.type == 'course_edit') {
$scope.courses[$scope.modal.req.index] = $scope.modal.req.course;
$("#course_modal").modal("hide");
$scope.modal.req.course = null;
}
},
type: "default",
req: {},
};
$scope.createCourse = function () {
$("#course_modal").modal("show");
$scope.modal.title = "Create course";
$scope.modal.btnText = "Create";
$scope.modal.type = "course_create";
$scope.modal.req = {};
};
$scope.editCourse = function (index) {
$("#course_modal").modal("show");
$scope.modal.title = "Edit course";
$scope.modal.btnText = "Ok";
$scope.modal.type = "course_edit";
$scope.modal.req.index = index;
};
$scope.deleteCourse = function (index) {
$("#course_modal").modal("show");
$scope.modal.title = "Delete course";
$scope.modal.btnText = "Yes";
$scope.modal.type = "course_delete";
$scope.modal.req.index = index;
};
}]);
Route.js
var Students = require('../../models/students');
var Courses = require('../../models/courses');
var Departments = require('../../models/departments');
var Exams = require('../../models/exams');
var ObjectId = require('mongoose').Types.ObjectId;
var bodyParser = require('body-parser');
module.exports = function (app) {
app.use(bodyParser.urlencoded({
extended: true
}));
app.post('/getCourses', (req, res) => {
Courses.find({}).exec(function (err, documents) {
res.send(documents);
console.log(documents);
});
});
app.post('/createCourse', (req, res) => {
var data = {
coursesName: req.body.coursesName,
coursesProfessor: req.body.coursesProfessor,
coursesDepartment: req.body.coursesDepartment,
coursesNumStudents: req.body.coursesNumStudents,
};
Courses.create(data, function (err, document) {
if (err) return res.status(500).send({
message: "Sorry! There was a problem creating a course."
});
res.send(document);
console.log(document);
});
});
};
menu.js (aka header)
var menu = angular.module("menu", []);
menu.controller('menuCtrl', ['$scope', '$location', function ($scope, $location) {
/*
if (notloggedin){
window.location.replace("/");
}
*/
$scope.logout = function () {
window.location.replace("/");
}
$scope.url = $location.url();
console.log($location.url());
}]);
menu.service('Courses', ['$http', function ($http) {
var Headers = {
'Content-Type': 'application/x-www-form-urlencoded',
}
var transformReq = function (obj) {
var str = [];
for (var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
}
this.getCourses = function (req) {
return $http({
method: 'POST',
url: '/getCourses',
headers: Headers,
transformRequest: transformReq,
data: req
});
}
this.createCourse = function (req) {
return $http({
method: 'POST',
url: '/createCourse',
headers: Headers,
transformRequest: transformReq,
data: req
});
}
}]);
And the courses.html
<div class="wrapper">
<div ng-include="'header/menu.html'"></div>
<div class="main-panel">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar bar1"></span>
<span class="icon-bar bar2"></span>
<span class="icon-bar bar3"></span>
</button>
<a class="navbar-brand" href="#">Courses</a>
</div>
</div>
</nav>
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="header">
<h4 class="title">Courses List</h4>
<p class="category">Here is a list of all courses</p>
<button class="btn btn-success" style="float:right" ng-click="createCourse()">Create Course</button>
</div>
<div class="content table-responsive table-full-width">
<table class="table table-striped">
<thead>
<th>Name</th>
<th>Professor</th>
<th>Department</th>
<th>Num of Students</th>
<th>#</th>
</thead>
<tbody>
<tr ng-repeat="c in courses">
<td>{{c.coursesName}}</td>
<td>{{c.coursesProfessor}}</td>
<td>{{c.coursesDepartment}}</td>
<td>{{c.coursesNumStudents}}</td>
<td>
<a href="" ng-click="editCourse($index)">Edit
</a> /
<a href="" ng-click="deleteCourse($index)">Delete
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="course_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h5 class="modal-title" id="modalLabel">{{modal.title}}</h5>
</div>
<div class="modal-body">
<div class="row">
<div class="col">
<form ng-if="modal.type == 'course_create' || modal.type == 'course_edit'">
<div class="form-group">
<label for="coursesName">Name</label>
<input type="text" class="form-control" ng-model="modal.req.course.coursesName" ng-disabled>
</div>
<div class="form-group">
<label for="coursesProfessor">Professor</label>
<input type="text" class="form-control" ng-model="modal.req.course.coursesProfessor" ng-disabled>
</div>
<div class="form-group">
<label for="coursesDepartment">Department</label>
<input type="text" class="form-control" ng-model="modal.req.course.coursesDepartment" ng-disabled>
</div>
<div class="form-group">
<label for="coursesNumStudents">Number of Students</label>
<input type="text" class="form-control" ng-model="modal.req.course.coursesNumStudents" ng-disabled>
</div>
</form>
<div ng-if="modal.type == 'course_delete'">
Are you sure you want to delete this course?
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-success" ng-click="modal.save()">{{modal.btnText}}</button>
</div>
</div>
</div>
</div>

This means that $scope.courses have some values which are duplicate. Duplicate keys are banned because AngularJS uses keys to associate DOM nodes with items.
So in this case you can use track by $index So repeated items will be tracked by its index.
<tr ng-repeat="c in courses track by $index">{{value}}</tr>

Related

Can we use jquery function inside angularjs

I have one table in jquery,In which when I click delete icon I need to display bootstrap modal to perform delete action.I did it using jquery but I dont know to do it in angular..Can anyone give me some suggestions?
<body ng-app="intranet_App">
<div class="container">
<div class="modal" id="deleteProject">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body" id="confirmMessage">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" id="confirmOk">Ok</button>
<button type="button" class="btn btn-default" id="confirmCancel">Cancel</button>
</div>
</div>
</div>
</div>
<div class="col-xs-12 margin20 padding table-responsive">
<table class="col-xs-12 table table-hover table-bordered" id="projectList" ng-controller="myCtrl">
<thead class="colorBlue">
<tr><th>Project Name</th><th>Client</th><th>Client Co-ordinator</th><th>Action</th></tr>
</thead>
<tbody id="projectListTBody" >
<tr ng-repeat="x in projectList | filter:ProjectName">
<td>{{ x.ProjectName}}</td>
<td>{{ x.Client}}</td>
<td>{{ x.OnsiteCoordinator}}</td>
<td>
<i class="fa fa-user-plus fa-2x" ng-click="addResource()"></i>
<i class="fa fa-edit fa-2x" ng-click="editProj(x.Id)"></i>
<i class="fa fa-trash fa-2x" data-toggle="modal" data-target="#myModal" data-dismiss="modal" ng-click="deleteProject(x.Id)"></i>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
<script>
var app = angular
.module("intranet_App", [])
.controller("myCtrl", function ($scope, $http) {
$scope.projDetails = [];
$http.post('/Project/getProjectsList')
.then(function (response) {
console.log(response)
$scope.projectList = response.data;
})
$scope.editProj = function (x) {
$scope.projectDetails(x);
window.location = "/Project/EditProject?id=" + x;
}
$scope.projectDetails = function (x) {
$scope.projDetails.push(x);
$scope.json = angular.toJson($scope.x)
console.log($scope.json)
}
$scope.addResource = function () {
window.location = "/Project/ProjectRes";
}
});
</script>
This is my jquery methods:
function deleteProject(control) {
event.stopPropagation()
id = $(control).closest('tr').attr('id');
confirmDialog("Are you sure do you want to delete this Project?", function () {
removeProject(id)
});
}
function removeProject(elem) {
var updatedBy = $("#userName").text();
var ajxObj = { id: elem};
$.ajax({
type: "POST",
url: "/project/ProjectDelete",
data: JSON.stringify(ajxObj),
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true,
cache: false,
success: function (msg) {
$(".success").html("project Deleted successfully!");
$('.success').show();
setTimeout(function () {
$('.success').hide();
}, 1000);
loadProjectsList()
}
});
}
You can use bootstrap angular model popup.
for more information https://angular-ui.github.io/bootstrap/#!#modal

$http.get cache false is not working

i am using this code to call the method but it is still keeping the cache and not refreshing the data on the screen
(function () {
'use strict';
app.controller('categoryController', ['$http', '$location', 'authService', 'ngWEBAPISettings', categoryController]);
////categoryController.$inject = ['$location'];
function categoryController($http, $location, authService, ngWEBAPISettings) {
/* jshint validthis:true */
//Creating headers for sending the authentication token along with the system.
var authheaders = {};
authheaders.Authorization = 'Bearer ' + authService.getToken();
//ForDate
var d = new Date();
var vm = this;
vm.title = 'Category';
////debugger;
////Vadiable for Grid
vm.Category = [];
////Vadiable for Adding
vm.category = {
CategoryID: 0,
CategoryName:"",
CreatedOn:d,
UpdatedOn:d
};
////Vadiable for Editing
vm.editCategory = {};
vm.getCategory = function () {
////debugger;
////authheaders.cache = false;
var config = {
headers: {
'Authorization': authheaders.Authorization
},
cache: false,
};
//For Grid
$http.get(ngWEBAPISettings.apiServiceBaseUri + "api/Categories", config)
.then(function (respose) {
//success
////debugger;
angular.copy(respose.data, vm.Category);
////debugger;
//var i = 2;
////debugger;
}, function (response) {
//failure
////debugger;
}).finally(function () {
////debugger;
//finally
}
);
}
vm.add = function ()
{
////authheaders.Content-Type="application/x-www-form-urlencoded";
////debugger;
vm.category.CreatedOn = d;
vm.category.UpdatedOn = d;
$http.post(ngWEBAPISettings.apiServiceBaseUri + "api/Categories", JSON.stringify(vm.category), { headers: authheaders })
.then(function (repose) {
////success
////debugger;
vm.Category.push(repose.data);
alert('Category has been addded successfully');
$('#addModal').modal('hide');
}, function (response) {
////failure
////debugger;
alert('An error has been occurred while adding the data');
}).finally(function () {
vm.category = {};
});
}
vm.edit = function (id) {
///debugger;
////alert(id);
$('#btnSubmit').html('Update');
$("#btnSubmit").removeAttr("ng-click");
$("#btnSubmit").attr("ng-click", "vm.edit()");
$('#addModal').modal('show');
}
vm.delete = function (id) {
////debugger;
alert(id);
}
activate();
function activate() { vm.getCategory(); }
}
})();
here is the html
<h1>{{vm.title}}</h1>
<div id="addModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="gridSystemModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="gridSystemModalLabel">Add Category</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label class="control-label col-md-3">Category Name</label>
<input class="form-control col-md-9" type="text" name="txtcategoryname" id="txtcategoryname" maxlength="200" ng-model="vm.category.CategoryName" required />
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" id="btnSubmit" class="btn btn-primary" ng-disabled="!vm.category.CategoryName" ng-click="vm.add()">Add</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-md-offset-10">
<span class="fa fa-plus fa-200px"></span> Add New Record
</div>
</div>
<table class="table table-responsive table-hover">
<thead>
<tr>
<th>Category Name</th>
<th>Created On</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="cat in vm.Category">
<td style="vertical-align:middle">{{cat.categoryName}}</td>
<td style="vertical-align:middle">{{cat.createdOn | date:'dd-MMM-yyyy' }}</td>
<td>
<input type="button" class="btn btn-sm btn-primary" ng-click="vm.edit(cat.categoryID)" value="Edit" />
<input type="button" class="btn btn-sm btn-primary" ng-click="vm.delete(cat.categoryID)" value="Delete" />
</td>
</tr>
</tbody>
</table>
<script type="text/javascript">
function openAddModal() {
$('#addModal').modal('show');
$('#btnSubmit').val('Add');
}
</script>
here it is get called from
function activate() { vm.getCategory(); }
It does disable cache for all get requests.
myApp.config([
// Diable IE Cache for $http.get requests
'$httpProvider', function ($httpProvider) {
// Initialize get if not there
if (!$httpProvider.defaults.headers.get) {
$httpProvider.defaults.headers.get = {};
}
// Enables Request.IsAjaxRequest() in ASP.NET MVC
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
// Disable IE ajax request caching
$httpProvider.defaults.headers.get['If-Modified-Since'] = '0';
}
]);
According to this Angular link https://docs.angularjs.org/api/ng/service/$http caching is disabled by default. Check if you have a global setting somewhere for the cache and disable if needed.
Also try this solution by adding a datetime parameter in querystring.
Destroying AngularJS $Http.Get Cache
this code works for me
app.config(['$httpProvider', function ($httpProvider) {
//initialize get if not there
if (!$httpProvider.defaults.headers.get) {
$httpProvider.defaults.headers.get = {};
}
//disable IE ajax request caching
$httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT';
// extra
$httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
$httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
}]);

ng-view not showing with resolve

I am using resolve in this way (seems to be the standard way to do this way). But the view is not showing. Any ideas what I missed? Best Regards
angular.module('fifaApp', ['ngRoute'])
.config(function($routeProvider) {
$routeProvider.when('/team/:code', {
templateUrl: 'views/team_details.html',
controller:'TeamDetailsCtrl as teamDetailsCtrl',
resolve: {
auth: function(UserService){
return UserService.session();
}
}
});
});
.factory('UserService', ['$http', function($http) {
var service = {
isLoggedIn: false,
session: function() {
var promise = $http.get('/api/session')
promise.success(function(response) {
service.isLoggedIn = true;
return response;
});
return promise;
};
return service;
};
}]);
.controller('MainCtrl', ['$scope','auth',
function($scope,auth) {
$scope.auth = auth.response;
}]);
And html:
<div class="team-details-container card">
<div class="team-logo">
<img title="Image Courtesy: Wikipedia"
ng-src="{{teamDetailsCtrl.team.logoUrl}}">
</div>
<div class="name">
<span ng-bind="teamDetailsCtrl.team.name"></span>
(<span ng-bind="teamDetailsCtrl.team.fifaCode"></span>)
</div>
<div class="detail">
<div class="label">
<span>Nickname</span>
</div>
<div class="title">
<span ng-bind="teamDetailsCtrl.team.nickname"></span>
</div>
</div>
<div class="detail">
<div class="label">
<span>FIFA Ranking</span>
</div>
<div class="title">
<span ng-bind="teamDetailsCtrl.team.fifaRanking">
</span>
</div>
</div>
<div class="detail">
<div class="label">
<span>Association</span>
</div>
<div class="title">
<span ng-bind="teamDetailsCtrl.team.association"></span>
</div>
</div>
<div class="detail">
<div class="label">
<span>Head Coach</span>
</div>
<div class="title">
<span ng-bind="teamDetailsCtrl.team.headCoach"></span>
</div>
</div>
<div class="detail">
<div class="label">
<span>Captain</span>
</div>
<div class="title">
<span ng-bind="teamDetailsCtrl.team.captain"></span>
</div>
</div>
</div>
Add $q in service.
.factory('UserService', ['$http' , '$q', function($http, $q) {
var service = {
isLoggedIn: false,
session: function() {
var deferred = $q.defer();
var promise = $http.get('/api/session')
promise.success(function(response) {
service.isLoggedIn = true;
deferred.resolve(response);
});
return deferred.promise;
};
return service;
};
}]);

Error: [ng:areq] Argument 'ChatAppCtrl' is not a function, got undefined

Hi I was trying to run this angular based chat app, but it's giving me this error. Kindly please help me fix this.
the code is already available on
https://github.com/tamaspiros/AngularChat
the error i am getting is
Error: [ng:areq] Argument 'ChatAppCtrl' is not a function, got undefined
http://errors.angularjs.org/1.3.9/ng/areq?p0=ChatAppCtrl&p1=not%20a%20function%2C%20got%20undefined
at REGEX_STRING_REGEXP (angular.js:63)
at assertArg (angular.js:1577)
at assertArgFn (angular.js:1587)
at angular.js:8418
at angular.js:7592
at forEach (angular.js:331)
at nodeLinkFn (angular.js:7579)
at compositeLinkFn (angular.js:7075)
at compositeLinkFn (angular.js:7078)
at publicLinkFn (angular.js:6954)
the index.html is
<!DOCTYPE html>
<html ng-app="chat">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="css/app.css">
<link rel="stylesheet" href="css/bootstrap.yeti.css">
<link rel="stylesheet" href="css/flags.css">
<link rel="stylesheet" href="components/font-awesome/css/font-awesome.css">
</head>
<body ng-controller="ChatAppCtrl" ng-cloak>
<!-- Fixed navbar -->
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#" ng-click="about()">AngularChat</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li>About</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><p class="navbar-text online" ng-if='status === "online"'>{{ status }}</p><p class="navbar-text offline" ng-if='status === "offline"'>{{ status }}</p></li>
<li class="dropdown" ng-show="joined">
{{ peopleCount }} online <b class="caret" ng-if="peopleCount > 0"></b>
<ul class="dropdown-menu">
<li ng-repeat="user in users"><p class="white">{{ user.name }} <span ng-if="user.countrycode"><img class="flag flag-{{user.countrycode}}"></span> <i class="fa fa-{{user.device}}"></i></p></li>
</ul>
</li>
<li class="dropdown" ng-show="joined">
{{ roomCount }} room<span ng-if="roomCount === 0 || roomCount > 1">s</span> <b class="caret" ng-if="roomCount > 0"></b>
<ul class="dropdown-menu">
<li ng-repeat="room in rooms">
<form class="form-inline" role="form"><div class="form-group"><p class="white">{{ room.name }}</p></div><button class="btn btn-success btn-xs" type="submit" ng-click='joinRoom(room)' ng-hide='room.id === user.owns || room.id === user.inroom || user.owns || user.inroom'>Join</button>
<button type="submit" ng-click='deleteRoom(room)' class="btn btn-xs btn-danger" ng-show='room.id === user.owns'>Delete</button>
<button type="submit" ng-click="leaveRoom(room)" class="btn btn-xs btn-info" ng-hide='room.id === user.owns || !user.inroom || user.owns || user.inroom !== room.id'>Leave</button></form>
</li>
</ul>
</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
<!-- Begin page content -->
<div class="container" ng-show="!joined">
<form class="form-inline" role="form">
<div class="form-group">
<label class="sr-only" for="username">Name: </label>
<input type="text" class="form-control" name="username" id="username" ng-model="username" placeholder="Enter desired name">
</div>
<button type="submit" class="btn btn-default btn-sm" ng-click='joinServer()'>Enter chat</button>
</form>
<small ng-if="error" class="text-danger">{{ error.join }}</small> <small ng-if="suggestedUsername" class="text-info" ng-click="setUsername(suggestedUsername)">How about <span class="text-success" style="cursor: pointer;">{{ suggestedUsername }}</a>?</small>
</div>
<div ng-hide="!joined" class="container" >
<p >Hello {{ user.name }}. <span ng-if="user.owns">You own a room: <strong>{{ user.roomname }}</strong>.</span> <span ng-if="!user.owns && user.inroom">You have joined a room: <strong>{{ user.roomname }}</strong>.<br> You can create your own room as well (but you need to leave the current one first)
</span><br>
<small ng-if="user.owns">You can remove your room by clicking delete in drop-down menu in the top right corner.</small></p>
<p ng-show="!user.inroom">Create a chat room or join one (top right corner).
<div id="createroom">
<form class="form-inline" role="form" ng-hide="user.owns && user.inroom">
<div class="form-group">
<label class="sr-only" for="roomname">Room name: </label>
<input type="text" placeholder="Enter room name" class="form-control" ng-model="roomname" name="roomname" id="roomname">
</div>
<button type="submit" class="btn btn-default btn-sm" ng-click="createRoom()">Create room</button>
<small ng-if="error" class="text-danger">{{ error.create }}</small>
</form>
</div>
<div id="chatpanel" ng-show="user.inroom" >
<div id="chat">
<form class="form-inline" role="form" ng-show="user.owns || user.inroom">
<div class="form-group">
<label class="sr-only" for="message">Message: </label>
<input type="text" placeholder="Enter message" class="form-control" ng-model="message" name="message" id="message" ng-keypress="typing($event, user.inroom)" on-focus="focus(true)" on-blur="focus(false)">
</div>
<button type="submit" class="btn btn-default btn-sm" ng-click='send()'>Send message</button>
</form>
<small ng-if="error" class="text-danger">{{ error.send }}</small>
</div>
<div class="row">
<div class="col-lg-6">
<div id="messages">
<ul>
<li class="list-unstyled" ng-repeat="message in messages track by $index" autoscroll ng-class="{dark: $index % 2 === 0}"><strong>{{ message.name }}</strong>: {{ message.message }}</li>
</ul>
</div>
</div>
<div class="col-lg-6">
<div id="sidebar">
<ul ng-if="isTyping">
<li ng-repeat="person in typingPeople track by $index" class="text-muted list-unstyled"><small>{{ person }} is typing</small></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="footer">
<div class="container">
<p class="text-muted">AngularChat by Tamas Piros | http://tamas.io/ | <a href="https://twitter.com/tpiros" target="_blank">#tpiros</p>
</div>
</div>
<!-- about modal -->
<script type="text/ng-template" id="aboutModal" />
<div class="modal-header">
<h3>About AngularChat</h3>
</div>
<div class="modal-body">
<p>Hello and thanks for visiting AngularChat.</p>
<p>This is an experimental project for testing new JavaScript technologies.</p>
<p>First, please enter your username. Once you've done this you have two options. You can create a room or you can join an already existing one.</p>
<p>Please note that once you've joined a room you can't create one (basically you can be part of one room at one time). Also note that if you're a room owner and you disconnect from the server, delete or leave your room all other participants will be removed from the room as well.</p>
<p>If you'd like to read more about the project please check out this article: http://tamas.io/angularchat/</p>
<p>If you're interested in the code behind this project, please go to: https://github.com/tamaspiros/angularchat</p>
</div>
<div class="modal-footer">
<button class="btn btn-warning btn-sm cancel" ng-click="cancel()">Cancel</button>
</div>
</div>
</script>
<script src="/socket.io/socket.io.js"></script>
<script src="components/angular/angular.js"></script>
<script src="components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<script src="components/jquery/dist/jquery.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/directives.js"></script>
<script src="js/services.js"></script>
</body>
</html>
and the function ChatAppCtrl is
'use strict';
function ChatAppCtrl($scope, $q, $modal, socket, useragent, geolocation) {
$scope.peopleCount = 0;
$scope.messages = [];
$scope.user = {}; //holds information about the current user
$scope.users = {}; //holds information about ALL users
$scope.rooms = []; //holds information about all rooms
$scope.error = {};
$scope.typingPeople = [];
$scope.username = '';
$scope.joined = false;
var typing = false;
var timeout = undefined;
/* ABOUT PAGE */
$scope.about = function() {
var modalInstance = $modal.open({
templateUrl: 'aboutModal',
controller: aboutModalCtrl
});
};
var aboutModalCtrl = function($scope, $modalInstance) {
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
};
/* ABOUT PAGE END */
$scope.setUsername = function(suggestedUsername) {
$scope.username = suggestedUsername;
}
function timeoutFunction() {
typing = false;
socket.emit('typing', false);
}
$scope.focus = function(bool) {
$scope.focussed = bool;
}
$scope.typing = function(event, room) {
if (event.which !== 13) {
if (typing === false && $scope.focussed && room !== null) {
typing = true;
socket.emit('typing', true);
} else {
clearTimeout(timeout);
timeout = setTimeout(timeoutFunction, 1000);
}
}
}
socket.on('isTyping', function(data) {
if (data.isTyping) {
$scope.isTyping = data.isTyping;
$scope.typingPeople.push(data.person);
} else {
$scope.isTyping = data.isTyping;
var index = $scope.typingPeople.indexOf(data.person);
$scope.typingPeople.splice(index, 1);
$scope.typingMessage = '';
}
});
$scope.joinServer = function() {
$scope.user.name = this.username;
if ($scope.user.name.length === 0) {
$scope.error.join ='Please enter a username';
} else {
var usernameExists = false;
socket.emit('checkUniqueUsername', $scope.user.name, function(data) {
usernameExists = data.result;
if (usernameExists) {
$scope.error.join = 'Username ' + $scope.user.name + ' already exists.';
socket.emit('suggest', $scope.user.name, function(data) {
$scope.suggestedUsername = data.suggestedUsername;
});
} else {
socket.emit('joinSocketServer', {name: $scope.user.name});
$scope.joined = true;
$scope.error.join = '';
}
});
}
}
$scope.send = function() {
if (typeof this.message === 'undefined' || (typeof this.message === 'string' && this.message.length === 0)) {
$scope.error.send = 'Please enter a message';
} else {
socket.emit('send', {
name: this.username,
message: this.message
});
$scope.message = '';
$scope.error.send = '';
}
}
$scope.createRoom = function() {
var roomExists = false;
var room = this.roomname;
if (typeof room === 'undefined' || (typeof room === 'string' && room.length === 0)) {
$scope.error.create = 'Please enter a room name';
} else {
socket.emit('checkUniqueRoomName', room, function(data) {
roomExists = data.result;
if (roomExists) {
$scope.error.create = 'Room ' + room + ' already exists.';
} else {
socket.emit('createRoom', room);
$scope.error.create = '';
if (!$scope.user.inroom) {
$scope.messages = [];
$scope.roomname = '';
}
}
});
}
}
$scope.joinRoom = function(room) {
$scope.messages = [];
$scope.error.create = '';
$scope.message = '';
socket.emit('joinRoom', room.id);
}
$scope.leaveRoom = function(room) {
$scope.message = '';
socket.emit('leaveRoom', room.id);
}
$scope.deleteRoom = function(room) {
$scope.message = '';
socket.emit('deleteRoom', room.id)
}
socket.on('sendUserDetail', function(data) {
$scope.user = data;
});
socket.on('listAvailableChatRooms', function(data) {
$scope.rooms.length = 0;
angular.forEach(data, function(room, key) {
$scope.rooms.push({name: room.name, id: room.id});
});
});
socket.on('sendChatMessage', function(message) {
$scope.messages.push(message);
});
socket.on('sendChatMessageHistory', function(data) {
angular.forEach(data, function(messages, key) {
$scope.messages.push(messages);
});
});
socket.on('connectingToSocketServer', function(data) {
$scope.status = data.status;
});
socket.on('usernameExists', function(data) {
$scope.error.join = data.data;
});
socket.on('updateUserDetail', function(data) {
$scope.users = data;
});
socket.on('joinedSuccessfully', function() {
var payload = {
countrycode: '',
device: ''
};
geolocation.getLocation().then(function(position) {
return geolocation.getCountryCode(position);
}).then(function(countryCode) {
payload.countrycode = countryCode;
return useragent.getUserAgent();
}).then(function(ua) {
return useragent.getIcon(ua);
}).then(function(device) {
payload.device = device;
socket.emit('userDetails', payload);
});
});
socket.on('updatePeopleCount', function(data) {
$scope.peopleCount = data.count;
});
socket.on('updateRoomsCount', function(data) {
$scope.roomCount = data.count;
});
socket.on('disconnect', function(){
$scope.status = 'offline';
$scope.users = 0;
$scope.peopleCount = 0;
});
}
Recent versions of Angular do not allow global functions to be used as controllers, see docs under "Arguments". The solutions:
(preferred) Use angular.module('chat').controller('ChatAppCtrl', ChatAppCtrl);
Configure the $controllerProvider: In a coonfig block, inject the $controllerProvider and run: $controllerProvider.allowGlobals().

Opening a DIV in the HTML as Modal in AngularJS

Learning some AngularJS here...
I have an Angular application which connects to an ASP.Net WebAPI.
I am trying to have a DIV inside my HTML open as a modal window.
My HTML looks as follows:
<div class="container" style="padding-top:20px;">
<div ng-app="vehicleApp" data-ng-controller="testingController" class="container">
<div ng-show="error" class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<p>{{ error }}</p>
</div>
<div class="modal fade" id="vehicleModel" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">X</button>
<h4 class="modal-title" id="myModalLabel" ng-hide="editMode">Add vehicle</h4>
<h4 class="modal-title" id="myModalLabel" ng-show="editMode">Edit vehicle: {{ vehicle.Id }}</h4>
</div>
<div class="modal-body">
<form class="form-horizontal" role="form" name="addvehicleform">
<div class="form-group">
<label for="title" class="col-sm-3 control-label">vehicle Name</label>
<div class="col-sm-7">
<input type="text" data-ng-model="vehicle.Name" class="form-control" id="vehiclename" placeholder="vehicle Name" required title="Enter your vehicle Name" />
</div>
</div>
<div class="form-group">
<label for="title" class="col-sm-3 control-label">Identification Account</label>
<div class="col-sm-7">
<input type="number" data-ng-model="vehicle.vehicleIdentificationAccountId" class="form-control" id="vehicleIdentificationAccountId" placeholder="vehicle Identification Account" required title="Enter your Identification Account" />
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-7">
<span data-ng-hide="editMode">
<input type="submit" value="Add" ng-disabled="addvehicleform.$invalid" data-ng-click="add()" class="btn btn-primary normal-button" />
</span>
<span data-ng-show="editMode">
<input type="submit" value="Update" ng-disabled="addvehicleform.$invalid" data-ng-click="update()" class="btn btn-primary normal-button" />
</span>
<input type="button" value="Cancel" data-ng-click="cancel()" class="btn btn-primary" />
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<h1>Vehicle List</h1>
<p><a data-ng-click="showadd()" href="javascript:;" class="btn btn-primary">Add New vehicle</a></p>
<table class="table table-striped table-bordered table-hover table-condensed">
<thead>
<tr>
<th>Vehicle ID</th>
<th>Name</th>
<th>Identification Account</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr data-ng-hide="agencies || agencies.length > 0">
<td colspan="4">
<div class="text-center text-warning">
<strong>No Agencies Retrieved</strong>
</div>
</td>
</tr>
<tr data-ng-repeat="vehicle in agencies">
<td>{{vehicle.Id}}</td>
<td>{{vehicle.Name}}</td>
<td>{{vehicle.vehicleIdentificationAccountId}}</td>
<td>
<a data-ng-click="get(vehicle)" href=""><span class="glyphicon glyphicon-open"></span>View</a>
<a data-ng-click="edit(vehicle)" href=""><span class="glyphicon glyphicon-edit"></span>Edit</a>
<a data-ng-click="showConfirm(vehicle)" href=""><span class="glyphicon glyphicon-remove-circle"></span>Delete</a>
</td>
</tr>
</tbody>
</table>
<hr />
<div class="modal fade" id="viewModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">X</button>
<h4 class="modal-title" id="myModalLabel">View vehicle Detail</h4>
</div>
<div class="modal-body">
<form class="form-horizontal" role="form" name="viewuser">
<div class="form-group">
<label for="ID" class="col-sm-3 control-label">ID</label>
<div class="col-sm-7">
{{vehicle.Id}}
</div>
</div>
<div class="form-group">
<label for="Name" class="col-sm-3 control-label">Name</label>
<div class="col-sm-7">
{{vehicle.Name}}
</div>
</div>
<div class="form-group">
<label for="vehicleIdentificationAccountId" class="col-sm-3 control-label">Identification Account</label>
<div class="col-sm-7">
{{vehicle.vehicleIdentificationAccountId}}
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="confirmModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">X</button>
<h4 class="modal-title" id="myModalLabel">Confirm</h4>
</div>
<div class="modal-body">
Are you sure you want to delete vehicle: {{ vehicle.Name}}?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-warning" data-ng-click="delete()" style="width:100px;">Ok</button>
<button type="button" class="btn btn-primary" data-dismiss="modal" style="width:100px;">Cancel</button>
</div>
</div>
</div>
</div>
</div>
</div>
testingController.js
'use strict';
app.controller('testingController', function ($scope, testingDataService, $modal) {
$scope.vehicles = [];
$scope.vehicle = null;
$scope.editMode = false;
// Get vehicle
$scope.get = function () {
$scope.vehicle = this.vehicle;
$('#viewModal').modal('show');
};
//get all vehicles
$scope.getAll = function () {
testingDataService.getvehicleList().success(function (data) {
$scope.vehicles = data;
}).error(function (data) {
$scope.error = "An Error has occured while Loading vehicles! " + data.ExceptionMessage;
});
};
// add vehicle
$scope.add = function () {
var currentvehicle = this.vehicle;
if (currentvehicle != null && currentvehicle.Name != null && currentvehicle.vehicleIdentificationAccountId!= null) {
testingDataService.addvehicle(currentvehicle).success(function (data) {
$scope.addMode = false;
currentvehicle = data;
$scope.vehicles.push(currentvehicle);
//reset form
$scope.vehicle = null;
$('#vehicleModel').modal('hide');
}).error(function (data) {
$scope.error = "An Error has occured while Adding vehicle! " + data.ExceptionMessage;
});
}
};
//edit vehicle
$scope.edit = function () {
$scope.vehicle = this.vehicle;
$scope.editMode = true;
$('#vehicleModel').modal('show');
};
//update vehicle
$scope.update = function () {
var currentvehicle = this.vehicle;
testingDataService.updatevehicle(currentvehicle).success(function (data) {
currentvehicle.editMode = false;
$('#vehicleModel').modal('hide');
}).error(function (data) {
$scope.error = "An Error has occured while Updating vehicle! " + data.ExceptionMessage;
});
};
// delete
$scope.delete = function () {
currentvehicle = $scope.vehicle;
testingDataService.deletevehicle(currentvehicle).success(function (data) {
$('#confirmModal').modal('hide');
$scope.vehicles.pop(currentvehicle);
}).error(function (data) {
$scope.error = "An Error has occured while Deleting vehicle! " + data.ExceptionMessage;
$('#confirmModal').modal('hide');
});
};
//Modal popup events
$scope.showadd = function () {
$scope.vehicle = null;
$scope.editMode = false;
$('#vehicleModel').modal({ backdrop: 'static' });
$('#vehicleModel').modal('show');
};
$scope.showedit = function () {
$('#vehicleModel').modal({ backdrop: 'static' });
$('#vehicleModel').modal('show');
};
$scope.showConfirm = function (data) {
$scope.vehicle = data;
$('#confirmModal').modal('show');
};
$scope.cancel = function () {
$scope.vehicle = null;
$('#vehicleModel').modal('hide');
}
// initialize your users data
$scope.getAll();
});
Basically when I click on the Add New Vehicle button, the console says:
ReferenceError: $ is not defined
on the line in the controller where it is supposed to show the modal:
$('#vehicleModel').modal({ backdrop: 'static' });
I am a bit lost on how to resolve this.
Appreciate any insight.
P.S. The data loads fine when this HTML view is loaded up. I also added a console.log inside the
$scope.showadd = function (){
console.log('Test');
};
and that is logged properly in the console. So totally lost right now...
Update:
Did a little more investigation. I issued in Chrome console the command:
$('#vehicleModel')
and it showed me the div with the id=vehicleModel.
I would argue that you should probably be using Angular UI Bootstrap to create your modal dialogs. Here is the link.
Here is a cut down version of how to open a modal using Angular UI Bootrstrap:
$scope.open = function (vehicle) {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
resolve: {
items: function () {
return $scope.items;
}
}
});
};
MODAL CONTENT
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">Modal!</h3>
</div>
<div class="modal-body">
<div >Body</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="$close('awesome')">OK</button>
<button class="btn btn-warning" ng-click="$dismiss('nah')">Cancel</button>
</div>
</script>
HTML
<a data-ng-click="open(vehicle)" href=""><span class="glyphicon glyphicon-open"></span>View</a>
You're trying to grab your element the jQuery way. $ is reserved in Angular. try using:
angular.element('div').modal({ backdrop: 'static' });
where 'div' is whatever your actual tag name is, and traverse the DOM for it...
EDIT: from https://docs.angularjs.org/error/jqLite/nosel
In order to resolve this error, rewrite your code to only use tag name selectors and manually traverse the DOM using the APIs provided by jqLite.
Alternatively, you can include a full version of jQuery, which Angular
will automatically use and that will make all selectors available.
You can code like this:
// Pre-fetch an external template populated with a custom scope
var myOtherModal = $modal({scope: $scope, template: 'modal/docs/modal.demo.tpl.html', show: false});
// Show when some event occurs (use $promise property to ensure the template has been loaded)
$scope.showModal = function() {
myOtherModal.$promise.then(myOtherModal.show);
};

Resources