Error: ng:areq Bad Argument Argument 'msgController' is not a function, got undefined - angularjs

I am new to angularJS and I couldn't understand why this error is coming. Please help find where I have done mistake.
index.html
<!DOCTYPE html>
<html ng-app="MyApp">
<head>
<title>Angular JS Web-Socket</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
<script src="js/chat.js"></script>
<script src="lib/ngDialog.js"></script>
<link rel="stylesheet" type="text/css" href="css/ngDialog-theme-default.css">
<link rel="stylesheet" type="text/css" href="css/ngDialog.css">
<body>
<button ng-controller="MainCtrl" ng-click="openChatBox()">Open</button>
</body>
</html>
chatBox.html
<script src="lib/ngDialog.js"></script>
<script src="lib/angular-websocket.js"></script>
<script src="js/socket.js"></script>
<link rel="stylesheet" type="text/css" href="css/ngDialog.css">
<link rel="stylesheet" type="text/css" href="css/chat.css">
<!-- The Modal -->
<div id="myModal" class="modal" ng-app="chatSocket">
<!-- Modal content -->
<div class="modal-content">
<div class="modal-header">
<div class="menu">
<div class="name">Bot</div>
<div class="close">Close</div>
</div>
</div>
<div class="modal-body" ng-controller="msgController">
<h2>Modal body</h2>
<label ng-repeat="item in socket.msg">
Name : {{item.name}} <br>
Msg : {{item.msg}}
</label>
</div>
<div class="modal-footer">
<h3>Modal Footer</h3>
<form ng-submit="submit()">
<input type="text" ng-model="msgbox">
<button id="sendMsg" type="submit" >Send Message</button>
</form>
</div>
chat.js
var app = angular.module('MyApp', ['ngDialog']);
app.controller('MainCtrl', function ($scope, ngDialog) {
$scope.openChatBox = function() {
ngDialog.openConfirm({template: 'chatBox.html',
scope: $scope //Pass the scope object if you need to access in the template
}).then(
function(value) {
//You need to implement the saveForm() method which should return a promise object
$scope.closeChat().then(
);
},
function(value) {
//Cancel or do nothing
}
);
};
});
socket.js
angular.module('chatSocket', ['ngWebSocket'])
.factory('socket', function ($websocket) {
// Open a WebSocket connection
var ws = $websocket("ws://" + document.location.host + document.location.pathname);
var msg = [];
ws.onMessage(function (event) {
console.log('message: ', event.data);
var response;
try {
response = event.data;
} catch (e) {
console.log('error: ', e);
}
msg.push({
name: "Bot",
msg: response,
});
});
ws.onError(function (event) {
console.log('connection Error', event);
});
ws.onClose(function (event) {
console.log('connection closed', event);
});
ws.onOpen(function () {
console.log('connection open');
ws.send('HELLO SERVER');
});
return {
msg: msg,
status: function () {
return ws.readyState;
},
send: function (message) {
console.log(message);
msg.push({
name: "User",
msg: message,
});
ws.send(message);
}
};
})
.controller('msgController', function ($scope, socket) {
$scope.socket = socket;
$scope.submit = function () {
socket.send($scope.msgbox);
};
});
If I didn't use msgController, the dialog box is opening. when I include this, the error is shown and couldn't open the dialog box.

Because you are referencing the msgController in openConfirm method of ngDialog and you didn't define it.
ngDialog.openConfirm({
template: 'chatBox.html',
controller: 'msgController',
scope: $scope //Pass the scope object if you need to access in the template
})
In addition to that you have specified msgController in chatSocket module and you are using it in MyApp module which is why you are getting the error.
You need to specify the chatSocket as dependency to MyApp module and define the msgController on MyApp module like blow:
var app = angular.module('MyApp', ['ngDialog','chatSocket']);
app.controller('msgController', function ($scope, socket) {
$scope.socket = socket;
$scope.submit = function () {
socket.send($scope.msgbox);
};
});

Related

Data sharing between controllers in angular js

