Can someone help me understand this AngularJS code?

Currently, I'm grappling with a form in Angular that's presenting me with an unusual complication. The form resembles a rating system where users are asked to rate 5 questions on a scale of 1-5. Seems simple enough, right?

Add up the scores and divide by 5, correct?

The math checks out, but here's where it gets interesting - if you choose the radio boxes in reverse order (from question 5 to question 1) and halt before selecting the last option, the calculations go haywire. For instance, picking "option 3" for 4 out of 5 questions yields an average of 666.6. However, it should actually be 2.4. Yet, when you select the options in the correct sequence from question 1 to question 5, everything adds up correctly even if you stop half-way.

I've created a fiddle so you can observe this phenomenon.

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

Here's the snippet of HTML code:

    <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>

And now for the Angular code:

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

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

    };

});

Does anyone have insights into what may be causing this odd behavior in Angular? It's not critical for my project, but the curiosity is definitely piqued!

Answer №1

In order to properly initialize your $scope.data, you should set an initial value like this:

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

    };

It is important to ensure that each item in your object is set as an int and not a string. This will avoid any issues that may arise due to incorrect data types. Hopefully this explanation helps!

Answer №2

Check out this Plunkr example

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

I have simplified the code and HTML for you. Simply use ng repeats to generate your array of radio buttons.

Make your model an array.

To calculate the average, add up the values in the model and divide by the number of populated rows (display 0 if no rows are populated).

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>

JavaScript

(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
       }
   } 

})();

Answer №3

The reason for this behavior is due to the fact that your ng-model assumes that all input values are strings by default. This leads to the unintended result you are experiencing here.

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

Essentially, what is happening is that the values are being concatenated as strings first, and then attempted to be divided. This results in a string being returned, which is then converted to a number after concatenation, leading to division.

For example,

When doing "" + 1, a string is returned. Dividing this string by 5 will surprisingly give you 0.2.

However, if all three options are set to "one", you will end up with a string of 111, which when divided by 5 gives you 22.2.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing React across various sections of a traditional website

I have transitioned from using Angular 1.x to React in my server-rendered ASP.NET website built on Umbraco CMS. While I am familiar with creating single-page applications (SPAs) using create-react-app, I now need to incorporate React components in various ...

Having issues with importing ThreeJS FBXLoader through CDN

I am attempting to import ThreeJS and the ThreeJS FBXLoader example through a cdn. Here are my imports: <script type="module"> import * as THREE from 'https://cdn.skypack.dev/three'; import * as FBXLoader from 'https://cdn.sk ...

Encountering challenges with the angular2-infinite-scroll plugin

I encountered 2 errors while using my application: Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost:3002/angular2-infinite-scroll angular2-polyfills.js:1243 Error: XHR error (404 Not Found) loading htt ...

Increase the Speed of setInterval in JavaScript

I'm currently experimenting with gradually decreasing the interval at which a function is executed within a setInterval method. Below is a simplified example code snippet: var speed = 100; window.setInterval( speed -= 0.01 , speed); I suspect that ...

Combining Prisma results into a unified object

I am currently working on a project using nextjs 13 and prisma ORM with MongoDB. My task involves fetching roles along with their permissions to create an admin role matrix. Here is the schema for the Role model. model Role { id String @id @de ...

Dealing with repetitive HTML elements in Angular JS: Tips for managing duplicate code such as headers and footers

After reading the Angular JS introduction, I noticed that there was no mention of a method to write your HTML header and footer code once and have it automatically included on all pages. Is there an official or recommended way to achieve this? ...

Any ideas on how to fix the error that pops up during the installation of the bootstrap package in Node

The npm command is not recognized as a valid cmdlet, function, script file, or operable program. Please double check the spelling of the command and ensure that the path is correct before trying again. This error occurred at line 1. npm i bootstrap + ...

Rendering the page using ReactDOM.render

Just started with ReactJS, I'm struggling to figure out why my page isn't displaying anything - <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> ...

Is it possible to retrieve a callback function from a select event in the Bootstrap dual listbox?

I'm fairly new to front-end development and have been using the Bootstrap DualListbox for a project. I'm looking for a way to save items moved from one list to another to a database before they are officially transferred. Is there a callback func ...

Sending information from Vue to Express for processing

Is there a way to pass data from Vue to an express server? For example, in the scenario below, I am looking to send the data logged in my Vue function to the "id" variable on the server side. expressApp.post('/delete' , function (request, respons ...

How is it that a callback function can successfully execute with fewer arguments provided?

Code I'm really intrigued by how this code functions. In the verifyUser function, it passes a callback function as the fourth argument to the verifyToken function. However, upon examining the verifyToken function itself, I noticed that it only has th ...

What is the best way to transfer the search query to a table filter when working with multiple JavaScript files?

I am struggling with passing the search query from my search file to my table file. The data for my datagrid table is retrieved from a database using an API call, and the table code is in one file while the search functionality code is in another file. I h ...

Switch from buffer to base64 encoding for viewing in Angular

Hello, I have developed an application using the MEAN stack. Currently, I am facing an issue with retrieving images from my endpoint. The image array values that I am receiving look like this: 8,8,7,7,9,8,9,8,9,8,9,9,8,8,8,8,7,9,7,7,9,10,16,13,8,8,16,9,7, ...

Retrieve the data stored in the `frontmatter` of `.mdx` files with the help of a `.js` script

I am looking to utilize https://github.com/iamvishnusankar/next-sitemap for Sitemap generation. However, when I try using it in the regular way as shown below: next-sitemap.js module.exports = { siteUrl: 'https://example.com', generateRobots ...

Learn how to effectively transfer data from $.getjson to PHP, specifically through the use of Laravel's @foreach loop

$.getJSON( 'http://localhost/media_books/index.php/new_books.json?provider_id=1&limit=99&offset=1') .done(function( json ) { $(tar).closest('.accordion').children('div').text(json); }); I have successfully obtaine ...

Modify parameters variable when searching by utilizing bootgrid along with structured-filter

I have implemented both https://github.com/evoluteur/structured-filter and to develop an advanced search functionality using ajax/php. Initially, the code is functioning correctly and retrieves data from the php file. However, I am facing difficulties wh ...

Notifying with Jquery Alert after looping through routes using foreach loop

I am trying to create a jQuery alert message that displays after clicking on a dynamically generated button in the view using a foreach loop. The issue I am facing is that only the first button in the loop triggers the alert, while the subsequent buttons ...

Drop-down functionality in Bootstrap Form becomes unresponsive after screen width is decreased

I recently encountered a strange issue with my simple Bootstrap form. When I resize my browser width to mobile size or view it on a mobile device, the form stops functioning properly. Unfortunately, I am unable to provide any specific code examples at this ...

What is the best method to display the content in the second response for ajax's authorization and dealing with cors?

I have successfully implemented basic authorization and enabled CORS on my VPS. Check the CORS preflight request using cURL: HTTP/1.1 200 OK Date: Sat, 15 Sep 2018 08:07:37 GMT Server: Apache/2.4.6 (CentOS) Access-Control-Allow-Origin: http://127.0.0 ...

Extracting information from within Ajax's Jsonp

How can I retrieve data from the Ajax function(result)? Why isn't this app working? Please assist me. function star(a) { var res; $.ajax({ url: 'https://api-metrica.yandex.com/analytics/v3/data/ga?end-date=today&ids=ga%3A35 ...