1

I'm creating a small calculator and it creates multiple values with binds. Is there a better way to do this? I feel like this is utter hackery. I'm new to Angular.

The calculator:

<div ng-app="App" ng-controller="CalculatorCtrl">
    <form action="javascript:;" id="calculator" class="form-inline">
        <fieldset class="grid grid-4">
            <div class="item">
                <input required type="number" 
                    ng-model="data.buy"
                    placeholder="Buy Price" 
                    maxlength="10"
                    tabindex="1" />
            </div>

            <div class="item">
                <input required type="number" 
                    ng-model="data.sell"
                    placeholder="Sell Price/target" 
                    maxlength="10"
                    tabindex="2" />
            </div>

            <div class="item">
                <input required type="number" 
                    ng-model="data.shares"
                    placeholder="Share Count" 
                    maxlength="10"
                    tabindex="3" />
            </div>

            <div class="item">
                <input required type="number" 
                    ng-model="data.fee"
                    placeholder="Commission Fee" 
                    maxlength="10"
                    tabindex="3" />
            </div>
        </fieldset>
    </form>

    <!-- Results -->
    <table class="table table-bordered table-striped table-hover">
        <tr>
            <th width="150">Total Profit</th>
            <td>{{ profit() | number:2 }}%</td>
        </tr>

        <tr>
            <th width="150">Net Gain</th>
            <td>{{ data.net = (data.soldFor - data.purchasedFor) | currency }}</td>
        </tr>

        <tr>
            <th width="150">Purchased For</th>
            <td>{{ data.purchasedFor = (data.buy * data.shares) + data.fee | currency }}</td>
        </tr>

        <tr>
            <th width="150">Sold For</th>
            <td>{{ data.soldFor = (data.sell * data.shares) - data.fee | currency }}</td>
        </tr>
    </table>
</div>

The JS (coffeescript) in question:

# Core Coffee
app = angular.module 'App', []
app.controller 'CalculatorCtrl', ['$scope', ($scope) ->
    $scope.profit = ->
        data = $scope.data
        return 0 unless data? and data.net? and data.purchasedFor? and data.soldFor?

        a = if data.soldFor > data.purchasedFor then data.soldFor else data.purchasedFor
        b = if a is data.soldFor then data.purchasedFor else data.soldFor

        res = if data.net >= 1 then '+' else '-'
        res += ((a - b) / b) * 100
]

How can I ensure that the data exists (like how Angular is doing automatically) without this line? return 0 unless data? and data.net? and data.purchasedFor? and data.soldFor?

EDIT: Thanks to Maxim, this works perfectly:

### Watch for the net gain value and then calculate a profit % ###
$scope.$watch 'data.net', (newVal, oldVal) ->
    return 0 unless newVal?
    data = $scope.data

    a = if data.soldFor > data.purchasedFor then data.soldFor else data.purchasedFor
    b = if a is data.soldFor then data.purchasedFor else data.soldFor

    $scope.data.profit = if newVal >= 1 then '+' else '-'
    $scope.data.profit += ((a - b) / b) * 100
1
  • can't get around testing your properties within calculator. You could put the properties into an array and loop array testing each one and return zero if any one doesn't exist. Or loop over keys in data so don't have to hard code property names Commented Oct 29, 2013 at 19:16

1 Answer 1

1

I would use $watch to listen on data.

See docs here

Generally $watch with flag true does deep compare.

Something like (hope you can convert it to coffee):

$scope.$watch(function () {
    return$scope.data;
   },
   function (newValue, oldValue) {
    // here you can write any action
   }, true);
Sign up to request clarification or add additional context in comments.

3 Comments

could still fill out only one field and watch will fire. Still have to validate the properties
watch will fire if data will change, no mater what sub-field
I think this is it, because I can watch for "data.net" which requires everything else anyway. Will test. EDIT: It works!

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.