AngularJS checkbox avoid counting when uncheck checkBox - angularjs

Here is my running code in Plunker
I got a bug: When I uncheck the answer, I do not want to count how many times we select this answer? We will only count the number when we check the answer. For example, I check "Yes", I uncheck "Yes", I check "Yes" again, I will only show "Yes" was selected 2 times, instead of 3 times.
I read some posts about this issue, but cannot make it work by using checked property?
<input type="checkbox" ng-change="answerSelected(ans)" ng-model="checkAnswer">{{ans.answer}}

change the ng-model to object property like ng-model="ans.checkAnswer"
<input type="checkbox" ng-change="answerSelected(ans)" ng-model="ans.checkAnswer">{{ans.answer}}
Then change the function like this
$scope.answerSelected = function(checkAnswer) {
if (checkAnswer.checkAnswer) {
checkAnswer.count++;
}
$scope.answerBoxSelected = true;
};
Demo

Just add a check like this,
if (checkAnswer) {
ans.count++;
$scope.answerBoxSelected = true;
}
DEMO
// Code goes here
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
$scope.questions = [{
id: 1,
question: "Do you like Foo?",
answers: [{
answer: "Yes",
count: 0,
id: 1,
question_id: 1
}, {
answer: "No",
count: 0,
id: 2,
question_id: 1
}]
},
{
id: 2,
question: "Do you like Bar?",
answers: [{
answer: "Yes",
count: 0,
id: 1,
question_id: 2
}, {
answer: "No",
count: 0,
id: 2,
question_id: 2
}]
}
]
$scope.question_index = 0;
$scope.answerSelected = function(checkAnswer,ans) {
if (checkAnswer) {
ans.count++;
}
$scope.answerBoxSelected = true;
};
$scope.nextQuestion = function() {
$scope.question_index++;
$scope.answerBoxSelected = false;
};
});
<!DOCTYPE html>
<html>
<head>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<div class="form-group" ng-if="question_index < questions.length">
<div ng-repeat="item in questions">
<div ng-if="question_index == $index">
<h2>{{item.question}}</h2>
<div ng-repeat="ans in item.answers">
<input type="checkbox" ng-change="answerSelected(checkAnswer,ans)" ng-model="checkAnswer">{{ans.answer}}
<br>
</div>
<div ng-if="answerBoxSelected" class="alert alert-warning">
<h3>Answer Selection Summary</h3>
<div ng-repeat="ans in item.answers">
<p>
"{{ans.answer}}" Has been selected {{ans.count}}
<span ng-if="ans.count == 0">time</span>
<span ng-if="ans.count > 0">times</span>
<p>
</div>
</div>
<button class="btn btn-info btn-lg" ng-if="answerBoxSelected && question_index < questions.length - 1" ng-click="nextQuestion()">Next Question > </button>
</div>
</div>
</div>
<div class="alert alert-success" ng-if="question_index == questions.length - 1 && answerBoxSelected">
Congratulations! You answered all the questions. Good job!
</div>
</div>
<script src="script.js">
</script>
</body>
</html>

One workaround is to pass the element itself to the answerSelected method, and check its checkAnswer property. We will only increment the count if this property is true.
<input type="checkbox" ng-change="answerSelected(ans, this)" ng-model="checkAnswer">{{ans.answer}}
$scope.answerSelected = function(checkAnswer, elem) {
if (elem.checkAnswer === true) {
checkAnswer.count++;
}
$scope.answerBoxSelected = true;
};

You can call the function conditionally only when the checbox is checked:
<input type="checkbox" ng-change="!checkAnswer || answerSelected(ans)" ng-model="checkAnswer">{{ans.answer}}
When the checkbox is checked, checkAnswer will evaluate to true, and the function will be called.
When the checkbox is unchecked, checkAnswer will evaluate to false, and the function will not be called.
Here's a plunker

Related

is data a reserved keyword in angularjs?

