How to delete data inside the list using bootstrap modal? - angularjs

I just want to delete the data inside the table using bootstrap modal, but it seems so hard to find the right way how to do this, here's my sample code. Inside my modal I have an href code that use to delete the data
, it is working outside the modal. I just want to know any solution make this working. thanks.
var app = angular.module('app', ['ui.bootstrap']);
var student = [{
name: 'Andrew'
}, {
name: 'Butler'
}, {
name: 'Cameron'
}, {
name: 'Delo'
}, {
name: 'Emman'
}, {
name: 'Ferbs'
}];
app.filter('startFrom', function() {
return function(input, start) {
if (input) {
start = +start; //parse to int
return input.slice(start);
}
return [];
}
});
app.controller('customersCtrl', function($scope, $timeout) {
$scope.list = student;
$scope.currentPage = 1; //current page
$scope.entryLimit = 10; //max no of items to display in a page
$scope.filteredItems = $scope.list.length; //Initially for no filter
$scope.totalItems = $scope.list.length;
$scope.setPage = function(pageNo) {
$scope.currentPage = pageNo;
};
$scope.filter = function() {
$timeout(function() {
$scope.filteredItems = $scope.filtered.length;
}, 10);
};
$scope.sort_by = function(predicate) {
$scope.predicate = predicate;
$scope.reverse = !$scope.reverse;
};
});
app.filter('startsWithA', function() {
return function(items, letter) {
console.log(items, letter)
var filtered = [];
var letterMatch = new RegExp(letter, 'i');
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (letterMatch.test(item.name.substring(0, 1))) {
filtered.push(item);
}
}
console.log(filtered);
return filtered;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.10.0/ui-bootstrap-tpls.js"></script>
<div ng-app="app">
<div class="container" ng-controller="customersCtrl">
<div class="row">
<div class="col-12">
<h2 id="titleHead"><center>Student List</center></h2>
</div>
<div class="option-panel">
<div class="col-sm-3 col-md-3 pull-right">
<form class="navbar-form">
<div class="input-group">
<input type="text" ng-model="search" ng-click="filter()" placeholder="Search student" class="form-control" placeholder="Search" name="search">
</div>
</form>
</div>
</div>
<div class="nav navbar-default">
<div class="tab-panel">
<nav>
<ul>
<li class="active" name="active"><a ng-click="letter = '[AB]'">A-B</a>
</li>
<li class="active" name="active"><a ng-click="letter = '[CD]'">C-D</a>
</li>
<li class="active" name="active"><a ng-click="letter = '[EF]'">E-F</a>
</li>
</ul>
</nav>
</div>
</div>
<div id="no-more-tables">
<table class="col-md-12 table-bordered table-condensed cf" ng-show="filteredItems > 0">
<thead class="cf">
<tr>
<th>
<center>Name
<a ng-click="sort_by('first_name');"></a>
</center>
</th>
</tr>
</thead>
<tbody color="#">
<tr ng-repeat="data in filtered = (list | filter:search |orderBy : predicate :reverse) | startFrom:(currentPage-1)*entryLimit |startsWithA:letter |limitTo:entryLimit ">
<td data-title="Name" class="text-center">{{data.name}} <a type="button" class="btn btn-xs btn-primary" style="width: 40%;" href="#" data-toggle="modal" data-target="#myModal" >Delete</a>
</td>
</tr>
</tbody>
</table>
<div class="col-md-12" ng-show="filteredItems == 0">
<div class="col-md-12">
<center>
<h4>No results found</h4>
</center>
</div>
</div>
<div class="col-md-12" ng-show="filteredItems > 0">
<center>
<div pagination="" page="currentPage" on-select-page="setPage(page)" boundary-links="true" total-items="filteredItems" items-per-page="entryLimit" class="pagination-small" previous-text="«" next-text="»"></div>
</center>
</div>
<div id="myModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Delete Student</h4>
</div>
<div class="modal-body">
<p>Do you want to delete this student?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">No</button>
<button type="button" class="btn btn-primary" href="<?php echo base_url(); ?>index.php/students/edit/studentform/{{data.id}}" >Yes</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

First I would suggest using $http service, or similar, for removing a record. Also, You'll notice that I made a change to the way your controller was organized by using the controller as syntax, and assigning everything to the controller, and not to the scope. That way you can pass on the controllers scope to directives and such more easily.
The idea is that you preserve an ID of the selected item, so that you can use it later on when you trigger the server delete action.
This can be done in many different ways, this is just one of the ways.
Hope this helps.
var app = angular.module('app', ['ui.bootstrap']);
var student = [{
id: 0,
name: 'Andrew'
}, {
id: 1,
name: 'Butler'
}, {
id: 2,
name: 'Cameron'
}, {
id: 3,
name: 'Delo'
}, {
id: 4,
name: 'Emman'
}, {
id: 5,
name: 'Ferbs'
}];
app.filter('startFrom', function() {
return function(input, start) {
if (input) {
start = +start; //parse to int
return input.slice(start);
}
return [];
}
});
app.controller('customersCtrl', function($http, $timeout) {
var vm = this,
itemId = null;
/**
* Store a selected item's ID
* #param id
*/
vm.getItemId = function (id) {
itemId = id;
};
/**
* Remove the selected item from the list
*/
vm.deleteItemFunction = function () {
console.log('remove', itemId);
// And then something like this
$http.delete('/students/edit/studentform/' + itemId).success(function () {
console.log('successfully removed');
});
};
vm.list = student;
vm.currentPage = 1; //current page
vm.entryLimit = 10; //max no of items to display in a page
vm.filteredItems = vm.list.length; //Initially for no filter
vm.totalItems = vm.list.length;
vm.setPage = function(pageNo) {
vm.currentPage = pageNo;
};
vm.filter = function() {
$timeout(function() {
vm.filteredItems = vm.filtered.length;
}, 10);
};
vm.sort_by = function(predicate) {
vm.predicate = predicate;
vm.reverse = !vm.reverse;
};
});
app.filter('startsWithA', function() {
return function(items, letter) {
console.log(items, letter)
var filtered = [];
var letterMatch = new RegExp(letter, 'i');
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (letterMatch.test(item.name.substring(0, 1))) {
filtered.push(item);
}
}
console.log(filtered);
return filtered;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.10.0/ui-bootstrap-tpls.js"></script>
<div ng-app="app">
<div class="container" ng-controller="customersCtrl as customer">
<div class="row">
<div class="col-12">
<h2 id="titleHead"><center>Student List</center></h2>
</div>
<div class="option-panel">
<div class="col-sm-3 col-md-3 pull-right">
<form class="navbar-form">
<div class="input-group">
<input type="text" ng-model="search" ng-click="customer.filter()" placeholder="Search student" class="form-control" placeholder="Search" name="search">
</div>
</form>
</div>
</div>
<div class="nav navbar-default">
<div class="tab-panel">
<nav>
<ul>
<li class="active" name="active"><a ng-click="letter = '[AB]'">A-B</a>
</li>
<li class="active" name="active"><a ng-click="letter = '[CD]'">C-D</a>
</li>
<li class="active" name="active"><a ng-click="letter = '[EF]'">E-F</a>
</li>
</ul>
</nav>
</div>
</div>
<div id="no-more-tables">
<table class="col-md-12 table-bordered table-condensed cf" ng-show="customer.filteredItems > 0">
<thead class="cf">
<tr>
<th>
<center>Name
<a ng-click="customer.sort_by('first_name');"></a>
</center>
</th>
</tr>
</thead>
<tbody color="#">
<tr ng-repeat="data in filtered = (customer.list | filter:search |orderBy : customer.predicate : customer.reverse) | startFrom:(customer.currentPage-1)* customer.entryLimit |startsWithA:letter |limitTo: customer.entryLimit ">
<td data-title="Name" class="text-center">
{{data.name}}
<a type="button" class="btn btn-xs btn-primary" style="width: 40%;" href="#" ng-click="customer.getItemId(data.id)" data-toggle="modal" data-target="#myModal">Delete</a>
</td>
</tr>
</tbody>
</table>
<div class="col-md-12" ng-show="customer.filteredItems == 0">
<div class="col-md-12">
<center>
<h4>No results found</h4>
</center>
</div>
</div>
<div class="col-md-12" ng-show="customer.filteredItems > 0">
<center>
<div pagination="" page="customer.currentPage" on-select-page="customer.setPage(page)" boundary-links="true" total-items="customer.filteredItems" items-per-page="customer.entryLimit" class="pagination-small" previous-text="«" next-text="»"></div>
</center>
</div>
<div id="myModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Delete Student</h4>
</div>
<div class="modal-body">
<p>Do you want to delete this student?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">No</button>
<button type="button" class="btn btn-primary" ng-click="customer.deleteItemFunction()">Yes</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

Related

how to group array and read using knockout.js data-bind: with

I am trying to group an array
[{ "Name": "test1", "Other": "Junk" },
{ "Name": "test1", "Other": "Junk2" },
{ "Name": "test2", "Other": "Pile" }]
I am using the following method to group by property.
var groupBy = function (xs, key) {
return xs.reduce(function (rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
My output from this is, "test1": {children info}, "test2": {one child info}
I am using knockout.js to pass this info to a modal, to which i am using data-bind="with: results"
I am just not sure how to display the results as
test1 - (2) *count/length of test1
test2 - (1) *count/length of test2
I have tried using data-bind="foreach: $parent", this doesn't seem to work. I have also tried setting the object, to a parent called UnpackedItems, then using foreach on UnpackedItems.. this doesn't work either.
<div class="modal fade" id="myModal" data-bind="with: TheseUnpackedItems" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Unpacked Items</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<table style="margin: auto;" class="table">
<tbody data-bind="foreach: UnpackedItems">
<tr>
<td>
<p class="form-control-static" data-bind="text: Name"></p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
self.ShowUnpacked = function(vm) {
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
const Property = "Name";
const GroupedUnpackedItems = groupBy(vm.UnpackedItems, Property);
var test = JSON.stringify(GroupedUnpackedItems);
var m = { "UnpackedItems": GroupedUnpackedItems }
self.TheseUnpackedItems(vm);
}
I am not getting any errors, however, no data actually shows up.
UnpackedItems is an object. So, you can't use foreach bindings. You could loop through the keys of the object using Object.keys()
<tbody data-bind="foreach: Object.keys(UnpackedItems)">
<tr>
<td>
<p class="form-control-static" data-bind="text: $data"></p>
</td>
</tr>
</tbody>
Here's a working snippet:
const groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
function viewModel() {
const self = this;
const UnpackedItems=[{Name:"test1",Other:"Junk"},{Name:"test1",Other:"Junk2"},{Name:"test2",Other:"Pile"}],
Property = "Name",
GroupedUnpackedItems = groupBy(UnpackedItems, Property),
m = { "UnpackedItems": GroupedUnpackedItems }
self.TheseUnpackedItems = ko.observable(m);
}
ko.applyBindings(new viewModel)
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div id="myModal" data-bind="with: TheseUnpackedItems">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Unpacked Items</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<table style="margin: auto;" class="table">
<tbody data-bind="foreach: Object.keys(UnpackedItems)">
<tr>
<td>
<p class="form-control-static" data-bind="text: $data"></p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>

AngularJS GitHub API| Conributors list in the repository list

I have a problem with the repository list in the list of all Conributors for this repository.
I want to create a Contributors list in the list of repositories downloaded using GitHub Api. However, I can not get these data for each repository and put them in html.
Has anyone any idea how to do this?
Thank you in advance for your help
My code:
App in html
<div ng-controller="gitApi" ng-app="app">
<div class="container">
<h1 class="text-center">
<span ng-hide="userData" />Loading</span>
<span />{{userData.name}}</span>
<br>
<a href="{{userData.html_url}}" class="btn btn-default">
{{userData.login}}
</a>
</h1>
<div class="panel panel-default">
<div class="panel-heading">
<form class="form-inline">
<span>
<h4>Repos <span class="badge">{{repoData.length}}</span>
<input ng-model="searchText" placeholder="Search" class="form-control input-sm">
</h4>
</span>
</form>
</div>
<div class="panel-body">
<div class="list-group">
<div ng-repeat="orgs in orgsData | filter:searchText | orderBy:predicate:reverse" class="list-group-item ">
<div class="row">
<div class="col-md-6">
<h4>
<a href="{{repo.html_url}}" target="_blank">
{{orgs.name}}
</a>
<small>{{orgs.description}}</small>
</h4>
<small>
<a href="{{orgs.homepage}}" class="">
<i class="fa fa-link"></i> WebPage
</a>
</small>
</div>
<div class="col-md-6">
Conributors List:
<div ng-repeat=" | filter:searchText | orderBy:predicate:reverse" class="list-group-item ">
<div class="row">
<div class="col-md-12">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
APP.js
angular.module('app', [])
.controller('gitApi', ['$scope', '$http', function($scope, $http) {
$scope.reposLoaded = false;
$scope.userLoaded = false;
$scope.orgsLoaded = false;
$http.get("https://api.github.com/users/angular")
.success(function(data) {
$scope.userData = data;
loadOrgsRepos();
});
var loadOrgsRepos = function() {
$http.get("https://api.github.com/orgs/angular/repos")
.success(function(data) {
$scope.orgsData = data;
});
}
$scope.predicate = '-updated_at';
}]);
You can get all contributors url from contributors_url and make an API call for each one of these, storing the result in the original $scope.orgsData array :
"use strict";
var githubApp = angular.module('app', []);
githubApp.controller('gitApi', ['$scope', '$http', '$q', function($scope, $http, $q) {
$http.get("https://api.github.com/users/angular")
.success(function(data) {
$scope.userData = data;
loadOrgsRepos();
});
var loadOrgsRepos = function() {
$http.get("https://api.github.com/orgs/angular/repos")
.success(function(data) {
$scope.orgsData = data;
var contribs = [];
for (var i in data) {
contribs.push(data[i].contributors_url);
}
$q.all(contribs.map(function(item) {
return $http({
method: 'GET',
url: item
});
}))
.then(function(results) {
results.forEach(function(val, i) {
$scope.orgsData[i].contributors = val.data;
});
});
});
}
$scope.repo_sort = '-updated_at';
$scope.contrib_sort = '-contributions'
}]);
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body id="page-top" class="index">
<div ng-controller="gitApi" ng-app="app">
<div class="container">
<h1 class="text-center">
<span ng-hide="userData">Loading</span>
<span>{{userData.name}}</span>
<br>
<a href="{{userData.html_url}}" class="btn btn-default">
{{userData.login}}
</a>
</h1>
<div class="panel panel-default">
<div class="panel-heading">
<form class="form-inline">
<span>
<h4>Repos <span class="badge">{{repoData.length}}</span>
<input ng-model="searchText" placeholder="Search" class="form-control input-sm">
</h4>
</span>
</form>
</div>
<div class="panel-body">
<div class="list-group">
<div ng-repeat="orgs in orgsData | filter:searchText | orderBy:repo_sort:reverse" class="list-group-item ">
<div class="row">
<div class="col-md-8">
<h4>
<a href="{{repo.html_url}}" target="_blank">
{{orgs.name}}
</a>
<small>{{orgs.description}}</small>
</h4>
<small>
<a href="{{orgs.homepage}}" class="">
<i class="fa fa-link"></i> WebPage
</a>
</small>
</div>
<div class="col-md-6">
Conributors List:
<div class="list-group-item">
<div class="row">
<div class="col-md-4">
name
</div>
<div class="col-md-4">
avatar
</div>
<div class="col-md-4">
contributions
</div>
</div>
</div>
<div ng-repeat="contrib in orgs.contributors | filter:searchText | orderBy:contrib_sort:reverse" class="list-group-item">
<div class="row">
<div class="col-md-4">
<a href="{{contrib.html_url}}" target="_blank">
{{contrib.login}}
</a>
</div>
<div class="col-md-4">
<img ng-src="{{contrib.avatar_url}}" height="42" width="42" />
</div>
<div class="col-md-4">
<p>
{{contrib.contributions}}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
Here is another fiddle

how to get specific item that selected?

screenshot attached.
I learning angularJS.
And i can't find a way to remove the selected item that the 'Remove' button was click on.
Is there any way to do it ?
code attached:
<ul class="unstyled">
<li ng-repeat="todo in todos">
<input type="checkbox" ng-model="todo.done">
<span class="done-{{todo.done}}">{{todo.text}}</span>
<button class="btn" ng-click="removeTodo()">Remove</button>
</li>
</ul>
var app = angular.module("app" , []);
app.controller("MyCtrl" , function($scope){
$scope.todos = [
{"text" :"Learn AngularJS","done":false},{"text" :"build an app","done":false}];
$scope.removeTodo = function(index) {
$scope.todos.splice(index,1);
}
$scope.removeTodo2 = function(todo) {
var index = getByValue( $scope.todos,todo);
$scope.todos.splice(index,1);
}
$scope.addTodo = function(todo){
var toDoObject = {"text":todo,"done":false};
$scope.todos.push(toDoObject);
};
$scope.done = function(todo){
angular.forEach($scope.todos,function(index,todo1){
if(todo == todo1)
$scope.todos[index].done = !$scope.todos[index].done;
})
}
function getByValue(arr, value) {
for (var i=0, iLen=arr.length; i<iLen; i++) {
if (arr[i].text == value) return i;
}
}
});
.done{
text-decoration: line-through;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MyCtrl">
<ul class="unstyled">
<li ng-repeat="todo in todos track by $index">
<input type="checkbox" ng-model="todo.done" >
<span ng-class="{'done' : todo.done == true}">{{todo.text}}</span>
<button class="btn" ng-click="removeTodo($index)">Remove</button>
<button class="btn" ng-click="removeTodo2(todo.text)">Remove2</button>
</li>
</ul>
<input type="text" ng-model="todo">
<input type="button" ng-click = "addTodo(todo)" value="Add">
</div>

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