var l = $scope.PendingKOTitems.length,
k = 0;
for (k = 0; k < l; k = k + 1) {
sItemCode = $scope.PendingKOTitems[k]["sItemCode"]
sOutletCode = $scope.selectedOutlet.sOutletCode;
sFinal = sOutletCode + "/" + sSubCatgCode
$http.get(sServiceURL + 'ItemMst/' + sFinal).then(function (resp) {
$scope.Items = resp.data;
iindexItem = getIndexOf($scope.Items, sItemCode, "sItemCode");
}, function (err) {
console.error('ERR', err);
// err.status will contain the status code
})
sCheckValue = $scope.CheckboxSelection.value;
$scope.invoice.items.push({
KOTNo: $scope.KOTNumValue,
ActiveMode: $scope.lActiveMode,
SubCatgCode: sSubCatgCode,
SubCatgDesc: sSubCatgDesc,
indexSubCatg: iindexSubCatg,
ItemCode: sItemCode,
ItemDesc: sItemDesc,
indexItem: iindexItem,
Qty: sQty,
OutletCode: sOutletCode,
BillType: sBillType,
MemberCode: sMemberCode,
RoomNum: sRoomNum,
BookingCode: dBookingCode,
TableCode: sTableCode,
WaiterCode: sWaiterCode,
UserID: sUserID
});
}
The get methode not fire in the for loop, after perform for loop it will fire.
I want get 'iindexItem' value for load select based on item sub category. But get method fire after the 'push' operation perform. so i was not able to get 'iindexItem' value. this my problem.
I tried this and this seems to work fine for me --
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular.js"></script>
</head>
<body ng-app="app">
<div ng-controller="ctrl">
<h1>This is a Heading</h1>
<p>This is a paragraph.</p>
</div>
<script type="text/javascript">
var angularapp = angular.module("app",[]);
angularapp.controller('ctrl', ['$scope', '$window', '$http', '$filter', '$timeout', MyCtrl]);
function MyCtrl($scope, $window, $http, $filter, $timeout){
for(var i=0; i<3; i++){
$http.get("http://httpbin.org/get").then(function (resp) {
debugger;
$scope.Items = resp.data; // here I set my breakpoint
console.log(i);
console.log(resp.data);
}, function (err) {
console.error('ERR', err);
// err.status will contain the status code
});
}
}
</script>
</body>
</html>
The debugger is hit on every iteration in the for loop.
Related
I am following Brad Daley's Book on angular framework. In the console it leads me to the following
I have a simple angular 1.7.8 app however I keep getting the following error;
Error: $injector:unpr
Unknown Provider.
url : https://code.angularjs.org/1.7.8/docs/error/$injector/unpr?p0=configTimeProvider%20%3C-%20configTime%20%3C-%20controllerA
var configApp = angular.module('configApp1', []);
configApp.config(function ($provide) {
$provide.value = ("configTime", new Date());
$provide.value = ("runTime", new Date());
for (var i = 0; i < 10000000; i++) {
var y = Math.sqrt(Math.log(i))
};
})//end config
configApp.run(function(configTime,runTime){
runTime.setTime(new Date().getTime());
});
configApp.controller('controllerA', ['$scope', 'configTime', 'runTime',
function ($scope, configTime, runTime) {
$scope.configTime = configTime;
$scope.runTime = runTime;
}])
The HTML is as a follows
<!DOCTYPE html>
<html ng-app = 'configApp1'>
<head>
<title>Configuration Run Blocks in Angular</title>
</head>
<body>
<div ng-controller = 'controllerA' >
<h2>Config Time</h2>
{{configTime}}
<h2></h2>
<hr>
<h2>Run Time</h2>
{{runTime}}
<h2></h2>
</div>
<script src="../angular/angular.min.js"></script>
<script src="js/config.js"></script>
</body>
</html>
Invoke $provide.value as a method of the $provide service:
var configApp = angular.module('configApp1', []);
configApp.config(function ($provide) {
̶$̶p̶r̶o̶v̶i̶d̶e̶.̶v̶a̶l̶u̶e̶ ̶=̶ ̶(̶"̶c̶o̶n̶f̶i̶g̶T̶i̶m̶e̶"̶,̶ ̶n̶e̶w̶ ̶D̶a̶t̶e̶(̶)̶)̶;̶
$provide.value("configTime", new Date());
̶$̶p̶r̶o̶v̶i̶d̶e̶.̶v̶a̶l̶u̶e̶ ̶=̶ ̶(̶"̶r̶u̶n̶T̶i̶m̶e̶"̶,̶ ̶n̶e̶w̶ ̶D̶a̶t̶e̶(̶)̶)̶;̶
$provide.value("runTime", new Date());
for (var i = 0; i < 10000000; i++) {
var y = Math.sqrt(Math.log(i))
};
})//end config
For more information, see
AngularJS $provide Service API Reference - value
Having resolved a couple of errors thanks to #sehaxx in Angularjs binding value from service I would like introduce async in the example as in the following code where a variable is initialized asynchronously and it's value is not reflected in the view.
(function(angular) {
'use strict';
angular.
module('myServiceModule', []).
controller('MyController', ['$scope', 'notify','$log', function($scope, notify, $log) {
this.clickCount = 0;
this.clickLimit = notify.clickLimit();
this.callNotify = function(msg) {
notify.push(msg);
this.clickCount = notify.clickCount();
$log.debug("[controller] Click count is now", this.clickCount, " and limit is ", this.clickLimit);
};
}]).
factory('notify', ['$window','$log', '$timeout', function(win,$log, $timeout) {
var msgs = [];
var clickCounter = 0;
var countLimit = 0;
$timeout( function(){
countLimit = Math.floor(Math.random() * 10)+1;
$log.debug("[service] Click limit initialized at", countLimit);
return countLimit;
}, 10);
return {
clickLimit: function(){
return countLimit;
},
clickCount: function() {
clickCounter = msgs.length;
$log.debug("[service] You are clicking, click count is now", clickCounter, " limit is ", countLimit);
return clickCounter;
},
push: function(msg) {
msgs.push(msg);
clickCounter = msgs.length;
$log.debug("[service] Counter is", clickCounter, " on ", countLimit);
if (msgs.length === countLimit) {
win.alert(msgs.join('\n'));
msgs = [];
}
}
}
}]);
})(window.angular);
Working example in pen
The reason this isn't working as expected is due to the fact that countLimit is a Primitive, and Primitives are always passed byVal rather than byRef, so there is no way for the factory to update the value at a later date.
Changing the countLimit to an Object fixes this, because the value of the Object is the Reference to the properties of the Object. In other words, we are able to pass byRef. We just have to update our code to refer to the Object's child property instead of referring to the value directly, i.e. countLimit.value.
working example: https://codepen.io/anon/pen/VVmdbE?editors=1111
(function(angular) {
'use strict';
angular.
module('myServiceModule', []).
controller('MyController', ['$scope', 'notify', '$log', function($scope, notify, $log) {
this.clickCount = 0;
this.clickLimit = notify.clickLimit();
this.callNotify = function(msg) {
notify.push(msg);
this.clickCount = notify.clickCount();
$log.debug("[controller] Click count is now", this.clickCount, " and limit is ", this.clickLimit.value);
};
}]).
factory('notify', ['$window', '$log', '$timeout', function(win, $log, $timeout) {
var msgs = [];
var clickCounter = 0;
var countLimit = {
value: 0,
};
$timeout(function() {
countLimit.value = Math.floor(Math.random() * 10) + 1;
$log.debug("[service] Click limit initialized at", countLimit.value);
return countLimit;
}, 10);
return {
clickLimit: function() {
$log.debug("called clickLimit");
return countLimit;
},
clickCount: function() {
clickCounter = msgs.length;
$log.debug("[service] You are clicking, click count is now", clickCounter, " limit is ", countLimit);
return clickCounter;
},
push: function(msg) {
msgs.push(msg);
clickCounter = msgs.length;
$log.debug("[service] Counter is", clickCounter, " on ", countLimit);
if (msgs.length === countLimit.value) {
win.alert(msgs.join('\n'));
msgs = [];
}
}
}
}]);
})(window.angular);
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-services-usage-production</title>
<script src="https://code.angularjs.org/snapshot/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="myServiceModule">
<div id="simple" ng-controller="MyController as self">
<p>Let's try this simple notify service, injected into the controller...</p>
<input ng-init="message='test'" ng-model="message">
<button ng-click="self.callNotify(message);">NOTIFY</button>
<p>(you have to click {{self.clickLimit.value-self.clickCount}} times more to see an alert)</p>
<div>You have clicked {{ self.clickCount }} times</div>
</div>
</body>
</html>
So I am getting an angular [$injector:unpr] error. Yes, I know what that normally means...I haven't defined something somewhere, or I am redefining the module over and over, or the like...but for the life of me I'm struggling to see the issue in my code.
I'm sure I'm missing something insanely basic, but after I've stared at code for a couple of hours, I go blind to it.
My HTML File:
<!DOCTYPE html>
<html ng-app="email">
<head>
<meta charset="UTF-8">
<title>Authentication</title>
<link href='https://fonts.googleapis.com/css?family=Roboto:400,100,300,500,700' rel='stylesheet' type='text/css'/>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
</head>
<body>
<script src="bower_components/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="node_modules/angular/angular.min.js"></script>
<div ng-controller="EmailAuthController as auth">
<h1>Authentication</h1>
<p>Request: [{{auth.request}}]</p>
<p>{{auth.response}}</p>
<p>{{1+2}}</p>
</div>
<script type="text/javascript" src="js/controllers/email.js"></script>
</body>
</html>
My email.js file (As you can see, I've commented out some stuff to try to isolate the issue):
/* global angular parseGet */
function parseGet(val) {
var result = '', // = "Not found",
tmp = [];
var items = location.search.substr(1).split('&');
for (var index = 0; index < items.length; index++) {
tmp = items[index].split('=');
if (tmp[0] === val) {
result = decodeURIComponent(tmp[1]);
}
}
return result;
}
(function () {
angular
.module('email', [])
.controller('EmailAuthController', [ '$scope','authFactory', function ($scope,authFactory) {
var vm = this,
req = parseGet('hash') || '';
vm.request = req;
// authFactory.validate(req)
// .then(function (response) {
// vm.response = response.data;
// });
}])
.factory('authFactory', [ '$rootScope', '$http', 'config', function ($rootScope, $http, config) {
var validate = function (hash) {
var url = config.SERVICE_URI + '/auth/email/' + hash;
return $http.get(url);
};
return {
validate: validate
};
}]);
})();
From the code you've given it appears config is not defined in your authFactory injection.
.factory('authFactory', [ '$rootScope', '$http', 'config', function(a, b, c) {} ]); // config is not defined
So i've split out my UI into subcomponents but then i realise that one of the components requires to be react to a dropdown change which is caught by the parent controller.
I can create a shared service for the variables and i have been able to inject the sub controller so that i can kick off functions BUT.
how do i then use the scope within the sub controller?
var ctrl1= $scope.$new();
$controller('ctrl', { $scope: ctrl1});
ctrl1.GetData();
this works fine. I can see data coming back in the console. BUT my ui doesnt change. What am i missing?
I've edited the post to illustrate what i'm attempting to do more clearly.
The drop down on change is caught by the parent controller but i then require the child controller to run away and get some data and update the UI.
It's an attempt to split out the components. Is this possible? Or have a split the components out too far?
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js"></script>
<script>
angular.module('app2', [])
.controller('ctrl2', ['$scope', '$http', function($scope, $http){
$scope.getdata = function(){
$http.post(WebServiceURL)
.success(function(data){
$scope.app2Data = "test2 data";
});
}
}]);
angular.module('app1', ['app2'])
.controller('ctrl1', ['$scope','$controller',function($scope, $controller){
$scope.name = 'Controller 1';
//just something to put in the ddp
$scope.data = [
{id:1, name: "test"},
{id:2, name: "test2"}
]
$scope.makeChanged = function(id){
//ddp has changed so i refresh the ui with some other data which is in got by ctrl2.
var cl2 = $scope.$new();
$controller('ctrl2', { $scope: cl2 });
cl2.getdata();
}
}]);
</script>
</head>
<body ng-app="app1">
<div ng-controller="ctrl1">
<p>here is: {{name}}</p>
<select ng-model="d" ng-options="d as dat.name for dat in data track by dat.id" ng-change="makeChanged(d.id)"></select>
<div>
{{app2Data.text}}
</div>
</div>
</body>
</html>
for anyone interested here's how i got round this.
I created a shared service between the two controllers. and created a callback on the service. i registered the call back on ctrl2 so when the shared variable changed the controller2 will do what i want it to and scope is freshed.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js"></script>
<script>
angular.module('app1', ['app2'])
.controller('ctrl1', ['$scope', '$controller', 'appointmentSharedProperties',
function($scope, appointmentSharedProperties) {
$scope.name1 = 'Controller 1';
console.log('ctrl1');
//just something to put in the ddp
$scope.data = [{
id: 1,
name: 'test'
}, {
id: 2,
name: 'test2'
}];
$scope.makeChanged = function(value) {
//ddp has changed so i refresh the ui with some other data which is in got by ctrl2.
appointmentSharedProperties.setDetail(value);
console.log('in makeChanged: ' + value);
}
}
]).service('appointmentSharedProperties', function() {
var test = '';
var __callback = [];
return {
getDetail: function() {
return test;
},
setDetail: function(value) {
test = value;
if (__callback.length > 0) {
angular.forEach(__callback, function(callback) {
callback();
});
}
},
setCallback: function(callback) {
__callback.push(callback);
}
};
});
angular.module('app2', [])
.controller('ctrl2', ['$scope', 'appointmentSharedProperties',
function($scope, appointmentSharedProperties) {
$scope.name2 = 'Controller 2';
console.log('ctrl2');
var getdata = function() {
console.log('in getdata');
$scope.app2Data = appointmentSharedProperties.getDetail();
}
appointmentSharedProperties.setCallback(getdata);
}
]);
</script>
</head>
<body ng-app="app1">
<div ng-controller="ctrl1">
<p>here is: {{name1}}</p>
<p>here is: {{name2}}</p>
<select ng-model="d" ng-options="d as dat.name for dat in data track by dat.id" ng-change="makeChanged(d.name)"></select>
<div>
{{app2Data}}
</div>
</div>
</body>
</html>
General example of how to pass variables from one controller to other
<html>
<head>
<meta charset="ISO-8859-1">
<title>Basic Controller</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js">
</script>
</head>
<body ng-app="myApp">
<div ng-controller="ctrl1">
{{greeting}}
</div>
<div ng-controller="ctrl2">
{{dataToHtml2}}
</div>
</body>
</html>
This is the javascript file for this
var myApp = angular.module('myApp',[]);
myApp.service('sampleService', function(){
var temp = '';
this.setValue = function(data){
temp = data;
}
this.getValue = function(){
return temp;
}
});
myApp.controller('ctrl1', function($scope,sampleService) {
$scope.greeting = 'This line is in first controller but I exist in both';
var data= $scope.greeting;
sampleService.setValue(data);
});
myApp.controller('ctrl2', function($scope, sampleService){
$scope.dataToHtml2 =sampleService.getValue();
});
Here is the blog that explains this flow : Frequently asked questions in angularjs
It has the demo of what I written. Happy coding..!!
I have a small problem and I don't understand this thing:
When I add an item to TestiFactorys arr - array it does update to both controllers
On the other hand why does not TestiFactorys arr_len update to both controllers. And in TestiController why do I have to "manually" update TestControllers list1_length to make it update to view but I don't have to update TestiContollers list1 to make it update to view
I am assuming that my poor Javascript or Javascript variable scope understanding is causing this but i just don't see it.
I am using AngularJS version 1.2.16
<!DOCTYPE html>
<html ng-app="TestiApp">
<head>
<title></title>
</head>
<body>
<div ng-controller="TestController">
List items from controller: {{list1}}<br>
List item count:{{list1_length}}
<input type="text" ng-model="param"><br>
<button ng-click="list1_add(param)">asd</button>
</div>
<br><br>
<div ng-controller="TestController2">
List items from controller2{{list2}} <br>
List items count in from controller2: {{list2_length}}
</div>
<script src="scripts/angular.min.js"></script>
<script src="scripts/app.js"></script>
</body>
</html>
And this is my app.js:
var TestiApp = angular.module('TestiApp', [])
TestiApp.factory('TestiFactory',function() {
var arr = ['abx','cbs'];
var arr_len = arr.length;
return {
list : function() {
return arr;
},
add_to_arr : function(n) {
arr.push(n);
},
arr_len : function() {
arr_len = arr.length;
return arr_len;
}
}
}
);
TestiApp.controller('TestController', function($scope, TestiFactory) {
$scope.list1 = TestiFactory.list();
$scope.list1_length = TestiFactory.arr_len();
$scope.list1_add = function (d) {
TestiFactory.add_to_arr(d);
$scope.param = '';
$scope.list1_length = TestiFactory.arr_len();
}
});
TestiApp.controller('TestController2', function($scope, TestiFactory) {
$scope.list2 = TestiFactory.list();
$scope.list2_length = TestiFactory.arr_len();
});
EDIT WITH SOLUTION
Here is working solution. Based to comments I decided to do more studying on Javascripts basics which
is of course the thing I should have done before trying to use this complex framework which uses Javascript. So now I have some basic understanding how to use references in Javascript and what primitive data types are. And based on that here is working version:
<!DOCTYPE html>
<html ng-app="TestiApp">
<head>
<title></title>
</head>
<body>
<div ng-controller="TestController">
List items from controller: {{list1()}}<br>
List item count:{{list1_len()}}
<input type="text" ng-model="param"><br>
<button ng-click="list1_add(param)">asd</button>
</div>
<br><br>
<div ng-controller="TestController2">
List items from controller2{{list2()}} <br>
List items count in from controller2: {{list2_length()}}
</div>
<script src="scripts/angular.min.js"></script>
<script src="scripts/app.js"></script>
</body>
</html>
And app.js:
var TestiApp = angular.module('TestiApp', [])
TestiApp.factory('TestiFactory',function() {
var arr = ['abx','cbs'];
return {
list : function() {
return arr;
},
add_to_arr : function(n) {
arr.push(n);
},
arr_len : function() {
return arr.length;
}
}
}
);
TestiApp.controller('TestController', function($scope, TestiFactory) {
$scope.list1 = TestiFactory.list;
$scope.list1_add = TestiFactory.add_to_arr;
$scope.list1_len = TestiFactory.arr_len;
});
TestiApp.controller('TestController2', function($scope, TestiFactory) {
$scope.list2 = TestiFactory.list;
$scope.list2_length = TestiFactory.arr_len;
});
I've ran into this many times. Factories and services in angular are not like scopes...they work using references. The reason the array updates in your controllers is because the original reference was updated. The length is not updating because the number type is primitive.
This should work:
TestiApp.controller('TestController', function($scope, TestiFactory) {
$scope.list1 = TestiFactory.list();
$scope.$watch('list1', function(list1) {
$scope.list1_length = list1.length;
});
$scope.list1_add = function (d) {
TestiFactory.add_to_arr(d);
$scope.param = '';
};
});
TestiApp.controller('TestController2', function($scope, TestiFactory) {
$scope.list2 = TestiFactory.list();
$scope.$watch('list2', function(list2) {
$scope.list2_length = list2.length;
});
});