The code below doesn't work if I use data in lst, it works, if I replace data with x, so is data a reserved keyword in AngularJS and why?
<script src="http://ajadata.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body ng-app='app1'>
<div id='Grocery' ng-controller='Grocery'>
<h3>Grocery List</h3>
<div ng-repeat='data in lst'>
<h4>{{data.item}}</h4>
</div>
<br>
<p> enter item:
<input type="text" ng-model='addItem' />
</p>
<button ng-click='addTolist(addItem)'>Add to list</button>
<button ng-click='addTolist(addItem)'>Add to list</button>
<h2>{{NoItemError}}</h2>
</div>
<!-- End of Grocery -->
<script>
var app1 = angular.module('app1', []);
app1.controller('Grocery', function($scope) {
$scope.lst = [{
item: 'banana',
needed: false
},
{
item: 'apple',
needed: false
},
{
item: 'milk',
needed: false
},
{
item: 'tomato',
needed: false
},
{
item: 'juice',
needed: false
}
]
$scope.addTolist = function(addItem) {
if (!(addItem === undefined || addItem === '')) {
$scope.lst.push({
item: addItem,
needed: false
});
$scope.NoItemError = '';
} else {
$scope.NoItemError = 'Please enter an item';
}
}
});
</script>
</body>
While replacing text with another, you broke your CDN URL for the AngularJS script.
It became http://ajadata.googleapis.com
Change it to http://ajax.googleapis.com
Here is a full script:
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
And here is a working example of your code:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body ng-app='app1'>
<div id='Grocery' ng-controller='Grocery'>
<h3>Grocery List</h3>
<div ng-repeat='data in lst'>
<h4>{{data.item}}</h4>
</div>
<br>
<p> enter item:
<input type="text" ng-model='addItem' />
</p>
<button ng-click='addTolist(addItem)'>Add to list</button>
<button ng-click='addTolist(addItem)'>Add to list</button>
<h2>{{NoItemError}}</h2>
</div>
<!-- End of Grocery -->
<script>
var app1 = angular.module('app1', []);
app1.controller('Grocery', function($scope) {
$scope.lst = [{
item: 'banana',
needed: false
},
{
item: 'apple',
needed: false
},
{
item: 'milk',
needed: false
},
{
item: 'tomato',
needed: false
},
{
item: 'juice',
needed: false
}
]
$scope.addTolist = function(addItem) {
if (!(addItem === undefined || addItem === '')) {
$scope.lst.push({
item: addItem,
needed: false
});
$scope.NoItemError = '';
} else {
$scope.NoItemError = 'Please enter an item';
}
}
});
</script>
</body>
Most reserved words in AngularJS start with $, for example $index or $id, etc.

Count number from value ng-repeat

