1

I'm trying to use Angular to create a tool that accepts user input from a slider tool, and automatically updates an "estimate" field whenever the values are changed. However, the data only seems to be binding on the way to the view; the user input is displayed, but doesn't seem to register in the scope.

Here's the HTML:

<h3 ng-controller="calcController" ng-model="estimate" class="floating-menu">${{estimate}}</h3>
    <form ng-controller="calcController" method="post" action="/estimate">

        <div class="container">
            <div class="vals">${{values.insurance}}</div>
            <div id="insurance-slider">
                <slider floor="0" ceiling="250" value="125" step="25" precision="2" ng-model="values.insurance" ng-change="changeVal()" translate="currencyFormatting"></slider>
            </div>

        <div class="container">
            <div class="vals">${{values.lease}}</div>
            <div id="lease-slider">
                <slider floor="0" ceiling="250" value="125" step="25" precision="2" ng-model="values.lease" translate="currencyFormatting"></slider>
            </div>
        </div>
     </form>

Here's the Angular:

 //create the module
   angular.module('Breeze', ['ngRoute', 'ngResource', 'ui.slider'])

   .config(function($routeProvider) {
       $routeProvider

       // route for the calculator page
           .when('/', {
           templateUrl: 'partials/calculator.html',
           controller: 'calcController'
       });
   })

    // create the controller and inject Angular's $scope
   .controller('calcController', function($scope, $http) {
       $scope.values = {
           // Default values
           insurance: 125,
           lease: 125,
       };

       $scope.estimate = $scope.values.insurance + $scope.values.lease
      }

       // Formatting for scale bar
       $scope.currencyFormatting = function(value) {
           return value.toString() + " $";
       }
   })

I've tried adding a $watch and a $broadcast function but can't seem to get them working.

This is what it looked like in Angular:

   $scope.$watch("values", function(newVal, oldVal, scope) {
       scope.estimate = addVals();
    })
  $scope.changeVal = function() {
    $scope.estimate = addVals();
    console.log('hi')

   $scope.estimate = $scope.values.insurance + $scope.values.lease
  }

Ideas?

Car
  • 337
  • 2
  • 4
  • 14
  • can you put up a fiddle or a jsbin? – vimes1984 Sep 26 '14 at 19:17
  • good call. I've started one here: jsfiddle.net/carno11/3gmjcq8k - having a minor setback getting the slider dependencies in there but will keep working on it... Also, this is my first time making a fiddle so I'm not exactly sure why the angular isn't showing up right... – Car Sep 26 '14 at 19:43
  • I have updated my answer. Noticed you were trying to use ng-controller twice and had no ng-app. – rleffler Sep 26 '14 at 20:22

3 Answers3

1

Just setting them equal in the beginning wont work. In your view, instead of having an estimate field just use this

<div ng-controller="calcController" ng-app="Breeze">
    <h3 ng-model="estimate" class="floating-menu">${{values.insurance + values.lease }}</h3>
        <form method="post" action="/estimate">

            <div class="container">
                <div class="vals">${{values.insurance}}</div>
                <div id="insurance-slider">
                    <slider floor="0" ceiling="250" value="125" step="25" precision="2" ng-model="values.insurance" ng-change="changeVal()" translate="currencyFormatting"></slider>
                </div>

            <div class="container">
                <div class="vals">${{values.lease}}</div>
                <div id="lease-slider">
                    <slider floor="0" ceiling="250" value="125" step="25" precision="2" ng-model="values.lease" translate="currencyFormatting"></slider>
                </div>
            </div>
           </div>
         </form>
</div>

This will keep them adding as the values change.

Another thing that would be breaking is that you have two controller calls to the same controller and no app. Need to change it as below with the new div and remove the rest of the ng-controllers.

Also, make sure that you have the ui slide javascript file included on your page.

rleffler
  • 430
  • 6
  • 15
  • I've tried this - it still doesn't update, even when the scale bar values change. That's why I feel like the updated data isn't being sent back to $scope - I can see the label next to the scale bar change, but the values aren't adding in the "estimate" field. – Car Sep 26 '14 at 19:54
  • Doubling up the controller calls was the problem - I think this ends up creating a new scope. Thanks! – Car Sep 27 '14 at 23:46
1

You are using two nested ng-controller="calcController"in your HTML. Hence two instanciations of the controller (two $scope) which will have their own estimate value, so when you update the inner estimate, the upper one is not aware of that.

You should remove the second ng-controller in your <form> (if the controller were different, then you would put the estimate variable in an object such as $scope.model.estimate so properties inheritance between the two controllers actually work. But in your case there is no reason to have two controllers).

Also, you should remove that ng-model="estimate" in your <h3> tag, which has no effect.

floribon
  • 19,175
  • 5
  • 54
  • 66
0

Did you try to bind to object instead of primitive type?

$scope.values.estimate = $scope.values.insurance + $scope.values.lease

see similar question here: Angularjs: 2 way binding not working in included template

Here is a fiddle http://jsfiddle.net/U3pVM/9330/

Community
  • 1
  • 1
lanan
  • 2,742
  • 3
  • 22
  • 29