Why is my angular script running an infinite loop? - javascript

What I am trying to do is check three boxes via event click upon page load with the use of for loop. What happens is it runs an infinite loop then the page hangs. Here is the code:
<!DOCTYPE html>
<html >
<head>
<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
</head>
<body ng-app="ngToggle">
<div ng-controller="AppCtrl">
<input type="checkbox" ng-model="dean" ng-click="btnChange($event, values, 1)" id="check-1" name="one" class="here" >
<input type="checkbox" ng-model="armada" ng-click="btnChange($event, values, 2)" id="check-2" name="one" class="here" >
<input type="checkbox" ng-model="armada" ng-click="btnChange($event, values, 2)" id="check-3" name="one" class="here" >
<!--<p ng-repeat="btn in btns">-->
<!-- <input type="checkbox" ng-model="btn.bool" class="here" > {{ btn.value }}-->
<!--</p>-->
{{btn }}
{{values }}
</div>
<script type="text/javascript">
angular.module('ngToggle', [])
.controller('AppCtrl',['$scope', '$timeout', function($scope, $timeout){
$scope.btns = [{}, {}, {}];
$scope.values = [];
$scope.btnChange = function(event, model, val){
_this = angular.element(event.target);
x = _this.prop("checked");
if(x){
model.push(val);
}else{
index = model.indexOf(val);
model.splice(index, 1);
}
};
ids = [1, 2, 3];
$timeout(function() {
for(x=0;x<ids.length;x++){
angular.element("#check-"+ids[x]).trigger("click");
}
}, 1000);
}]);
</script>
</body>
</html>
Here is the plunker: http://plnkr.co/edit/7DpCvkKLlKhRc3YwFTq0?p=info
PS
If you comment or removed the angular.element trigger this will not occur. If someone can provide a code that will trigger the click events on the checkboxes via loop. THEN IT WILL BE GREAT

You can do it the Angular way by setting default values to your checkboxes:
As you use ng-model, in your controller, just set dean and armada to true.
UPDATE:
I've nevertheless debugged your JS. Here is a plunker of your function working. I've used y in the loop (x was already defined) and change a bit the condition of looping.
Anyway, I would recommend you to do with Angular... :-)

Related

How to pass index value to controller from ng-repeat in Angular