Is it possible to add a numbers output from ng-repeat ? I have this output from ng-repeat
1
2
1
I want to add that number so it will become 4. this is the code
<p data-ng-repeat="ticketA in cart.sw_tickets" ng-if="ticketA.ProductId == tickets.ProductId && ticketA.PricingTypeId == 1" ng-init="adultTOT = ticketA.total_ticket">
{{adultTOT}}
</p>
I'm really new in Angular and i'm not really sure I can do trick somewhere inside ng-repeat.
hope from anyone help! thanks
angular.module("app", [])
.controller("SampleController", function($scope) {
var ctrl = this;
ctrl.adultTOT = 0;
ctrl.sw_tickets = [{
Id: 1,
total_ticket: 1
}, {
Id: 2,
total_ticket: 2
}, {
Id: 3,
total_ticket: 1
}]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-app="app">
<div data-ng-controller="SampleController as ctrl">
<p data-ng-repeat="ticketA in ctrl.sw_tickets" ng-init="ctrl.adultTOT= ctrl.adultTOT+ticketA.total_ticket">
{{ctrl.adultTOT}}
</p>
</div>
</div>

Angularjs filters OR conditions

I am trying to create a filter where I can conditionally select multiple attributes of the same variable. For example
var list = [ {id: 1, state: 'U'}, {id: 2, state: 'P'} ]
<div ng-repeat="item in list| filter:{state:'U'}>
This would result in id 1 only being displayed.
<div ng-repeat="item in list| filter:{state:'P'}>
This would result in id 2 only being displayed.
How can I create a filter to display all id's that have state:'P' OR state:'A'
Neither of the below work:
<div ng-repeat="item in list| filter:{state:'P' || 'A'}>
<div ng-repeat="item in list| filter:({state:'P'} || {state:'A'})>
Hope this below code snippet might help you ! Run it :)
var app = angular.module('app', []);
app.controller('Ctrl', function($scope) {
$scope.list = [{
id: 1,
state: 'U'
}, {
id: 2,
state: 'P'
}, {
id: 3,
state: 'A'
}];
$scope.state = function(item) {
return (item.state == 'P' || item.state == 'A');
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="Ctrl">
<div ng-repeat="item in list | filter:state">
{{item.id}}
</div>
</div>
Why do have so much confusion. Use ng-if just like your normal if statement like this
var list = [ {id: 1, state: 'U'}, {id: 2, state: 'P'},{id: 1, state: 'A'} ]
<div ng-repeat="item in list">
<div ng-if="item.state == 'A' || item.state== 'P'">
{{item.id}}
</div>
</div>
Implementation is also as below
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.list = [{id: 1,state: 'U'}, {id: 2,state: 'P'}, {id: 3, state: 'A'}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="item in list">
<div ng-if="item.state == 'A' || item.state== 'P'">
{{item.id}}
</div>
</div>
</div>

How to get dynamic ng-model from ng-repeat in javascript?

I'm developoing a web app and stuck here:
Part of the HTML:
<div class="input-group">
<select name="select" class="form-control input-group-select" ng-options="key as key for (key , value) in pos" ng-model="word.pos" ng-change="addPos()">
<option value="">Choose a POS</option>
</select>
<span class="sort"><i class="fa fa-sort"></i></span>
</div>
<ul class="listGroup" ng-show="_pos.length > 0">
<li class="list" ng-repeat="item in _pos track by $index">
<span>
{{item.pos}}
<span class="btn btn-danger btn-xs" ng-click="delPos($index)">
<span class="fa fa-close"></span>
</span>
</span>
<!-- I wanna add the input which can add more list item to the item.pos-->
<div class="input-group">
<a class="input-group-addon add" ng-class=" word.newWordExp ? 'active' : ''" ng-click="addItemOne()"><span class="fa fa-plus"></span></a>
<input type="text" class="form-control exp" autocomplete="off" placeholder="Add explanation" ng-model="word.newWordExp" ng-enter="addExpToPos()">
{{word.newWordExp}}
</div>
</li>
</ul>
Part of the js:
$scope._pos = [];
$scope.addPos = function () {
console.log("You selected something!");
if ($scope.word.pos) {
$scope._pos.push({
pos : $scope.word.pos
});
}
console.dir($scope._pos);
//console.dir($scope.word.newWordExp[posItem]);
};
$scope.delPos = function ($index) {
console.log("You deleted a POS");
$scope._pos.splice($index, 1);
console.dir($scope._pos);
};
$scope.addItemOne = function (index) {
//$scope.itemOne = $scope.newWordExp;
if ($scope.word.newWordExp) {
console.log("TRUE");
$scope._newWordExp.push({
content: $scope.word.newWordExp
});
console.dir($scope._newWordExp);
$scope.word.newWordExp = '';
} else {
console.log("FALSE");
}
};
$scope.deleteItemOne = function ($index) {
$scope._newWordExp.splice($index, 1);
};
So, what am I wannt to do is select one option and append the value to $scope._pos, then display as a list with all of my selection.
And in every list item, add an input filed and add sub list to the $scope._pos value.
n.
explanation 1
explanation 2
explanation 3
adv.
explanation 1
explanation 2
So I don't know how to generate dynamic ng-model and use the value in javascript.
Normaly should like ng-model="word.newExplanation[item]" in HTML, but in javascript, $scope.word.newExplanation[item] said "item is not defined".
can any one help?
If I've understood it correclty you could do it like this:
Store your lists in an array of object this.lists.
The first object in the explanation array is initialized with empty strings so ng-repeat will render the first explanation form.
Then loop over it with ng-repeat. There you can also add dynamically the adding form for your explanation items.
You can also create append/delete/edit buttons inside the nested ng-repeat of your explanation array. Append & delete is already added in the demo.
Please find the demo below or in this jsfiddle.
angular.module('demoApp', [])
.controller('appController', AppController);
function AppController($filter) {
var vm = this,
explainTmpl = {
name: '',
text: ''
},
findInList = function (explain) {
return $filter('filter')(vm.lists, {
explanations: explain
})[0];
};
this.options = [{
name: 'option1',
value: 0
}, {
name: 'option2',
value: 1
}, {
name: 'option3',
value: 2
}];
this.lists = [];
this.selectedOption = this.options[0];
this.addList = function (name, option) {
var list = $filter('filter')(vm.lists, {
name: name
}); // is it in list?
console.log(name, option, list, list.length == 0);
//vm.lists
if (!list.length) {
vm.lists.push({
name: name,
option: option,
explanations: [angular.copy(explainTmpl)]
});
}
};
this.append = function (explain) {
console.log(explain, $filter('filter')(vm.lists, {
explanations: explain
}));
var currentList = findInList(explain);
currentList.explanations.push(angular.copy(explainTmpl));
}
this.delete = function (explain) {
console.log(explain);
var currentList = findInList(explain),
index = currentList.explanations.indexOf(explain);
if (index == 0 && currentList.explanations.length == 1) {
// show alert later, can't delete first element if size == 1
return;
}
currentList.explanations.splice(index, 1);
};
}
AppController.$inject = ['$filter'];
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp" ng-controller="appController as ctrl">
<select ng-model="ctrl.selectedOption" ng-options="option.name for option in ctrl.options"></select>
<input ng-model="ctrl.listName" placeholder="add list name" />
<button class="btn btn-default" title="add list" ng-click="ctrl.addList(ctrl.listName, ctrl.selectedOption)"><i class="fa fa-plus"></i>
</button>
<div class="list-group">Debug output - current lists:<pre>{{ctrl.lists|json:2}}</pre>
<div class="list-group-item" ng-repeat="list in ctrl.lists">
<h2>Explanations of list - {{list.name}}</h2>
<h3>Selected option is: {{ctrl.selectedOption}}</h3>
<div class="list-group" ng-repeat="explain in list.explanations">
<div class="list-group-item">
<p class="alert" ng-if="!explain.title">No explanation here yet.</p>
<div class="well" ng-if="explain.title || explain.text">
<h4>
{{explain.title}}
</h4>
<p>{{explain.text}}</p>
</div>Title:
<input ng-model="explain.title" placeholder="add title" />Text:
<input ng-model="explain.text" placeholder="enter text" />
<button class="btn btn-primary" ng-click="ctrl.append(explain)">Append</button>
<button class="btn btn-primary" ng-click="ctrl.delete(explain)">Delete</button>
</div>
</div>
</div>
</div>
</div>

binding data in ng-repeat angularjs

*This is my html file where i want to repeat chapters which is a array that looks like
My code gives binds the selected checked boxes only (Index values) to true. But i need the entire list of chapters and their i.d's to be retrieved on submit.
Cannot figure out how to iterate it on nested loops *
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<span ng-repeat="chapter in chapters">
<label><input type="checkbox" name="checkbox" value="{{chapter}} ng-model="escConfigForm.chapters[$index]" >{{chapter.name}}</label><br>
</span>
<input type="submit" id="save" value="Save" />
$scope.chapters = chapterService.getChapters($scope.isbn);
$scope.submit = function(escConfigForm) {
var postData = {
content_items: JSON.stringify({
"#context" : [],
"#graph" : [ {
"#type" : "ContentItemPlacement",
"placementOf" : {
"#type" : "LtiLink",
"text" : escConfigForm.examName,
"mediaType" : "application/vnd.ims.lti.v1.launch+json",
"title" : "Exam Study Center",
"custom" : {
"dueDate" : escConfigForm.examDueDate,
"targetScore" : escConfigForm.examTargetScore,
"chapters" : escConfigForm.chapters
},
"activityType" : "other",
"activityRefId" : $scope.escId
}
} ]
}),
data: $scope.data
};
postForm($scope.postUrl, postData);
var configData = {
"activityRefId" : $scope.escId,
"dueDate" : escConfigForm.examDueDate,
"targetScore" : escConfigForm.examTargetScore,
"chapters" : escConfigForm.chapters
};
console.log($scope.chapters);
JSON file:
[{"name":"Chapter 1: Negative Messages","id":"832115"},{"name":"Chapter 2: Physics","id":"832115"},...]
I would recommend maintaining a list of the selected objects in the controller.
using this post as referenece: How do I bind to list of checkbox values with AngularJS?
I created this fiddle: http://jsfiddle.net/ruwk5r0v/7/
<div ng-app="formExample">
<div ng-controller="ExampleController"> <span ng-repeat="chapter in chapters" ng-click="checkboxChange($index)" ng-checked="selection.indexOf($scope.chapters[$index]) > -1">
<input type="checkbox" name="checkbox" value="{{$index}}" />
{{chapter.name}}
<br>
</span>
<br>
<input type="submit" ng-click="submitForm()" id="save" value="Save" />
<div> <span ng-repeat="chapter in selection">
<span>
{{chapter.name}}
</span>
<br>
</div>
and the js:
angular.module('formExample', []).controller('ExampleController', ['$scope', function ($scope) {
$scope.chapters = [{
"name": "Chapter 1: Negative Messages",
"id": "832115"
}, {
"name": "Chapter 2: Physics",
"id": "832115"
}];
$scope.submitForm = function () {
console.log(selection);
}
$scope.selection = []
$scope.checkboxChange = function(index){
var chapter = $scope.chapters[index];
var idx = $scope.selection.indexOf(chapter);
if (idx > -1){
$scope.selection.splice(idx, 1);
} else {
$scope.selection.push(chapter);
}
}
}]);
here you can very easily implement your submit function, just use the new selection object.
This really should be moved into a directive, but don't have time to write that right now :P
Here I created a controller for the snippet, and added some data to $scope.chapters object, and it is displaying correctly. The values disappear when selected, but that is another issue.
angular.module('myApp', [])
.controller('myCtrl', ['$scope',
function($scope) {
$scope.chapters = [{
name: 'Chapter 1: Negative Messages',
id: "1",
isSelected: false
}, {
name: 'Chapter 2: Physics',
id: "2",
isSelected: false
}];
$scope.submitItems = function(chapters) {
alert(JSON.stringify(chapters));
}
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myCtrl">
<span ng-repeat="chapter in chapters">
<input type="checkbox" name="checkbox" value="{{chapter}}"
ng-model="chapter.isSelected" />
{{chapter.name}}
</span>
<br>
<form ng-submit="submitItems(chapters)">
<input ng-model="chapters" type="submit" id="save" value="Save" />
</form>
</div>
</div>
Edit: Updated the code to reflect the OP needs.

Resources