AngularJS : a web socket defines several functions inside a service.
Do you know how to call these functions (onCLose, send, ...) from a controller ??
The controller is called when i click on a button.
A error says "is not a function" about these 2 lines :
$scope.websocket.send and $scope.websocket.onClose
<!DOCTYPE html><html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="lib/angular.min.js"></script>
<script type="text/javascript" src="lib/angular-websocket.js"></script>
<script type="text/javascript">
var app = angular.module('myApp', ['ngWebSocket']);
app.service('WebSocketWrapper', ['$log', '$websocket', '$rootScope', function($log, $websocket, $rootScope){
var ws = null;
this.state = 'initializing';
this.message = 'websocket initializing';
var self = this;
this.init = function(){
if(!ws){
ws = $websocket('ws://127.0.0.1:8080/WebSocketHome/echo', null, {reconnectIfNorNormalClose: true});
ws.onClose(function(){
console.info('close');
$rootScope.$apply(function(){
self.state = 'disconnected';
self.message = 'Websocket disconnected';
});
});
ws.onOpen(function(){
console.info('connected');
$rootScope.$apply(function(){
self.state = 'connected';
self.message = 'websocket connected';
});
});
ws.onMessage(function(message){
console.log("RECEIVED : " + message);
});
}
};
}]);
app.controller('WebSocketStateCtrl', ['$scope', 'WebSocketWrapper', function($scope, WebSocketWrapper){
$scope.websocket = WebSocketWrapper;
$scope.websocket.init();
$scope.sendMessage = function(){
$scope.websocket.send($scope.name);
$scope.websocket.onClose();
}
}]);
</script>
</head>
<body>
<div ng-app="myApp" ng-controller="WebSocketStateCtrl">
<form action="">
<input type="text" ng-model="name">
<button ng-click="sendMessage()">SEND</button>
</form>
</div>
</body>
</html>
To get rid of the "is not a function" errors, you need to bind the ws object to the service object by using this.ws instead of var ws
With this, you need not return any object from the service.
So, your service code would look like -
app.service('WebSocketWrapper', ['$log', '$websocket', '$rootScope', function($log, $websocket, $rootScope){
this.ws = null; // Attach ws to service object
this.state = 'initializing';
this.message = 'websocket initializing';
var self = this;
this.init = function(){
if(!this.ws){
this.ws = $websocket('ws://127.0.0.1:8080/WebSocketHome/echo', null, {reconnectIfNorNormalClose: true});
this.ws.onClose(function(){
console.info('close');
$rootScope.$apply(function(){
self.state = 'disconnected';
self.message = 'Websocket disconnected';
});
});
this.ws.onOpen(function(){
console.info('connected');
$rootScope.$apply(function(){
self.state = 'connected';
self.message = 'websocket connected';
});
});
this.ws.onMessage(function(message){
console.log("RECEIVED : " + message);
});
}
};
}]);
I finally found the solution, thanks to Vandesh :
app.service('WebSocketWrapper', ['$log', '$websocket', '$rootScope', function($log, $websocket, $rootScope){
this.ws = null; // Attach ws to service object
this.state = 'initializing';
this.message = 'websocket initializing';
var self = this;
this.init = function(){
if(!this.ws){
this.ws = $websocket('ws://127.0.0.1:8080/WebSocketHome/echo', null, {reconnectIfNorNormalClose: true});
this.ws.onClose(function(){
console.info('close');
$rootScope.$apply(function(){
self.state = 'disconnected';
self.message = 'Websocket disconnected';
});
});
this.ws.onOpen(function(){
console.info('connected');
$rootScope.$apply(function(){
self.state = 'connected';
self.message = 'websocket connected';
});
});
this.ws.onMessage(function(message){
console.log("RECEIVED : " + message);
});
}
};
return this.ws;
}]);
app.controller('WebSocketStateCtrl', ['$scope', 'WebSocketWrapper', function($scope, WebSocketWrapper){
$scope.websocket = WebSocketWrapper;
$scope.websocket.init();
$scope.sendMsg = function sendMsg() {
$scope.websocket.ws.send($scope.name);
}
}]);
Related
I am new to angular and creating my first application using angular in it and getting this error.
"[$injector:unpr] Unknown provider: dataServiceProvider <- dataService <- firstctrl"
Below is my code for which i am getting the error.
my aspx page:
<asp:Content ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
<script type="text/javascript" src="../Scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script src="../Scripts/angular.js"></script>
<script src="../app/app.js"></script>
<script src="../app/shared/services/dataService.js"></script>
<script src="../app/controller/firstctrl.js"></script>
<meta name="WebPartPageExpansion" content="full" />
</asp:Content>
<asp:Content ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server">
Page Title
</asp:Content>
<asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server">
<div ng-app="rootapp" ng-controller="firstctrl">
{{first}} {{last}}
</div>
</asp:Content>
App.js
(function () {
'use strict';
angular
.module('rootapp', [
'ngRoute'
])
.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
controller: 'firstctrl',
templateURL: ''
})
.otherwise({ redirectTo: '/' });
}]);
})();
Controller JS
firstctrl.js
(function () {
'use strict';
var hostweburl;
var appweburl;
var SPLanguage;
var SPClientTag;
var SPProductNumber;
var context = SP.ClientContext.get_current();
var user = context.get_web().get_currentUser();
var UserDetails = "";
var ProjectList = "";
var queryStringValue = {};
var defaultQueryStringVal = '';
var ready = false;
var digest = "";
var UserEmailID = "";
var ExtLog = "";
var lineno = 0;
var country = '';
var ip = '';
var city = '';
var SettingsList = '';
var CurrentUser;
var btntext;
var UID;
var ConsolidatedValue;
var LiceKey;
var checkboxval;
var HostFlag;
angular
.module('rootapp', [])
.controller('firstctrl', ["$scope", "dataService", function ($scope, dataService) {
$scope.first = "John";
$scope.last = "Doe";
parseQueryString();
//replaced my api-key value from x
TogetCountry("https://api.ipdata.co/?api-key=xxxxxxxxxxxxxxxxxxxxxxxxxx");
function parseQueryString() {
var qstr = document.URL.split("?")[1].split("&");
var a = qstr;
for (var i = 0; i < a.length; i++) {
var b = a[i].split('=');
queryStringValue[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '');
}
SPLanguage = queryStringValue.SPLanguage || '';
SPClientTag = queryStringValue.SPClientTag || '';
SPProductNumber = queryStringValue.SPProductNumber || '';
hostweburl = queryStringValue.SPHostUrl;
appweburl = queryStringValue.SPAppWebUrl;
defaultQueryStringVal = "SPHostUrl=" + hostweburl + "&SPLanguage=" + SPLanguage + "&SPClientTag=" + SPClientTag + "&SPProductNumber=" + SPProductNumber + "&SPAppWebUrl=" + appweburl;
console.log("defaultQueryStringVal-----", defaultQueryStringVal);
}
function TogetCountry(url) {
console.log("TogetCountry");
dataService.GetCountry(url).then(function (result) {
console.log("result", result);
});
console.log("---------" + country, city, ip);
}
}]);
})();
dataservice.js
(function () {
'use strict';
angular
.module('rootapp')
.service('dataService', ['$http', '$q', function ($http, $q) {
var service = {};
service.GetCountry = function (URL) {
var deferred = $q.defer();
$http.get(URL).then(function (result) {
deferred.resolve(result.data);
}, function () {
deferred.reject();
});
return deferred.promise;
}
return service;
}]);
})();
Appreciate if get any help in resolving this.
You're defining rootapp twice. Once in App.js and once in firstctrl.js. You need to remove the [] from .module('rootapp', []) in firstctrl.js.
Trying to retrieve using angular the json found at: "https://api.github.com/users/angular", more precisely the id property from that json.
Any thoughts on why this fails (in debug mode I get a
'response is not defined'
):
<html ng-app="myViewer">
<head>
<script data-require="angular.js#*" data-semver="1.2.25" src="https://code.angularjs.org/1.2.25/angular.js"></script>
</head>
<body ng-controller="MyController">
{{ result.id }}
{{ err }}
</body>
<script type="text/javascript">
(function() {
var app = angular.module("myViewer", []);
var MyController = function($scope, $http)
{
$http.get("https://api.github.com/users/angular")
.then(function1, onerr);
var function1 = function(response)
{
$scope.result = response.data;
}
var onerr = function(reason)
{
$scope.err = "nightmare";
}
}
app.controller("MyController", ["$scope", "$http", MyController]);
}());
</script>
</html>
I expect the result to be the id that you can see by copying that link in your browser.
Here is a working fiddler https://jsfiddle.net/paka2/8roj37q9/1/
angular.module("myViewer", []).controller("myCtrl", function($scope,$http){
this.result = {};
this.err ;
$http.get("https://api.github.com/users/angular")
.then(function1, onerr) ;
function function1 (response)
{
$scope.result = response.data;
}
function onerr (reason)
{
$scope.err = "nightmare";
}
});
Hope it helps!!
Works if I correct the order:
var function1 = function(response)
{
$scope.result = response.data;
}
var onerr = function(reason)
{
$scope.err = "nightmare";
}
$http.get("https://api.github.com/users/angular")
.then(function1, onerr);
function1 should be defined before i call it with then.
I think your promise is wrong.
$http.get('https://api.github.com/users/angular').then(function(response){
$scope.result = response.data;
})
See same HTTP call working below:
https://plnkr.co/edit/8JqZ5NukHnHWGPxZ0GRr
try this i think you have incorrectly defined the controller as mycontroller and it should be SecondController instead.
app.controller("MyController", ["$scope", "$http", SecondController ]);
Try with following
var function1 = function(response) { $scope.result = response; }
/*service */
app.service('sharedProperties', function () {
var property = 'First';
return {
getProperty: function () {
return property;
},
setProperty: function(value) {
property = value;
}
};
});
/*first contoller */
app.controller('loginCtrl',function($scope,$location,$http,$window,sharedProperties){
$scope.submit =function(){
var username=$scope.username;
var pass=$scope.password;
sharedProperties.setProperty(username);
$location.path('/userdashboard');
$window.location.reload();
});
}
});
/*second controller*/
app.controller('empController', function($route,$scope,$http,$routeParams,sharedProperties){
$scope.getEmployees = function(){
alert( sharedProperties.getProperty());
};
};
Try this, it will work for you. :
<div ng-app="myApp" ng-controller="myCtrl">
<button ng-click="sendData();"></button>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
function sendData($scope) {
var arrayData = [1,2,3];
$scope.$emit('someEvent', arrayData);
}
});
app.controller('yourCtrl', function($scope, $http) {
$scope.$on('someEvent', function(event, data) {
console.log(data);
});
});
</script>
Service does not need to return anything. You have to assign everything in this variable. Because service will create instance by default and use that as a base object.
app.service('sharedProperties', function () {
this.property = 'First';
});
Then in controller
sharedProperties.property = $scope.username;
Had you been looking to use factory
app.factory('sharedProperties', function () {
var factory = {};
factory.property = 'Hello';
factory.setProperty = function (value) {
factory.property = value;
};
return factory;
});
Then in controller you would use it
sharedProperties.setProperty($scope.username); // Setter
$scope.var = sharedProperties.property; //getter
EDIT
Working Plnkr
You can assign members to $rootScope, which will store data globally for your app. Just inject $rootScope to each controller.
For instance...
/*first controller */
app.controller('loginCtrl',function($scope,$rootScope,$location,$http,$window,sharedProperties){
$scope.submit =function(){
var username=$scope.username;
var pass=$scope.password;
$rootScope.username = username;
$location.path('/userdashboard');
$window.location.reload();
});
}
});
This will make 'username' available to any controller that injects and consumes $rootScope.
/*second controller*/
app.controller('empController', function($route,$scope,$rootScope,$http,$routeParams,sharedProperties){
$scope.getEmployees = function(){
alert($rootScope.username);
};
};
I am writing unit tests for angularjs application. I am using karma,jasmine as the tools for writing and testing the unit test cases.
Below are code components:
app.js
(function() {
"use strict";
angular.module("indirectTax.core", []);
angular.module('indirectTax', ['mgcrea.ngStrap', 'ngRoute', 'ngSanitize', 'cfp.hotkeys', 'ngUpload', 'LocalStorageModule', 'indirectTax.core', 'angulartics', 'ng.shims.placeholder', 'brantwills.paging', 'ngMask']).config(['$routeProvider',
function($routeProvider) {
$routeProvider.when('/dashboard', {
templateUrl: 'dashboard/dashboard.html',
controller: 'DashboardController as ctrl'
}).when('/terms/:id', {
templateUrl: 'terms/terms.html',
controller: 'TermsController as ctrl'
}).otherwise({
redirectTo: '/dashboard'
});
}
]).config(["$httpProvider",
function($httpProvider) {
// Disable IE9 Ajax Request Caching.
if (!$httpProvider.defaults.headers.get) {
$httpProvider.defaults.headers.get = {};
}
}
]).config(['hotkeysProvider',
function(hotkeysProvider) {
// Override the original hotkeys template, in order to add a wrapper
hotkeysProvider.template = "<div ng-include=\"'hotkeys-template.html'\"></div>";
hotkeysProvider.cheatSheetDescription = 'Show / Hide current shortcuts';
}
]).run(['initData', 'core.lib.common', '$rootScope', 'hotkeys', 'localStorageService', '$location',
function(initData, common, $rootScope, hotkeys, localStorageService, $location) {
common.setConfig(initData.configFile);
common.currentUser = initData.currentUser;
$rootScope.$on('$viewContentLoaded', function(event) {
angular.element('#main-footer').fadeIn(500);
});
}
]).constant("toastr", toastr).constant("interact", interact).constant("html2canvas", html2canvas);
})();
users-details-controller.js
var UsersDetailsController = (function () {
function UsersDetailsController($controller, userService, $location, $route, common) {
this.userService = userService;
this.$location = $location;
this.$route = $route;
this.common = common;
this.loading = true;
this.predicate = "userName";
this.reverse = false;
this.searchKey = "";
this.users = [];
this.activeAmount = 0;
this.inactiveAmount = 0;
this.checkPermissions();
this.init();
}
// Only root users should have access to the "User Details" page
UsersDetailsController.prototype.checkPermissions = function () {
if (this.common.currentUser.role !== this.common.constants.ROOT_ROLE) {
this.$location.path("/dashboard");
}
};
UsersDetailsController.prototype.init = function () {
this.getUserList();
};
///////////
//API Calls
//Get selected question set info
UsersDetailsController.prototype.getUserList = function () {
var self = this;
self.loading = true;
self.userService.getUsersList().then(function (data) {
self.loading = false;
self.users = data.users;
self.activeAmount = data.activeUsersCount;
self.inactiveAmount = data.inactiveUsersCount;
}, function (data) {
self.loading = false;
});
};
UsersDetailsController.$inject = ['$controller', 'core.api.user', '$location', '$route', 'core.lib.common'];
return UsersDetailsController;
})();
angular.module('indirectTax').controller('UsersDetailsController', UsersDetailsController);
users-details-controller-spec.js
describe("user-details-controller", function () {
// Before each test runs we're going to need ourselves an Angular App to test - go fetch!
beforeEach(function () {
module("indirectTax"); // module is an alias for angular.mock.module
});
// Tests for the sageDetail controller
describe("usersDetailsController ->", function () {
var $rootScope, $scope, $q, $location, common, userService, //controller depedencies
usersDetailsController; // controller
// Before each test runs set up the controller using inject - an alias for angular.mock.inject
beforeEach(inject(function (_$controller_, _$rootScope_, _$q_, _$location_, _common_, _userService_) {
$scope = {};
// Note how each parameter is prefixed and suffixed with "_" - this an Angular nicety
// which allows you to have variables in your tests with the original reference name.
// So here we assign the injected parameters to the describe-scoped variables:
$rootScope = _$rootScope_;
$q = _$q_;
$location = _$location_;
common = _common_;
userService = _userService_;
// create a usersDetails controller and inject the dependencies we have set up
usersDetailsController = _$controller_("UsersDetailsController", {
$scope: $scope,
$location: $location,
common: common,
userService: userService
});
}));
it("controller should have initial predicate value 'userName'", function () {
// tests this code has executed:
//this.predicate = "userName";
expect(usersDetailsController.predicate).toBe("userName");
});
});
});
SpecRunner.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Jasmine Spec Runner v2.3.4</title>
<link rel="shortcut icon" type="image/png" href="libs/jasmine-2.3.4/jasmine_favicon.png">
<link rel="stylesheet" href="libs/jasmine-2.3.4/jasmine.css">
<script src="libs/jasmine-2.3.4/jasmine.js"></script>
<script src="libs/jasmine-2.3.4/jasmine-html.js"></script>
<script src="libs/jasmine-2.3.4/boot.js"></script>
<!-- inject:vendor:js -->
<script src="libs/jquery.js"></script>
<script src="libs/angular.js"></script>
<script src="libs/angular-mocks.js"></script>
<script src="libs/angular-local-storage.js"></script>
<script src="libs/angular-route.js"></script>
<script src="libs/angular-sanitize.js"></script>
<script src="libs/angular-shims-placeholder.js"></script>
<script src="libs/angular-strap.js"></script>
<script src="libs/angular-strap.tpl.js"></script>
<script src="libs/angulartics.js"></script>
<script src="libs/deferred-bootstrap.js"></script>
<script src="libs/hotkeys.js"></script>
<script src="libs/html2canvas.js"></script>
<script src="libs/interact.js"></script>
<script src="libs/moment.js"></script>
<script src="libs/ng-upload.js"></script>
<script src="libs/ngMask.min.js"></script>
<script src="libs/paging.js"></script>
<script src="libs/toastr.js"></script>
<!-- endinject -->
<!-- inject:js -->
<script src="core/app.js"></script>
<script src="core/lib/init.js"></script>
<script src="core/api/user-service.js"></script>
<script src="core/lib/analytics.js"></script>
<script src="core/lib/common.js"></script>
<script src="core/lib/ng-interact.js"></script>
<!-- include source files here... -->
<script src="admin/users-details-controller.js"></script>
<!-- include spec files here... -->
<script src="spec/admin/users-details-controller-spec.js"></script>
</head>
<body>
</body>
</html>
Now I am triggering the http-server and trying to run the SpecRunner.html file. But I am getting the below mentioned error:
init.js
var Core;
(function (Core) {
var Lib;
(function (Lib) {
var Init = (function () {
function Init($http, $q, common, user) {
this.$http = $http;
this.$q = $q;
this.common = common;
this.user = user;
this.initData = new Core.Models.InitData();
}
Init.prototype.resolve = function () {
var self = this;
var deferred = this.$q.defer();
this.$q.all([this.loadConfig()]).then(function () {
return self.getCurrentUser(self.getAPIURL());
}).then(function () {
deferred.resolve(self.initData);
});
return deferred.promise;
};
Init.prototype.loadConfig = function () {
var self = this;
var deferred = this.$q.defer();
self.$http.get(self.common.constants.CONFIG_FILE).then(function (response) {
self.initData.configFile = response.data;
deferred.resolve();
});
return deferred.promise;
};
Init.prototype.getCurrentUser = function (api_url) {
var self = this;
var deferred = this.$q.defer();
self.user.getCurrent(api_url).then(function (user) {
self.initData.currentUser = user;
deferred.resolve();
});
return deferred.promise;
};
Init.prototype.getAPIURL = function () {
if (this.initData.configFile) {
return this.initData.configFile.API_URL;
}
return this.common.constants.API_URL;
};
Init.$inject = ["$http", "$q", "core.lib.common", "core.api.user"];
return Init;
})();
Lib.Init = Init;
angular.module("indirectTax.core").service("core.lib.init", Init);
angular.element(document).ready(function () {
deferredBootstrapper.bootstrap({
element: document.body,
module: "indirectTax",
injectorModules: "indirectTax.core",
resolve: {
initData: ["core.lib.init", function (init) {
return init.resolve();
}]
}
});
});
})(Lib = Core.Lib || (Core.Lib = {}));
})(Core || (Core = {}));
Can anyone guide me to resolve the error?
I have a service to share data between controllers and a controller to handle $http request in my application. I use list with ng-repeat to display
data and currently have hardcoded JSON data on service. I plan to modify the hardcoded method to get data from server using $http.post and I got the data but my list is not updated. I have tried adding $timeout but still no luck.
Here is my code:
app.service("Storage", function ($rootScope, $http, $q) {
var predicate = 'name';
var reverse = false;
var content = this;
content.items = [];
content.filteredItems = [];
return {
requestData: function() {
var deferred = $q.defer();
var data = $.param({
json: JSON.stringify({
req_type: 'type_1',
reg_name: 'name_2'
})
});
$http.post("http://yourdomain/json.php", data)
.success(function(data, status) {
deferred.resolve(data);
})
.error(function(data) {
deferred.reject(data);
});
return deferred.promise;
},
setContent : function(data){
content.items = data;
},
getContentItems : function () {
return content.items;
}
}
});
Controller:
app.controller('MainController', function($scope, $window, $filter, $timeout, $http, Storage) {
$scope.predicate = null;
$scope.reverse = null;
this.items = null;
Storage.requestData().then(function(data) {
Storage.setContent(data);
$timeout(function(){
$scope.predicate = Storage.getPredicate();
$scope.reverse = Storage.getReverse();
this.items = Storage.getContentItems();
});
//$scope.$apply();
console.log('After11 : ' + JSON.stringify(Storage.getContentItems()));
});
});
You made mistake at this line:
this.items = Storage.getContentItems();
this !=== controller's this
I always create mv variable at the top of controller and use mv instead of this for avoiding this mistake.
angular
.module('app', [])
.service('Storage', function($http, $q, $timeout) {
var content = this;
var items = [];
this.requestData = function() {
var deferred = $q.defer();
//TODO Some http request
$timeout(function() {
deferred.resolve(['A', 'B', 'C']);
}, 1000);
return deferred.promise;
};
this.setContent = function(data) {
items = data;
};
this.getContentItems = function() {
return items;
};
})
.controller('MainCtrl', function(Storage) {
var mv = this;
mv.items = [];
Storage.requestData().then(function(data) {
Storage.setContent(data);
mv.items = Storage.getContentItems();
});
});
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<meta charset="utf-8">
</head>
<body ng-app="app">
<ul ng-controller="MainCtrl as mv">
<li ng-repeat="item in mv.items" ng-bind="item"></li>
</ul>
</body>
</html>