I am dynamically creating divs, while clicking a button which contains some radio inputs. In the controller I have an array for the divs population which initially has a length of 1.
'use strict';
angular.module('load').controller(
'commodityController',
function($scope, $http, $state, $stateParams) {
$scope.parentload = $scope.$parent.load;
$scope.addMoreCommodities = function() {
$scope.parentload.loadCommodities.push({
'isHazmat' : false,
'dimension' : 'IN'
});
}
$scope.parentload.loadCommodities = []; // emtry array
$scope.addMoreCommodities(); // Here initialize the array
$scope.changeHazmat = function(booleans, val) {
console.log("booleans " + booleans);
console.log("isactive " + val);
$scope.parentload.loadCommodities[val].isHazmat = booleans;
};
});
Using following html, while loading the page div populated well,
<div class="form-right-card disabledInput" ng-init="showname==true" id="commodityContent">
<form name="commodityAttForm">
<div ng-repeat="loadCommodities in load.loadCommodities">
<div class="form-group33"> {{$index}} // here value prints correctly
<label class="form-label">Hazmat</label>
<input type="radio" class="form-btn-inactive" ng-click="changeHazmat('true',$index)" id="yes" name="hazmat" />
<label class="plsLabel" for="yes">Yes</label>
<input type="radio" class="form-btn-inactive" ng-click="changeHazmat('false',$index)" id="no" name="hazmat" />
<label class="plsLabel" for="no">No</label>
</div>
</div>
</form>
</div>
<button class="form-btn-link" ng-click="addMoreCommodities()">+ Add Commodity</button>
I am able to generate the div with all the inputs when clicking on the button. Problem is, I am sending the $index to controller on ng-click of the radio buttons, while clicking on the radio buttons, I am calling the function changeHazmat('true',$index) here the index is always 0, even when I have an array with a length greater than 1.
$scope.changeHazmat = function(selected, val) {
console.log("val" + val);
$scope.parentload.loadCommodities[val].isHazmat = selected;
Log is always printing the index as 0.
Can someone help me here, what am I doing wrong?
You are correctly passing the $index the controller and the code should work.
However I would recommend to use ngModel with ngValue directive.
<input type="radio" ng-model="loadCommodities.isHazmat" ng-value=true name="hazmat" />
(function(angular) {
'use strict';
angular.module('myApp', [])
.controller('Controller', ['$scope', function($scope, ) {
$scope.parentload = {
loadCommodities: []
};
$scope.addMoreCommodities = function() {
$scope.parentload.loadCommodities.push({
'isHazmat': false,
'dimension': 'IN'
});
}
$scope.addMoreCommodities();
$scope.changeHazmat = function(booleans, val) {
$scope.parentload.loadCommodities[val].isHazmat = booleans;
};
}]);
})(window.angular);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="Controller">
<div ng-repeat="loadCommodities in parentload.loadCommodities">
<div class="form-group33">
<label class="form-label">Hazmat</label>
<input type="radio" ng-model="loadCommodities.isHazmat" ng-value=true name="hazmat" />
<label class="plsLabel" for="yes">Yes</label>
<input type="radio" ng-model="loadCommodities.isHazmat" ng-value=false name="hazmat" />
<label class="plsLabel" for="no">No</label>
</div>
<p>{{parentload.loadCommodities}}</p>
</div>
</div>
</div>
I'm wondering if the problem is you're assigning the same "id" ('yes' and 'no') to multiple divs (ie inside the loop). It might be the reason the $index isn't working for you. If you remove the id's for the time being and re-try, I'm thinking the problem goes away.

How to convert AngularJS scope object into simple JS array?

How to convert AngularJS scope object into simple JS array?
This function checks if any checkbox is checked and adds corresponding value to an object.
Now I want to transfer the object values to an array and alert it after press the button. But the result is undefined, why?
var formApp = angular.module('formApp', [])
.controller('formController', function($scope) {
// we will store our form data in this object
$scope.formData = {};
});
var array = Object.keys(formData).map(function(k) { return obj[k] });
function test(){
alert(array);
}
<-- index.html -->
<!DOCTYPE html>
<html>
<head>
<!-- CSS -->
<!-- load up bootstrap and add some spacing -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<style>
body { padding-top:50px; }
form { margin-bottom:50px; }
</style>
<!-- JS -->
<!-- load up angular and our custom script -->
<script src="http://code.angularjs.org/1.2.13/angular.js"></script>
<script src="app.js"></script>
</head>
<!-- apply our angular app and controller -->
<body ng-app="formApp" ng-controller="formController">
<div class="col-xs-12 col-sm-10 col-sm-offset-1">
<h2>Angular Checkboxes </h2>
...
<!-- MULTIPLE CHECKBOXES -->
<label>Favorite Colors</label>
<div class="form-group">
<label class="checkbox-inline">
<input type="checkbox" name="favoriteColors" ng-model="formData.favoriteColors.red"> Red
</label><br>
<label class="checkbox-inline">
<input type="checkbox" name="favoriteColors" ng-model="formData.favoriteColors.blue"> Blue
</label> <br>
<label class="checkbox-inline">
<input type="checkbox" name="favoriteColors" ng-model="formData.favoriteColors.green"> Green
</label>
</div>
...
<!-- SHOW OFF OUR FORMDATA OBJECT -->
<h2>formData_object_is_not_empty-test</h2>
<pre>
{{formData}}
</pre>
<button onclick="test()">Click me</button>
</div>
</body>
</html>
Try this:
var formApp = angular.module('formApp', [])
.controller('formController', function($scope) {
// we will store our form data in this object
$scope.formData = {};
var array = Object.keys($scope.formData).map(function(k) { return obj[k] });
// wait for the formData to change and then alert
setTimeout(function() {
alert(array);
}, 2000);
});
Angular is made in a way that you are not allowed to access the scope variables outside the controller.
If you want to have the array as debug information, use a browser plugin like AngularJS Batarang or use console.log(array) instead of alert(array) or try to save array in a global variable with document.array = array, so you can access it in the browser console.

Improving AngularJS view update with ngshow

Right now I have a view that uses ng-show to show a select DOM object when certain criteria are met and ng-show for a input DOM for all other cases. When I do this and switch between the two cases, input box takes longer to disappear than when the select appears. The delay is pretty noticeable so I want to improve it so that there's very little delay between the two DOM changes.
Is there any way to do this?
<div>
<input ng-show="field && (type == 'search' || fieldBucket[field].moreBuckets)"
type="text" ng-model="value">
<select class="facet-value"
ng-show="field && type == 'filter' && !fieldBucket[field].moreBuckets"
ng-model="value"
ng-options="fieldBucket[field].buckets">
</select>
</div>
I don't think it is anyway related to ng-show or hide it might depend on some data which you are expecting from server as response.
I have created a simple demo for you that in basic ng-show/hide there isn't any leg if their value is set at same time.
<!doctype html>
<html ng-app>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
</head>
<body>
<div class="wrapper" ng-app="test">
<div class="phone" ng-controller="TestCtrl" ng-init="type = 'search'">
search
filter
<div >
<input ng-show="type == 'search'"
type="text" ng-model="value">
<select class="facet-value"
ng-show="type == 'filter'"
ng-model="value"
ng-options="obj.name for obj in list">
</select>
</div>
</div>
</body>
<script type="text/javascript">
var app = angular.module('test', []);
function TestCtrl($scope) {
$scope.list = [{name : 'one'}, {name : 'two'}];
}
</script>
</html>

Checkboxes binding in AngualrJS

I have two checkboxes , one with Data Binding and other one is without Data Binding.As you can see in the code below.
<html ng-app="notesApp">
<head><title>Notes App</title></head>
<body ng-controller="MainCtrl as ctrl">
<div>
<h2>What are your favorite sports?</h2>
<div ng-repeat="sport in ctrl.sports">
<label ng-bind="sport.label"></label>
<div>
With Binding:
<input type="checkbox" data-ng-true-value="YES" data-ng-false-value="NO" >
</div>
<div>
Using ng-checked:
<input type="checkbox" data-ng-checked='sport.selected === "YES"'>
</div>
<div>
Current state : {{sport.selected}}
</div>
</div>
</div>
<script type="text/javascript" src="angular.js"></script>
<script type="text/javascript">
angular.module('notesApp',[])
.controller('MainCtrl',[function(){
var self = this;
self.sports = [
{label:'Basketball',selected: 'YES'},
{label:'Cricket',selected:'NO'},
{label:'Soccer',selected:'NO'},
{label:'Swimming',selected:'YES'}
];
}]);
</script>
</body>
</html>
When i click on the checkbox of 'with data binding', it should bind and reflect the value in current state label.But it is not happening.Why ?.Can someone help Please .
2 problems I found with your code:
You forgot ng-model
You should specify a constant for ng-true-value and ng-false-value, by specifying YES angular will look for a YES property on the scope, write 'YES' instead
Updated working plnkr:
http://plnkr.co/edit/rnYRUpIICC7HAKdKXf3i?p=preview
<html ng-app="notesApp">
<head>
<title>Notes App</title>
</head>
<body ng-controller="MainCtrl as ctrl">
<div>
<h2>What are your favorite sports?</h2>
<div ng-repeat="sport in ctrl.sports">
<label ng-bind="sport.label"></label>
<div>
With Binding:
<input type="checkbox" ng-model="sport.selected" data-ng-true-value="'YES'" data-ng-false-value="'NO'" />
</div>
<div>
Using ng-checked:
<input type="checkbox" data-ng-checked="sport.selected === 'YES'" />
</div>
<div>
Current state : {{sport.selected}}
</div>
</div>
</div>
<script src="https://code.angularjs.org/1.4.3/angular.js"></script>
<script type="text/javascript">
angular.module('notesApp',[])
.controller('MainCtrl',[function(){
var self = this;
self.sports = [
{label:'Basketball',selected: 'YES'},
{label:'Cricket',selected:'NO'},
{label:'Soccer',selected:'NO'},
{label:'Swimming',selected:'YES'}
];
}]);
</script>
</body>
</html>
EDIT: As #g00glen00b mentioned, before angular 1.3 ng-true-value accepted only constant values, so in case you're not using angular 1.3 or later you don't have to wrap YES in quotes.
The data-ng-true-value and data-ng-false-value are used when you're using the input[checkbox] directive, but they do require ngModel, as you can see in the docs (note that ng-model is not in square brackets).
Without providing the model, AngularJS has no way to know where to apply the true/false value to. Adding data-ng-model does seem to work, as you can see in the following fiddle.
<input type="checkbox" ng-model="sport.selected"
data-ng-true-value="YES"
data-ng-false-value="NO" />
Also, please note that when using AngularJS 1.3 or higher, the values of ng-true-value and ng-false-value should be an expression rather than a constant value. Which means that for AngularJS 1.3 and higher you'll have to replace it by ng-true-value="'YES'", for example:
<input type="checkbox" ng-model="sport.selected"
data-ng-true-value="'YES'"
data-ng-false-value="'NO'" />
You are not applying "data-ng-model" attribute to the the checkbox. Please replace your "With binding" check box code from below:
<input type="checkbox" data-ng-model="sport.selected" data-ng-true-value="YES" data-ng-false-value="NO" >

how to set ng-model Value via ng-init or value tag

I want to set ng-model Value. I tried with ng-init and value tag.
My code:
Init
{{formObject.consultantId}} // value prints
<input type="hidden" data-ng-model="formObject.consultant.id" data-ng-init="formObject.consultant.id=formObject.consultantId">
{{formObject.consultant.id}} // no data Prints
Value
{{formObject.consultantId}} // value prints
<input type="hidden" data-ng-model="formObject.consultant.id" value="{{formObject.consultantId}}">
{{formObject.consultant.id}} // no data Prints
This works for me
<input type="hidden" data-ng-model="formObject.consultant.id" data-ng-init="formObject.consultant.id='test'">
{{formObject.consultant.id}} // prints as test
Whats wrong in my code ? How to initialize this Value to Model ?
EDIT
I found my issue. This code works for me in Normal Html Form.
But above codes are in ModelForm(directive).
you should change {{formObject.consultantShare.consultant.id}} to {{formObject.consultant.id}} (to OP's edit, now removed)
Take a look at this
var app = angular.module('myApp', []);
app.controller('Controller', function ($scope) {
$scope.formObject = {};
$scope.formObject.consultant = {};
$scope.formObject.consultantId = "254";
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='myApp' ng-controller="Controller">{{formObject.consultantId}} // value prints
<input type="hidden" data-ng-model="formObject.consultant.id" data-ng-init="formObject.consultant.id=formObject.consultantId" />{{formObject.consultant.id}}
<br/>{{formObject.consultantId}} // value prints
<input type="hidden" data-ng-model="formObject.consultant.id" value="{{formObject.consultantId}}"/>{{formObject.consultant.id}}
</div>
Can you share your controller to see how formObject is initialized. Meanwhile I have added
var myapp= angular.module('myForm',[]);
(function(){
angular.module('myForm').controller('formController',[formController]);
function formController(){
var vm = this;
vm.formObject = {consultantId:10,consultant:{consultantId:''}};
}
})();
<!DOCTYPE html>
<html ng-app="myForm">
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div ng-controller="formController as vm">
<span>formObject.consultantId:{{vm.formObject.consultantId}}</span>
<input type="hidden" ng-model="vm.formObject.consultantId" ng-init="vm.formObject.consultant.consultantId=vm.formObject.consultantId"
</br>
<span>formObject.consultant.consultantId: {{vm.formObject.consultant.consultantId}}</span>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="formController.js"></script>
</body>
</html>
my solution at : http://plnkr.co/edit/q4d8ZVXz3ki02EjkNZ0n

Categories

Resources