Encountering an issue while attempting to retrieve the average rating: Error occurs in the template helper due to a TypeError where the property 'rating' cannot be read when it

When it comes to my collections of recipes and reviews, users are able to review a recipe and rate it from 1 to 5. I am currently encountering an error while attempting to calculate the average rating of a recipe: Exception in template helper: TypeError: Cannot read property 'rating' of null. Can anyone provide guidance on what mistake I may be making and how to resolve this issue?

collections.js

Recipes = new Mongo.Collection('recipes');
Reviews = new Mongo.Collection('reviews');

add_review.js

Template.add_review.events({
    'submit .add-review':function(event){
        var rating = event.target.rating.value;
        var review = event.target.review.value;
            Reviews.insert({
                rating:rating,
                review:review,
                recipeId:Router.current().data()._id
            });

        return false;
})

helper to calculate average rating

Template.reviews.helpers({

    averageRating: function() {
        var reviews = Reviews.find({recipeId: Router.current().data()._id});
        var ratings = _.pluck(reviews, 'rating');
        var sum = ratings.reduce(function(pv, cv){return pv + cv;}, 0);
        var avg = sum / ratings.length;
        return Math.round(avg);
    }
})

Answer №1

find retrieves a cursor. To convert reviews into an array, you can use fetch in this manner:

var reviews = Reviews.find({recipeId: Router.current().data()._id}).fetch();

Furthermore, ensure to handle the scenario where ratings is an empty array to avoid the average returning as Infinity. Consider adding a check like this:

Template.reviews.helpers({
  averageRating: function() {
      var selector = {recipeId: Router.current().data()._id};
      var reviews = Reviews.find(selector).fetch();

      if (reviews.length === 0)
        return 0;

      var ratings = _.pluck(reviews, 'rating');
      var sum = ratings.reduce(function(pv, cv){return pv + cv;}, 0);
      var avg = sum / ratings.length;
      return Math.round(avg);
  }
});

For further insights, refer to: meteor common mistakes.

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

Issue with the functionality of Bootstrap 5 dismissable alert needs to be addressed

I encountered an issue with the alert in my html code: <div class="alert alert-success alert-dismissible fade show d-flex align-items-center justify-content-center" id="alert" style="display:none;"> <button type=& ...

Is it possible to add items to your cart based on a matching product ID?

My challenge is to add an item to a list only if it matches the id, ensuring that only one item is added to the cart. I've attempted various methods but React doesn't seem to recognize my item's id. Below is the code excerpt where I'm ...

Restrict the quantity of recommendations provided by the AutoComplete feature

After exploring the autocomplete API from https://material-ui.com/api/autocomplete/, I am unable to figure out a way, given my basic understanding of javascript, to restrict the display of a specific number of options beneath the TextField. I am working o ...

Generating a PowerPoint or PowerPointX file from a byte array using TypeScript and Angular 2

In order to generate a .ppt/.pptx file in Angular 2, I am looking for a way to convert my byteArray response into a Blob Object. While I have successfully converted it into image and pdf formats using the code snippet below: var blob = new Blob(resp, {typ ...

Pressing the close button will shut down all bootstrap models

Is there a way to fix an issue where closing Model2 also dismisses the main Model? In my code, there is a button "Launch modal" to open the Model, and within the Model, there is a button "Launch modal2" to open a new model called Model2. However, when ...

Tips for utilizing the for each function within a for loop

Looking to showcase prices alongside each product based on their unique sku value, I've put together a price list. An array of data is being iterated through and pushed into the div container. var arr = [ { "sku": "552", "title": "orange", "pric ...

Utilizing global constants within a Meteor method: A guide

In my Meteor method, I need to pass a Day Of Week value: Meteor.methods({ 'insertShift': function(dow, shiftnum, . . .) { check(dow, Number); check(shiftnum, Number); . . . Shifts.insert({ sh_dow: ...

The dropdown menu is displaying the initial value from the JSON file rather than the expected default text

Operation.. Users need to choose the items displayed in a dropdown menu, which are read from a JSON file. The dropdown menu should initially show a default text of "Please select shops..." before displaying the item names. Challenge: The default text of ...

I'm curious, is there a method to add animation to dynamically adjust the size of the header within the HeaderFooterLayout

Looking for a way to animate the header size within a HeaderFooterLayout? I have been attempting to resize it with an animation, but it seems like there is no specific API for this. Are there any techniques or workarounds that can be used to achieve this ...

To prevent flickering when using child flex elements, it's best to use position fixed along with a dynamically updated scrollbar position using Javascript

My navigation component includes a slim banner that should hide upon scroll and a main-nav bar that should stick to the top of the screen and shrink when it does so. I initially looked into using Intersection Observer based on a popular answer found here: ...

Tips for detecting if a user is typing in React Native

Currently, I am working on an application in React Native where I am implementing a search feature similar to Instagram. The idea is to display the search results as soon as the user stops typing. However, my current approach seems to be causing issues wit ...

Glass-pane or angular/HTML overlay on a designated element

Is there a way to create a glass-pane effect, like an hourglass symbol on a semi-transparent layer, within the boundaries of an HTML element E? The goal is to have the glass-pane only overlap the area within E's boundaries. When the glass-pane is ac ...

Reduce the file size of CSS and JS files for Magento

We are facing an issue with minifying CSS and Javascript for our Magento website. Currently, the size of our website is 1.1 MB and we aim to reduce it to 1 MB or even lower if possible. I tried using the "CSS Settings" and "Javascript Settings" functions ...

Transforming web pages containing html, css, and javascript code into a custom node.js application

I am facing an issue where my HTML pages with CSS and js files work perfectly when opened individually in a browser like Chrome. However, when I try to integrate these pages into a Node.js project that I have created, the js file is not being recognized ...

What steps can be taken to keep an SVG path (graphic) consistently centered, regardless of changes to the viewport?

My current project operates in 2 layers: the bottom layer features a large SVG object with numerous paths, while the top layer displays a small SVG object that I aim to keep perfectly centered. The bottom layer is positioned absolutely using CSS, and the t ...

Fetching locales asynchronously in nuxt.js using i18n and axios: A step-by-step guide

I am facing an issue with getting the location asynchronously. Whenever I try to implement my code, it results in a "Maximum call stack size exceeded" error. How can I resolve this issue? Previously, I attempted to retrieve the location by using the axios ...

Utilize Redux in conjunction with TypeScript to seamlessly incorporate a logout feature

My login page redirects to a private /panel page upon successful login with an accessToken. I am utilizing the Redux store to verify the token in the privateRoute component. Challenges I'm encountering: I aim to enable logout functionality from t ...

Rearrange the elements of an array without altering the original

Looking for a way in JavaScript to sort an array without altering the element order but creating a "grouping" feature. Example Data: [ {group: 'test', title: 'A'}, {group: 'test', title: 'B'}, {group: &apos ...

Implementing ReactJS render state with loops

Having trouble implementing a responsive upvote button. I use an ajax call named 'users' to get an array of user data, and then loop through it to find if any post IDs match the ones in the 'upvoted' array. When a match is found, it mea ...

Is there a way to automatically display the detailsPanel in Material-table upon loading?

I am currently working on creating a subtable for the main React Material-Table. So far, everything is functioning correctly as expected, with the details panel (subtable) appearing when the toggle icon is pressed. Is there a way to have it displayed by d ...