3

Currently have my checkboxes adding and subtracting their costs from my total cost. How can I get my select to do the same? Currently its putting in a default value of 7700.00 when without the select field it is at 0.00. Also noticed my select field is breaking my checkbox function by not subtracting the number off when unchecked.

Updated Fiddle: http://jsfiddle.net/9exaarn2/6/

HTML:

<div ng-app>
    <div ng-controller="showCrtl">
        <input type="checkbox" name="additionalCoverage" ng-click="cost(150, $event.target.checked)">
        <label>Add this coverage $150/YR</label>
        <br>
        <input type="checkbox" name="additionalCoverage" ng-click="cost(40, $event.target.checked)">
        <label>and or this coverage $40/YR</label><br>

            <select>
                <option disabled selected>Select one...</option>
                <option ng-selected="option(200)">add $200/yr</option>
                <option ng-selected="option(500)">add $500/yr</option>
            </select>
         <h1 class="annualCost">TOTAL ANNUAL COST<br>OF HOME WARRANTY</h1>
 <span style="color: green; font-size: 45px; line-height: 2;">{{annualCost}}</span>
        <br>
    </div>
</div>

JS:

function showCrtl($scope) {
    $scope.dollarAmmount = 0.00;
    $scope.annualCost = "$" + $scope.dollarAmmount + ".00";

    $scope.option = function (amt) {
        $scope.dollarAmmount = $scope.dollarAmmount + amt;
        $scope.annualCost = "$" + $scope.dollarAmmount + ".00";
        console.log($scope.dollarAmmount)
    };

    $scope.cost = function (amt, checked) {
        amt *= checked ? 1 : -1;
        $scope.dollarAmmount = $scope.dollarAmmount + amt;
        $scope.annualCost = "$" + $scope.dollarAmmount + ".00";
        console.log($scope.dollarAmmount)
    };
}

EDIT: Oops had a typo in my fiddle. Issue still the same...