Hi I am new to Angularjs. I am learning how to share data between two controllers using dataservice. Looking at the tutorial I made my own program but it is not working. Can anyone suggest what I am doing wrong here?
<!DOCTYPE html>
<html>
<head>
<title>AngularJS Services</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.5/angular.min.js"></script>
</head>
<body>
<div ng-app="dataServiceApp">
<div ng-controller="ChildCtrl">
<h2>First controller</h2>
<button>+</button>{{Holder.value}}
</div>
<div ng-controller="ChildCtrl2">
<h2>Second controller</h2>
<button>+</button>{{Holder.value}}
</div>
</div>
<script>
var myapp = angular.module("dataServiceApp",[]);
myapp.factory('Holder', function() {
return {
value: 0
};
});
myapp.controller('ChildCtrl', function($scope, Holder) {
$scope.Holder = Holder;
$scope.increment = function() {
$scope.Holder.value++;
};
});
myapp.controller('ChildCtrl2', function($scope, Holder) {
$scope.Holder = Holder;
$scope.increment = function() {
$scope.Holder.value++;
};
});
</script>
</body>
</html>
You have forgotten to register onclick listeners to the buttons:
<button ng-click="increment()">+</button>{{Holder.value}}
Hope this helps. Complete working example below:
<!DOCTYPE html>
<html>
<head>
<title>AngularJS Services</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.5/angular.min.js"></script>
</head>
<body>
<div ng-app="dataServiceApp">
<div ng-controller="ChildCtrl">
<h2>First controller</h2>
<button ng-click="increment()">+</button>{{Holder.value}}
</div>
<div ng-controller="ChildCtrl2">
<h2>Second controller</h2>
<button ng-click="increment()">+</button>{{Holder.value}}
</div>
</div>
<script>
var myapp = angular.module("dataServiceApp",[]);
myapp.factory('Holder', function() {
return {
value: 0
};
});
myapp.controller('ChildCtrl', function($scope, Holder) {
$scope.Holder = Holder;
$scope.increment = function() {
$scope.Holder.value++;
};
});
myapp.controller('ChildCtrl2', function($scope, Holder) {
$scope.Holder = Holder;
$scope.increment = function() {
$scope.Holder.value++;
};
});
</script>
</body>
</html>
p.s. I also fully agree with JB Nizet's comment: check whether you really need to learn AngularJS instead of Angular 2-7/VueJS/React.

Get autocompleted value from input in controller

