0

I am working on a form with Angular and ran into an odd issue. The form is like a rating form, and I want to display to the user the average rating, it is 5 questions, based on a score of 1-5. Easy right?

Add them together and divide by 5?

The math works, but if you select the radio boxes going backwards.. meaning start selecting the 5 question, and going to question 1, and you STOP before selecting the last radio box the math is all screwy. For example selecting "option 3" for 4 out of 5 questions comes up with an average of 666.6? But that should come out to an average of 2.4. If you select the elements in the correct order going from question 1 to question 5, the math works out even if you stop selecting options?

I created a fiddle so you can see this.

http://jsfiddle.net/YGQT9/737/

The HTML;

    <div ng-app="myApp">

    <form name="saveTemplateData" action="#" ng-controller="FormCtrl">
<input type='radio' ng-value="1" name="cat1" ng-model="data.cat1">1
<input type='radio' ng-value="2" name="cat1" ng-model="data.cat1">2
<input type='radio' ng-value="3" name="cat1" ng-model="data.cat1">3
<input type='radio' ng-value="4" name="cat1" ng-model="data.cat1">4
<input type='radio' ng-value="5" name="cat1" ng-model="data.cat1">5
---- Selected: {{ data.cat1 }} # DO NOT SELECT
<br />
<input type='radio' ng-value="1" name="cat2" ng-model="data.cat2">1
<input type='radio' ng-value="2" name="cat2" ng-model="data.cat2">2
<input type='radio' ng-value="3" name="cat2" ng-model="data.cat2">3
<input type='radio' ng-value="4" name="cat2" ng-model="data.cat2">4
<input type='radio' ng-value="5" name="cat2" ng-model="data.cat2">5
---- Selected: {{ data.cat2 }} # STOP HERE
<br />
<input type='radio' ng-value="1" name="cat3" ng-model="data.cat3">1
<input type='radio' ng-value="2" name="cat3" ng-model="data.cat3">2
<input type='radio' ng-value="3" name="cat3" ng-model="data.cat3">3
<input type='radio' ng-value="4" name="cat3" ng-model="data.cat3">4
<input type='radio' ng-value="5" name="cat3" ng-model="data.cat3">5
---- Selected: {{ data.cat3 }} # NEXT HERE
<br />
<input type='radio' ng-value="1" name="cat4" ng-model="data.cat4">1
<input type='radio' ng-value="2" name="cat4" ng-model="data.cat4">2
<input type='radio' ng-value="3" name="cat4" ng-model="data.cat4">3
<input type='radio' ng-value="4" name="cat4" ng-model="data.cat4">4
<input type='radio' ng-value="5" name="cat4" ng-model="data.cat4">5
---- Selected: {{ data.cat4 }} # NEXT HERE
<br />
<input type='radio' ng-value="1" name="cat5" ng-model="data.cat5">1
<input type='radio' ng-value="2" name="cat5" ng-model="data.cat5">2
<input type='radio' ng-value="3" name="cat5" ng-model="data.cat5">3
<input type='radio' ng-value="4" name="cat5" ng-model="data.cat5">4
<input type='radio' ng-value="5" name="cat5" ng-model="data.cat5">5
---- Selected: {{ data.cat5 }} # START HERE
<br />
Avg Selected: {{ (data.cat1 + data.cat2 + data.cat3 + data.cat4 + data.cat5) / 5|number }}

    </form>

</div>

The Angular

    var app = angular.module('myApp', []);
    app.controller('FormCtrl', function ($scope, $http) {

    $scope.data = {
        cat1: "",
        cat2: "",
        cat3: "",
        cat4: "",
        cat5: "",

    };

});

Anyone know what is going on under the hood in Angular that is coming out like this? It's not really a big deal for me, but I am very curious.

3 Answers 3

1

Because you need to set an initial value to your $scope.data like this

$scope.data = {
        cat1: 0,
        cat2: 0,
        cat3: 0,
        cat4: 0,
        cat5: 0,

    };

You need to set every item in your object to int but you set it as a string. That is the reason :) Hope it helps

Sign up to request clarification or add additional context in comments.

Comments

1

here is a plunkr

https://plnkr.co/edit/hdGaRDmq8ZYw62tBVsCj?p=preview

I simplified your code / html a bit. just use ng repeats to create your array of radio buttons.

let your model be an array.

to find the average sum up the model values and divide by any rows that have been populated (if no rows have been populated show 0)

html

<div ng-app="myApp">
    <div ng-controller="myCtrl as vm">
  <div ng-repeat = "j in [1,2,3,4,5]">
     <span ng-repeat = " i in [1,2,3,4,5]">
      <input type="radio" 
       ng-value=i name="cat{{j}}" ng-model="vm.model[j]">{{$index + 1}}
     </span>
     </div>
     {{vm.getAverage()}}
    </div>
</div>

js

(function() {
    'use strict';
angular
  .module('myApp', [])
  .controller('myCtrl', myCtrl);

   function myCtrl(){
       /* jshint validthis: true */
       var vm=this;
       vm.model = [];
       vm.getAverage = getAverage;

       function getAverage(){
        return vm.model.reduce((a, b) => a + b, 0)/vm.model.filter(i => i > 0).length || 0
       }
   } 

})();

Comments

0

Its because your ng-model implies that all the input values are strings by default, so what you're doing here

Avg Selected: {{ (data.cat1 + data.cat2 + data.cat3 + data.cat4 + data.cat5) / 5|number }}

is actually appending the strings and then trying to divide but end up returning a string which then once appended gets converted to a number and divided.

So..

Doing "" + 1 will return a string, dividing that string by 5 will magically return 0.2.

However if all 3 options are set as one you'll get as string of 111 that divided by 5 is 22.2.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.