2

I'm fairly new to Angular. I have two calculators that are functioning, and I'm trying to add the two $scope values, GrandTotal and GrandTotalTwo, to get a total of both sums TotalSum.

Codepen

HTML

<div ng-app="myApp" ng-controller="myController">
    <table>
        <tr>
            <th>Camp Fees</th>
            <th>Number of Campers</th>
            <th>Rates</th>
            <th>Totals</th>
        </tr>
        <tr ng-repeat="event in events">
            <td>{{event.name}}</td>
            <td><input placeholder="0" class="qty" type="number"
                       ng-model="quantity" min="0"
                       ng-change="recalc(event, quantity )" 
                       restrict-to="[0-9]" />
               </div>
            </td>
            <td>{{event.cost | currency : $}}</td>
            <td class="subTotal" placeholder="$0.00">
                {{ quantity*event.cost | currency : $}}
            </td>
        </tr>
    </table>
    <div>
        <h2>Camp Fee Total : {{GrandTotal | currency : $}}</h2>
    </div>
    <br>

    <div ng-controller="myControllerTwo">
        <table>
            <tr>
                <th>Accommodation Fees</th>
                <th>Rooms Needed</th>
                <th>Rates</th>
                <th>Totals</th>
            </tr>
            <tr ng-repeat="eventTwo in eventsTwo">
                <td>{{eventTwo.nameTwo}}</td>
                <td><input placeholder="0" class="qty" type="number"
                           ng-model="quantityTwo" min="0"
                           ng-change="recalcTwo(eventTwo, quantityTwo )"
                           restrict-to="[0-9]" />
                </td>
                <td>{{eventTwo.costTwo | currency : $}}</td>
                <td class="subTotal">{{ quantityTwo*eventTwo.costTwo | currency : $}}</td>
            </tr>
        </table>
        <div>
            <h2>Accommodation Fee Total : {{GrandTotalTwo | currency : $}}</h2>
        </div>
    </div>
</div>
<div ng-controller="ToAddTotal">
    <h2>Sum = {{TotalSum | currency : $}}</h2>
</div>

JS

(function() {
    var myApp = angular.module("myApp", []);
    myApp.controller("myController", ["$scope", myController]);
    var events = [{
        name: "Adults",
        cost: 485,
        itemTotal: 0
    }, {
        name: "Kids 13-18",
        cost: 394,
        itemTotal: 0
    }, {
        name: "Kids 4-12",
        cost: 307,
        itemTotal: 0
    }, {
        name: "Kids 0-3",
        cost: 100,
        itemTotal: 0
    }];

    function myController($scope) {
        $scope.events = events;
        $scope.recalc = function(item, quantity) {
            item.itemTotal = quantity * item.cost;
            $scope.GrandTotal = 0;
            var sum = 0;
            angular.forEach($scope.events, function(event) {
                $scope.GrandTotal = $scope.GrandTotal + event.itemTotal;

                $scope.GrandTotal == NaN ? "custom msg" : $scope.GrandTotal;
                // console.log($scope.GrandTotal);
            })

        };
    }
    myApp.controller("myControllerTwo", ["$scope", myControllerTwo]);
    var eventsTwo = [{
        nameTwo: "Hotel Style Rooms:",
        costTwo: 535, //Not relevant info (display: none in css - line:745)
        itemTotalTwo: 0 //Not relevant info (display: none in css - line:745)

    }, {
        nameTwo: "First Room",
        costTwo: 535,
        itemTotalTwo: 0
    }, {
        nameTwo: "Additional Room(s)",
        costTwo: 445,
        itemTotalTwo: 0
    }, {
        nameTwo: "RV Sites",
        costTwo: 175,
        itemTotalTwo: 0
    }];

    function myControllerTwo($scope) {
        $scope.eventsTwo = eventsTwo;
        $scope.recalcTwo = function(item, quantityTwo) {
            item.itemTotalTwo = quantityTwo * item.costTwo;
            $scope.GrandTotalTwo = 0;
            var sumTwo = 0;
            angular.forEach($scope.eventsTwo, function(eventTwo) {
                $scope.GrandTotalTwo = $scope.GrandTotalTwo + eventTwo.itemTotalTwo;

                $scope.GrandTotalTwo == NaN ? "custom msg" : $scope.GrandTotalTwo;
                // console.log($scope.GrandTotal);
            })

        };
    }
    function ToAddTotal($scope) {
        $scope.TotalSum = function() {
            return $scope.GrandTotal * 1 + $scope.GrandTotalTwo * 1;
        };
    }
})();
3
  • Read AngularJS Developer Guide - Scope Hierarchies. Commented Jun 13, 2018 at 18:41
  • It looks like the third controller is outside of the <div> which encloses the ng-app directive. That is why the AngularJS compiler does not evaluate the {{ expressions for the grand total sum. Commented Jun 13, 2018 at 19:06
  • New AngularJS developers often do not realize that ng-repeat, ng-switch, ng-view, ng-include and ng-if all create new child scopes, so problems often show up when these directives are involved. Issue with primitives can be easily avoided by following the "best practice" of always have a '.' in your ng-models. For more information, see What are the nuances of scope prototypal / prototypical inheritance in AngularJS?. Commented Jun 13, 2018 at 19:14

2 Answers 2

1

You can do everything with the ng-change and ng-model directives -- no need for custom code:

  1. Put everything in the same controller
  2. Set the ng-change attribute on the inputs to set the total: [simplifying for clarity] ng-change="$parent.TotalSum = $parent.GrandTotal + $parent.GrandTotalTwo"
  3. Set the ng-model attribute of the output to TotalSum
Sign up to request clarification or add additional context in comments.

6 Comments

The key to this answer is keeping everything on the same controller. Each view/template (HTML File) should be bound to only one controller. This is how you keep things in-line and readable. Angular is great because of it's dependency injection. So you bind your controller to you template, but within your controller you inject your needs (services).
Something also to note I think to help distinguish AngularJS features is the ng-model and ng-change are both directives. Directives or components are smaller isolated (Key word) functions that you can share throughout the app.
This answer neglects the fact that inputs with ng-model are inside an ng-repeat and the code is not following the "best practice" of always have a '.' in your ng-models.
@georgeawg good eye -- updated the answer -- I agree: the OP code needs heavily refactored.
The use of $parent is a code smell, a symptom of a deeper problem.
|
0

Turns out I noticed I had an extra </div>, which was throwing off my code.

I removed:

function ToAddTotal($scope) {
    $scope.TotalSum = function() {
        return $scope.GrandTotal * 1 + $scope.GrandTotalTwo * 1;
    };
}

and,

<div ng-controller="ToAddTotal">
    <h2>Sum = {{TotalSum | currency : $}}</h2>
</div>

and instead wrote this in the HTML:

<h2>Total Sum : {{GrandTotal*1 + GrandTotalTwo*1 | currency : $}}</h2>

My final product is here if anyone is interested to see all of the code.

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.