I have the following in my view:
<label for="txtFrom">Pickup Location</label>
<input type="text" id="pickup" placeholder="Address, aiport, train station, hotel..." ng-model="pickup">
<label for="txtDestination">Destination</label>
<input type="text" id="destination" placeholder="Address, aiport, train station, hotel..." ng-model="destination">
<input class="btn btn-success" name="calcPrice" id="calcPrice" type="submit" value="Calculate Price" ng-click="calcPrice()">
I am using google maps api for places to autocomplete the input boxes, so if a user starts typing "Lo", he will get a list of places that starts with "Lo" and for example he chooses London.
The problem is in my controller I am not getting the whole autocompleted value. I am only getting what the user initially entered, in this case "Lo".
Here is my controller:
app.controller('BookingsCtrl', function($scope, BookingsService) {
$scope.pickup = "";
$scope.destination = "";
$scope.syncNotification = "";
$scope.calcPrice = function() {
console.log($scope.pickup);
BookingsService.save({
pickup: $scope.pickup,
destination: $scope.destination
}, function(response) {
console.log(response.message);
});
};
});
EDIT:
Here is also a snippet of the JS:
var pickup = document.getElementById('pickup');
var options = {
componentRestrictions: {
country: 'ee'
}
};
var autocompletePickup = new google.maps.places.Autocomplete(pickup, options);
google.maps.event.addListener(autocompletePickup, 'place_changed', function () {
var place = autocompletePickup.getPlace();
pickup.innerHtml = place.formatted_address;
var lat = place.geometry.location.lat();
var long = place.geometry.location.lng();
});
EDIT 2 : Added service
app.service('BookingsService', function ($resource) {
return $resource('http://localhost:3000/', {});
});
EDIT 3 : Template
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="components/bootstrap/dist/css/bootstrap.min.css" type="text/css" />
<link rel="stylesheet" href="assets/css/style.css" type="text/css" />
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDt1Y30OssBToIzSCOr3g5IkN3c0D75XVE&libraries=places"
></script>
</head>
<body ng-app='strelsau_client'>
<div class="site-wrapper">
<div class="site-wrapper-inner">
<div class="cover-container">
<div class="masthead clearfix">
<div class="inner">
<img class="masthead-brand" src="../assets/img/logo.png">
<nav>
<ul class="nav masthead-nav">
<li class="active">Home</li>
<li>Contact</li>
</ul>
</nav>
</div>
</div>
<div ng-view>
</div>
</div>
</div>
</div>
<script src="components/jquery/dist/jquery.min.js"></script>
<script src="components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="components/angular/angular.min.js"></script>
<script src="components/angular-route/angular-route.min.js"></script>
<script src="components/angular-resource/angular-resource.min.js"></script>
<script src="js/main.js"></script>
<script src="js/controllers/bookings_controllers.js"></script>
<script src="js/services/bookings_service.js"></script>
</body>
</html>
In fact pickup input element is not getting updated once the place is resolved.
The problem with this function:
google.maps.event.addListener(autocompletePickup, 'place_changed', function () {
var place = autocompletePickup.getPlace();
pickup.innerHtml = place.formatted_address; //invalid
//...
});
For setting input field value should be used value property.
Anyway, given the example, try to replace it with:
(function (scope) {
google.maps.event.addListener(autocompletePickup, 'place_changed', function () {
var place = autocompletePickup.getPlace();
scope.pickup = place.formatted_address;
});
})($scope);
Example
angular.module('myApp', [])
.controller('BookingsCtrl', function ($scope) {
$scope.pickup = "";
$scope.destination = "";
$scope.syncNotification = "";
var pickup = document.getElementById('pickup');
var options = {
componentRestrictions: {
country: 'ee'
}
};
var autocompletePickup = new google.maps.places.Autocomplete(pickup, options);
(function (scope) {
google.maps.event.addListener(autocompletePickup, 'place_changed', function () {
var place = autocompletePickup.getPlace();
scope.pickup = place.formatted_address;
});
})($scope);
$scope.calcPrice = function () {
console.log($scope.pickup);
alert($scope.pickup);
/*BookingsService.save({
pickup: $scope.pickup,
destination: $scope.destination
}, function (response) {
console.log(response.message);
});*/
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>
<div ng-app="myApp" ng-controller="BookingsCtrl" ng-cloak>
<label for="txtFrom">Pickup Location</label>
<input type="text" id="pickup" placeholder="Address, aiport, train station, hotel..." ng-model="pickup">
<label for="txtDestination">Destination</label>
<input type="text" id="destination" placeholder="Address, aiport, train station, hotel..." ng-model="destination">
<input class="btn btn-success" name="calcPrice" id="calcPrice" type="submit" value="Calculate Price" ng-click="calcPrice()">
</div>

AngularJS POST and GET 404 Error

Using AngularJS, I'm trying to post data from a form into an ng-repeat and save to a database. When I click submit, I get the 404 error for post and get. Can someone help show me where I went wrong?
Here's my html:
<html ng-app="Inventory-App">
<head>
<meta charset="utf-8">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.js" charset="utf-8"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<!-- SEMANTIC -->
<link rel="stylesheet" type="text/css" href="../semantic/dist/semantic.min.css">
<script src="../semantic/dist/semantic.min.js"></script>
<!-- MY STUFF -->
<link rel="stylesheet" href="../css/styles.css" media="screen" title="no title" charset="utf-8">
<script src="../scripts/script.js" charset="utf-8"></script>
<script src="../scripts/services/itemsAPI.js" charset="utf-8"></script>
<script src="../scripts/controllers/main.js" charset="utf-8"></script>
<script src="../scripts/app.js" charset="utf-8"></script>
</head>
<body ng-controller="MainController">
<nav>
<h1>Cabinet.me</h1>
<p>An Inventory of Your Kitchen</p>
</nav>
<div class="ui container">
<form class="ui form">
<div class="field">
<label>Item</label>
<input type="text" placeholder="Item" ng-model="post.name">
</div>
<div class="field">
<label>Details (if any)</label>
<input type="text" placeholder="Details" ng-model="post.details">
</div>
<div class="field">
<label>Amount</label>
<select class="ui dropdown" ng-model="post.amount">
<option value="">Amount</option>
<option value="1">High</option>
<option value="1">Medium</option>
<option value="0">Low</option>
</select>
</div>
<button class="ui button" type="submit" ng-click="createItem(post)">Submit</button>
</form>
<div class="ui divider"></div>
<div class="ui cards">
<div class="card" ng-repeat="item in items | orderBy: 'created_at':true">
<div class="content">
<div class="header">{{item.name}}</div>
<div class="meta">Availability: {{item.amount}}</div>
<div class="description">
{{item.details}}
</div>
<button class="ui secondary button">
Delete
</button>
</div>
</div>
</div>
</div>
</body>
</html>
Here's my Controller:
angular
.module('mainController', ['itemsAPI'])
.controller('MainController', ['$scope', '$http', 'itemsAPI',
function( $scope, $http, itemsAPI ) {
$scope.items = [];
// $scope.itemData = '';
$scope.createItem = function(post){
var newItem = {
item : {
name: post.name,
details: post.details,
amount: post.amount
}
}
itemsAPI.create(newItem).then(function(response){
console.log(response);
$scope.items.push(response.data);
})
itemsAPI.getAll().then(function(response){
$scope.items = response.data;
});
}
$scope.removeItem = function(item){
itemsAPI.remove(item._id).then(function(response){
if (response.status == 203) {
$scope.items = $scope.items.filter(function(i){
return i._id != item._id;
});
}
});
}
}]);
Here's the itemsAPI code:
angular
.module('itemsAPI', [])
.factory('itemsAPI', ['$http',
function($http) {
return {
getAll: function(){
return $http.get('/items');
},
create: function(newItem){
return $http.post('/items', newItem);
},
remove: function(id){
return $http.delete('/items/' + id);
}
}
}])
And my API route:
var express = require('express');
var router = express.Router();
var Item = require('../../models/item');
// Get
router.get('/', function(req, res, next) {
Item.find(function(err, items) {
if (err) {
next(err);
}else {
res.json(items);
}
})
});
router.post('/', function(req, res, next) {
Item.create(req.body.item, function(err, item) {
if (err) {
next(err);
}else {
res.json(item);
}
});
});
router.delete('/:id', function(req, res, next) {
Item.findByIdAndRemove(req.params.id, function(err) {
if (err) {
next(err);
}else {
res.status(203).end();
}
})
});
module.exports = router;
I appreciate any help I can get!
Replace this
router.post('/', function(req, res){
with
router.post('/items', function(req, res){
in inventory/server/routes/api/items.js
Edit:
I'm mistaken. You use '/api/items' route in app.js and not necessary to add 'items' path as I wrote above. But on the client side you try to post your data on the '/items' route not on '/api/items'.

Angular - Get data into ng-Model from object in controller

I am not able to put the data into ng-model in view from an object in controller.
VIEW1 :
<input type="text" class="user-input" name="profile.firstname" ng-model="profile.firstname" ng-minlength="2" required pattern=".{2,}" placeholder="E.g. Anvika" title="Please enter atleast 2 characters">
When I click a button in VIEW2, it fires a function (say function 'test').
VIEW2
<input type="submit" ng-click="register.test()" ui-sref="doctorRegister" value="Profile">
CONTROLLER:
var app = angular.module('app');
app.controller('registerController', ['$scope', 'tempDataStorageService', function ($scope, tempDataStorageService) {
var register = this;
register.doctor = {};
register.test = function () {
register.refreshProfile = tempDataStorageService.get(register.doctor.profile);
//console.log(register.refreshProfile);
var a = register.refreshProfile.firstname;
console.log(a);
}
}
TempDataStorageService:
var app = angular.module('app');
app.factory('tempDataStorageService', function() {
var savedData = {};
function set(data) {
savedData = data;
}
function get() {
return savedData;
}
return {
set: set,
get: get
}
});
EDIT: I have tried to show the declaration of the controller as well, if that helps.
How can I make it so that when I click on the Profile button on VIEW2, it populates VIEW1 with the data?
The plunker:
Working example
The html:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.8/angular.js" data-semver="1.4.8"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl as mainCtrl">
<form>
<h2 class="text-primary">Get data into ng-Model from object in controller</h2>
<hr>
<div class="form-group">
<h3 ng-class="!mainCtrl.firstName? 'text-danger' : 'text-success'">Enter Name</h3>
<input type="text" class="form-control" ng-model="mainCtrl.firstName" placeholder="E.g. Anvika">
</div>
<hr>
<h3 class="text-info">This is what you are typing: {{mainCtrl.firstName}}</h3>
<button type="button" class="btn btn-success" ng-click="mainCtrl.test()">Save Name</button>
</form>
<hr>
<h3 class="text-info">This is what is stored</h3>
<h4>Doctor first name: {{mainCtrl.storedData.doctorFirstName}}</h4>
</body>
</html>
The JS:
var app = angular.module('plunker', []);
app.controller('MainCtrl', ['tempDataStorageService', function(tempDataStorageService) {
var register = this;
register.firstName = "";
register.storedData = tempDataStorageService;
register.test = function () {
tempDataStorageService.setName(register.firstName);
}
}]);
app.factory('tempDataStorageService', function() {
// The service object
var profile = {};
profile.doctorFirstName = "No doctor data stored";
//The functions
profile.setName = function(data) {
profile.doctorFirstName = data;
}
profile.getName = function() {
return profile.doctorFirstName;
}
// return the service object
return profile;
});
Recommendations:
Please properly format code when asking questions.
As good practice use a style guide. A good starting point is John
Papa's Angular Style Guide

AngularJS broadcast from $rootScope to modal window scope

Is there any way to broadcast from $rootScope to modal window $scope?
My $rootScope is ApplicationController and I'm listening in there to socket.io event. When I handle this event I want to $broadcast to ChatController (modal window) $scope (which might be already opened so resolve won't help me here).
A quick example to demonstrate this issue:
index.html:
<!DOCTYPE html>
<html ng-app="App">
<head>
<link data-require="bootstrap-css#3.1.1" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
<script data-require="angular.js#1.3.0-beta.5" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<script data-require="jquery#*" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script data-require="bootstrap#3.1.1" data-semver="3.1.1" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script data-require="angular-ui-bootstrap#0.11.0" data-semver="0.11.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="ApplicationController">
<h1>Hello Plunker!</h1>
<input type="button" value="open modal" ng-click="openModal()">
<div ng-controller="NotModalController">
{{fields.field1}}
</div>
</body>
</html>
script.js:
(function() {
var app = angular.module("App", ["ui.bootstrap"]);
app.controller("ApplicationController", function($scope, $modal) {
$scope.openModal = function() {
var modalInstance = $modal.open({
templateUrl: 'chat.html',
controller: 'ModalController',
size: 'lg',
resolve: {
}
});
modalInstance.result.then(function() {
console.log('modal closed');
}, function() {
console.log('modal dismissed');
});
setTimeout(function() {
console.log('broadcasting event');
$scope.$broadcast('someEvent', 'broadcasted value');
}, 3000);
};
});
app.controller("NotModalController", function($scope) {
$scope.fields = {
field1: 'initial'
};
$scope.$on('someEvent', function(event, args) {
$scope.fields.field1 = args;
});
});
app.controller("ModalController", function($scope) {
$scope.fields = {
field1: 'initial'
};
$scope.$on('someEvent', function(event, args) {
$scope.fields.field1 = args;
});
});
})();
modalTemplate.html
<div>
{{fields.field1}}
</div>
the plunkr url : http://plnkr.co/edit/9xpwmleZJnAG66cGWcYO
Think you should use $rootScope.$broadcast instead $scope.$broadcast

Resources