Parzi
  • 694
  • 2
  • 10
  • 33
  • It would appear you are thinking with a jQuery mindset. I'll post a jsfiddle in a few minutes to show you the angular way to achieve your goal. – Jonathan Wilson May 19 '15 at 21:58
  • Awesome! I will wait patiently... :P – Parzi May 19 '15 at 21:59
  • 1
    You should read [this question and answer](http://stackoverflow.com/questions/14994391/thinking-in-angularjs-if-i-have-a-jquery-background/15012542#15012542). I think it will help. – Jonathan Wilson May 19 '15 at 21:59

3 Answers3

2

It is clear you are thinking with a jQuery mindset. You need to practice thinking the angular way. See this question and answer for some idea on what that is.

First thing, you need to actually model your problem, describing what things are and not so much how things are done. This may seem like splitting hairs. It is not. You should be using ng-model to track form input, not click handlers.

Here's the controller code you should strive for.. notice how totalCost is defined as a sum of the coverage costs.. and not some value you are manipulating manually as the user changes your form:

function showCrtl($scope) {
    $scope.coverage = [];
    $scope.totalCost = function (){
        return $scope.coverage.reduce(function(sum, cost){
            return sum + parseInt(cost);
        },0);
    };
}

And here's the template (note that I removed the input names and click handlers... you don't need 'em!):

<input type="checkbox" ng-model="coverage[0]" ng-true-value="150" ng-false-value="0">
<label>Add this coverage $150/YR</label>
<br>
<input type="checkbox" ng-model="coverage[1]" ng-true-value="40" ng-false-value="0">
<label>and or this coverage $40/YR</label><br>
<select ng-model="coverage[2]">
    <option disabled selected>Select one...</option>
    <option ng-value="200">add $200/yr</option>
    <option ng-value="500">add $500/yr</option>
</select>
<h1 class="annualCost">TOTAL ANNUAL COST<br>OF HOME WARRANTY</h1>
<span style="color: green; font-size: 45px; line-height: 2;">
{{totalCost() | currency}}
</span>

Also note the use of currency. This is called a filter. It is used for formatting a number in the $0.00 format. Formatting is a responsibility typically handled by the view and not the controller or model.

Check out the working fiddle.

If you're interested, we can take things a little further and improve the model more. Do you see how the coverage costs are duplicated in the template (one for display, one in ng-value)? We can rewrite the controller and view such that the application model (your coverage options) are represented in only one place:

Controller:

function showCrtl($scope) {
    $scope.coverageCosts = [];
    $scope.totalCost = function (){
        return $scope.coverageCosts.reduce(function(sum, cost){
            return sum + parseInt(cost);
        },0);
    };
    $scope.primaryCoverageOptions = [150,40];
    $scope.specialCoverageOptions = [200, 500];
}

In the future, your coverageOptions might come from your back end via AJAX ($http.get) or vary on some schedule. Now that the information has been extracted from your view, you can change it more freely.

Template:

<div ng-app>
    <div ng-controller="showCrtl">
        <div ng-repeat="option in primaryCoverageOptions">
            <label>
            <input type="checkbox" ng-model="coverageCosts[$index]" ng-true-value="{{option}}" ng-false-value="0"/>
            Add this coverage {{option | currency}}/YR
            </label>                
        </div>
        <select ng-model="coverageCosts[2]">
            <option disabled selected>Select one...</option>
            <option ng-repeat="option in specialCoverageOptions" ng-value="option">
                {{option | currency}}
            </option>
        </select>
        <h1 class="annualCost">TOTAL ANNUAL COST<br>OF HOME WARRANTY</h1>
        <span style="color: green; font-size: 45px; line-height: 2;">
        {{totalCost() | currency}}
        </span>
        <div>
            Selected coverage costs: {{coverageCosts}}
        </div>
        <br>
    </div>
</div>

Now there is no duplicated data in the view... all data comes from the controller. This is good practice.

Updated fiddle

Community
  • 1
  • 1
Jonathan Wilson
  • 4,138
  • 1
  • 24
  • 36
  • one thing that I notice right off the bat. There is no longer a $ or a decimal point value which I need both. (This may be something I can solve on my own just pointing out that they are no longer there and needed for my situation) – Parzi May 19 '15 at 22:20
  • 1
    in your html, to display $ and .00, just add the `currency` filter, see this: [angularjs docs](https://docs.angularjs.org/api/ng/filter/currency)..the View should handle this type of formatting, not the Model or Controller. – Shehryar Abbasi May 19 '15 at 22:22
  • @Shehryar didn't think of that. I was able to easily add it back using the controller but that might work better I will look into that. Thanks everyone who has helped! :D – Parzi May 19 '15 at 22:23
  • @Shehryar, good catch. Updated the answer to include use of the `currency` filter. – Jonathan Wilson May 19 '15 at 22:32
  • @JonathanWilson Just added your code to my website it works GREAT!!! thanks again. – Parzi May 19 '15 at 22:37
  • @LandonCall You're welcome. Hopefully, you're now closer to being able to write clean angular code yourself! – Jonathan Wilson May 19 '15 at 22:39
0

Here is the solution

<div ng-app>

Add this coverage $150/YR
and or this coverage $40/YR

<select ng-selected="option()" ng-model="sel">
  <option disabled selected>Select one...</option>
  <option value="200">add $200/yr</option>
  <option value="500">add $500/yr</option>
</select>
<h1 class="annualCost">TOTAL ANNUAL COST<br>OF HOME WARRANTY</h1>
<span style="color: green; font-size: 45px; line-height: 2;">{{annualCost}}</span>
<br>

and for your js,

function showCrtl($scope) {
$scope.sel =0;
$scope.dollarAmmount = 0.00;
$scope.annualCost = "$" + $scope.dollarAmmount + ".00";

$scope.option = function () {
    $scope.dollarAmmount = $scope.dollarAmmount + $scope.sel;
    $scope.annualCost = "$" + $scope.dollarAmmount + ".00";
    console.log($scope.dollarAmmount)
};

$scope.cost = function (amt, checked) {
    amt *= checked ? 1 : -1;
    $scope.dollarAmmount = $scope.dollarAmmount + amt;
    $scope.annualCost = "$" + $scope.dollarAmmount + ".00";
    console.log($scope.dollarAmmount)
};

}

Olatunde Garuba
  • 1,049
  • 1
  • 16
  • 21
0

You can simply bind a $scope model to select then watch its value.. after every change take differences of new and old value and add it to the totalAmount...

$scope.$watch('selectedValue', function(newValue, oldValue){
    $scope.dollarAmmount = $scope.dollarAmmount + (newValue - oldValue);
    console.log($scope.dollarAmmount)
    $scope.annualCost = "$" + $scope.dollarAmmount + ".00";
})

here is your updated JSFIDDLE...

NOTE!!: You should initialize your variable at your scope otherwise first value f it will be undefined which breaks your algorithm...

$scope.selectedValue = 0;
Poyraz Yilmaz
  • 5,847
  • 1
  • 26
  • 28