I have a small quiz application that I am converting into angular. It displays a question, and 4 possible answers that you select through radio buttons. You can move to the next question or back to the original and your selection is noted.
I am having problems reselecting the radio button when I want to go back to the question. The attribute for the button states that I have changed it to true, but it is not indicated. Only when I go back to the first question, and try to go back a second time does it update correctly. I am assuming that since it can't back back any further and can run again that there is some updating to the buttons going on and that is what is doing it.
The extra space appears to be a formatting issue with stack overflow, it isn't in my actual code base. I have since remove it.
Any help would be greatly appreciated. The code is rough right now as I just have everything thrown into the controller. Some structure will come later.
HTML
<div ng-controller="mainController" class="col-md-5 col-md-offset-5">
<div>
{{quizQuestions}}
</div>
<div ng-repeat="answers in quizAnswers">
<label>{{answers}}</label>
<input class="rad" type="radio" name="answer" ng-click="markAnswer($index)">
</div>
<div>
<label>Change the question</label>
<input type="button" ng-click="decrease()" value="Back">
<input type="button" ng-click="increase()" value="Next">
</div>
</div>
Angular
$scope.adder = 0;
$scope.answer = [];
$scope.markAnswer = function(index) {
$scope.answer.splice($scope.adder,1,index);
};
$scope.display = function(number) {
$scope.quizQuestions = allQuestions[number].question;
$scope.quizAnswers = allQuestions[number].choices;
};
$scope.decrease = function() {
if($scope.adder === 0) {
} else {
$scope.adder -= 1;
$scope.display($scope.adder);
}
document.getElementsByClassName('rad') [$scope.answer[$scope.adder]].checked = true;
};
$scope.display($scope.adder);
There is a syntax error in your "rad" class ng-click
<input class="rad" type="radio" name="answer" ng- click="markAnswer($index)">
you need to take out the space between ng- and click
For what your doing, you should look into the ng-model directive. Mind if take a look at your markAnswer() function?
Related
I have a Quizz module developed in Angular2, so merely some questions with proposed answers and you have to check only one answer , I know radio buttons can handle the situation but i want it to be checkboxes with a radio button behavior, the issue is that i did a part of the job but since it is more complicated within an *ngFor loop , once i check a B-Question answer the A-Question checked answer will be unchecked and so on.
Here is my HTML :
<div *ngFor="#qt of listQuestion"><h3 class="uk-accordion-title" >{{qt.wordingQ}}</h3>
<div class="uk-accordion-content">
<input type="checkbox" class="cb" id="0" [(ngModel)]="qt.chp[0]" onchange="cbChange(this)" />
<label for="0" class="inline-label" > <b>{{qt.lpo[0]}}</b></label><br><br>
<input type="checkbox" class="cb" id="1" [(ngModel)]="qt.chp[1]" onchange="cbChange(this)" />
<label for="1" class="inline-label"><b>{{qt.lpo[1]}}</b></label><br><br>
<input type="checkbox" class="cb" id="2" [(ngModel)]="qt.chp[2]" onchange="cbChange(this)"/>
<label for="2" class="inline-label"> <b>{{qt.lpo[2]}}</b></label><br><br>
<input type="checkbox" class="cb" id="3" [(ngModel)]="qt.chp[3]" onchange="cbChange(this)"/>
<label for="3" class="inline-label"><b>{{qt.lpo[3]}}</b></label>
</div></div>
And here is the Script making the solo-checking way :
<script>
function cbChange(obj) {
var cbs = document.getElementsByClassName("cb");
for (var i = 0; i < cbs.length; i++) {
cbs[i].checked = false;
}
obj.checked = true;
}
</script>
As you can see it is an *ngFor loop to load a list of questions ; every question has a list of propositions (lpo[i]) and the [(ngModel)]="qt.chp[i]" is for taking the status of every proposition (checked proposition) , I think i have to refer every onchange function to every unique ngModel (as it is in indexing) but i do not know how. Any help Please ?
(Here is a real image of the situation)
In your situation, because only one answer should be selected for each question, I suggest you to not use boolean field in answer-level to indicate selection. Rather, you should store the selected answer in question-level. Something like this:
class Question {
wording: string;
answers: string[];
selectedAnswer: string;
selectAnswer(ans: string) {
this.selectedAnswer = ans;
}
}
In future, you can easily change the selectedAnswer property and selectAnswer function implementation to cater multiple selections if needed.
The question template then needs to be modified a little bit to accommodate the change:
<div *ngFor="let question of questions">
<p>{{question.wording}}</p>
<div *ngFor="let answer of question.answers; let aIndex = index">
<input type="checkbox" class="cb" id="{{aIndex}}" [ngModel]="answer === question.selectedAnswer" (ngModelChange)="question.selectAnswer(answer)" />
<label for="{{aIndex}}" class="inline-label" > <b>{{answer}}</b></label><br><br>
</div>
</div>
Here is the runnable plunker:
http://plnkr.co/edit/xMTtFp31rU2ZqCtV8JO1?p=preview
I have a form which has 10 checkboxes. By default angular js triggers on individual checkbox. I want to grab all selected check box values on submit action only. Here is my code...
<form name="thisform" novalidate data-ng-submit="booking()">
<div ng-repeat="item in items" class="standard" flex="50">
<label>
<input type="checkbox" ng-model="typeValues[item._id]" value="{{item._id}}"/>
{{ item.Service_Categories}}
</label>
</div>
<input type="submit" name="submit" value="submit"/>
</form>
$scope.check= function() {
//console.log("a");
$http.get('XYZ.com').success(function(data, status,response) {
$scope.items=data;
});
$scope.booking=function(){
$scope.typeValues = [];
console.log($scope.typeValues);
}
I am getting empty array.
Can somebody tell how to grab all selected checkbox values only on submit event.
<div ng-repeat="item in items">
<input type="checkbox" ng-model="item.SELECTED" ng-true-value="Y" ng-false-value="N"/>
</div>
<input type="submit" name="submit" value="submit" ng-click="check(items)"/>
$scope.check= function(data) {
var arr = [];
for(var i in data){
if(data[i].SELECTED=='Y'){
arr.push(data[i].id);
}
}
console.log(arr);
// Do more stuffs here
}
Can I suggest reading the answer I posted yesterday to a similar StackOverflow question..
AngularJS with checkboxes
This displayed a few checkboxes, then bound them to an array, so we would always know which of the boxes were currently checked.
And yes, you could ignore the contents of this bound variable until the submit button was pressed, if you wanted to.
As per your code all the checkboxes values will be available in the typeValues array. You can use something like this in your submit function:
$scope.typeValues
If you want to access the value of 3rd checkbox then you need to do this:
var third = $scope.typeValues[2];
Declare your ng-model as array in controller, like
$scope.typeValues = [];
And in your template, please use
ng-model="typeValues[item._id]"
And in your controller, you will get this model array values in terms of 0 and 1. You can iterate over there.
I am making a form field where I would like to do a simple show-hide to display div's on a radio button.
<form id="basic" name="basic">
<label><input name="formelement" type="radio" value="yes" /> Yes </label>
<label><input name="formelement" type="radio" value="no" /> No </label>
<div id="yes" style="display: none;">
This is the div that displays that shows when 'Yes' is selected.
</div>
<div id="no" style="display: none;">
This is the div that displays that shows when 'No' is selected.
</div>
</form>
I have played with some various javascript's I have found online and have achieved not a lot of success as most of them online manage to show-hide one div. Getting the 'yes' to hide when 'no' is selected and vice-versa is the tricky part. If anyone could provide some assistance that would be really appreciated!
Just paste these code between head tags
<script type="text/javascript">
window.onload=function(){
var el1 = document.getElementsByName('formelement')[0];
var el2 = document.getElementsByName('formelement')[1];
el1.onchange=function(){
var show=el1.value;
var hide=el2.value;
document.getElementById(show).style.display='block';
document.getElementById(hide).style.display='none';
}
el2.onchange=function(){
var show=el2.value;
var hide=el1.value;
document.getElementById(show).style.display='block';
document.getElementById(hide).style.display='none';
}
}
</script>
DEMO.
The below is assuming value of radio is same as id of the div..
function getRadioVal(name){
var oRadio = document.forms[0].elements[name];
for(var i = 0; i < oRadio.length; i++)
if(oRadio[i].checked)
return oRadio[i].value;
return '';
}
//hide both divs..
document.getElementById("yes").style.display = "none";
document.getElementById("no").style.display = "none";
//show only one of them..
document.getElementById(getRadioVal("formelement")) = "block";
Dealing with javascript without any libraries is a pain when things get complex, I would recommend libraries such as jQuery
this is what you want
How can I check whether a radio button is selected with JavaScript?
assign onclick event and you are good to go.
Here is sample http://jsfiddle.net/HhXGH/57/
I am clicking radio button by jquery but knockout.js does not recognize it.Still it shows first clicked value.
<p>Send me spam: <input type="checkbox" data-bind="checked: wantsSpam" /></p>
<div data-bind="visible: wantsSpam">
Preferred flavor of spam:
<div><input type="radio" name="flavorGroup" value="cherry" data-bind="checked: spamFlavor" /> Cherry</div>
<div><input type="radio" name="flavorGroup" value="almond" data-bind="checked: spamFlavor" /> Almond</div>
<div><input type="radio" name="flavorGroup" value="msg" data-bind="checked: spamFlavor" /> Monosodium Glutamate</div>
</div>
var viewModel = {
wantsSpam: ko.observable(true),
spamFlavor: ko.observable('cherry')
};
ko.applyBindings(viewModel);
$(':radio:last').click();
alert(viewModel.spamFlavor())
This because Knockout is subscribing to the click events of checked radio/checkbox elements only. If you checkout the binding handler code for checked. It does this.
var updateHandler = function() {
var valueToWrite;
if (element.type == "checkbox") {
valueToWrite = element.checked;
} else if ((element.type == "radio") && (element.checked)) {
valueToWrite = element.value;
} else {
return; // "checked" binding only
responds to checkboxes and selected radio buttons
}
So in order to get your code to work do this.
$(':radio:last').prop('checked', true).click();
However if the goal is to check the last value, why not just do
viewModel.spamFlavor("msg");
This would achieve the same result.
Hope this helps.
Adding $(':radio:last').attr('checked', true); in addition to triggering click makes it work for me:
http://jsfiddle.net/jearles/HhXGH/61/
I have two different jsFiddles since I'm not sure exactly what your after.
The first jsFiddle will respond via alert when the last radio button is manually clicked.
The second jsFiddle is your posted /57/ jsFiddle without the alert.
Using an alert or console.log with a function will actually invoke that function. That said, after you have manually set the .click() to the last radio button, it's inadvertently reset back to cherry since that's the default value.
RE-EDIT: The second jsFiddle now includes alert written in syntax that doesn't invoke the function & now uses shorted markup.
Ok before i make spaghetti of this code i thought id ask around here. ive made a quiz for an online site.
The answers are stored in an array, and ive a function that checks the answers array to what youve clicked. then it counts them and gives you your score.
but i want to change the clor of the right answer wen the user clicks the score button. so the correct answers are highlighted. something like this https://www.shutterpoint.com/Home-Quiz.cfm (just hit submit at the bottom, no need to do the quiz).
the little answer icon at the side looks flashy but id rather just have the text change color. heres how my questions are formatted
<p>Film speed refers to:</p>
<p id = "question1">
<input type="radio" name="question1" id="Wrong" value = "a" onClick = "recordAnswer(1,this.value)"/>How long it takes to develop film. <br/>
<input type="radio" name="question1" id="Wrong" value = "b" onClick = "recordAnswer(1,this.value)"/>How fast film moves through film-transport system. <br/>
<input type="radio" name="question1" id="Answer" value = "c" onClick = "recordAnswer(1,this.value)"/> How sensitive the film is to light. <br/>
<input type="radio" name="question1" id="Wrong" value = "d" onClick = "recordAnswer(1,this.value)"/> None of these makes sense. <br/></p>
and these are the two functions that are called throughout. record answer is called every time the user clicks a button
function recordAnswer(question,answer)
{
answers[question-1] = answer;
}
this is the final button which calculates the score
function scoreQuiz()
{
var totalCorrect = 0;
for(var count = 0; count<correctAnswers.length;count++)
{
if(answers[count]== correctAnswers[count])
totalCorrect++;
}
<!--
alert("You scored " + totalCorrect + " out of 12 correct!");
-->
}
another function is best i think. ive already made attempts at it and know i have to set the color using
document.getElementById('Answer').style.color = '#0000ff';
onyl problem is 'Answer' doesnt seem to be registering. anyone shed some light?
ok so i cant have two or more of the same ids.
what about
if(value == correctAnswers[])
{
// change the color.
}
QUICK RESPONCE:
USE <P>
<p>
<input type="radio" name="question_1" class="wrong" value="a" />
How long it takes to develop film.
</p>
THEN
if(value == correctAnswers[])
{
YOUR_ELEMENT.parentNode.style.color = 'green';
}
IMPROVEMENT
DEMO: http://jsbin.com/aceze/26
hi Overtone!
first of all you need to restyle a litte your HTML schema!
you have multiple id="Wrong" instead of class="Wrong"
then here how your code should look:
var answers = { 1:'a' , 2:'f' , 3:'h' };
function checkQuestions() {
var form_elements = document.question_form.elements.length;
for ( var i = 0; i < form_elements; i++ )
{
var type = question_form.elements[i].type;
if ( type == "radio" ){
var quest = question_form.elements[i];
//if ( quest.checked ) {
var question_index = parseInt(quest.name.split('_')[1]);
//}
if ( quest.value == answers[question_index] ) {
quest.parentNode.style.border = '1px solid green';
quest.parentNode.style.color = 'green';
} else {
//quest.parentNode.style.border = '1px solid red';
quest.parentNode.style.color = 'red';
}
}
}
}
USE a FORM and one time SUBMIT BUTTON instead of adding onclick to each RADIO like this
<form name="question_form" id="question_form" method="POST" action='#'>
<div id="question_1"> <H4>QUESTIONS TIME 1</H4>
</div>
<p>
<input type="radio" name="question_1" class="wrong" value="a" />
How long it takes to develop film.
</p>
<p>
<input type="radio" name="question_1" class="wrong" value="b" />
How fast film moves through film-transport system.
</p>
<p>
<input type="radio" name="question_1" class="answer" value="c" />
How sensitive the film is to light.
</p>
<p>
<input type="radio" name="question_1" class="wrong" value="d" />
None of these makes sense.
</p>
...
...
<input type="radio" name="question_2" class="wrong" value="h" />
<span>None of these makes sense.
</span>
</p>
<input type="submit" name="submit" onclick="checkQuestions();return false;" value="submit"/>
</form>
PS: demo example updated with style... for sake!
You should format your ids in a more usable way.. I'd suggest something similar to questionNUMBER_answerVALUE.
Then it'd be a simple matter of...
for (var i=0; i<correctAnswers;i++) {
document.getElementById("question" + (i+1) + "_answer" + correctAnswers[i].toUpperCase()).style.color = "#0000FF";
};
Just check I've got your zero/non-zero indexing correct with regard to question/ answer numbers.
Instead of using a <p> I would consider using a <label for='question1_answerA'>How long it takes to develop film.</label>. You can still use a jQuery selector to find it and it feels more semantically correct. You will then also be able to select the option by clicking the text.
Although your other HTML isn't semantically correct. You need to give each radio a unique ID.
Obligatory jquery solution:
var highlightCorrect = function(){
$(".Answer").css("color", "#00FF00");
}
This is all assuming that you fix your HTML to use classes rather than IDs for "Wrong" and "Answer".