20

I'm trying to build a calculator for daycare prices in Angular.

Every location in the company franchise has separate prices for every day. So my thinking was to build a form, with first a select that allows you to select the location, then a series of checkboxes for the days.

I'm having trouble with ng-true-value in the checkboxes selecting the correct prices from my json file.

UPDATE: Added Plunkr: http://plnkr.co/edit/MDmrqaH1VzLBzjd5eHgT?p=preview

Consider this code:

        <p class="kind_section">Choose location</p>
        <select ng-model="formData.location" ng-options="location.title for location in data.bso"></select>

        <p class="kind_section">Select days</p>

        <input type="checkbox" ng-model="location.day.mon" ng-change="calculatePrice()" ng-true-value="{{data.bso[formData.location.ID].prices.monday}}" ng-false-value="0">Ma
        <input type="checkbox" ng-model="location.day.tue" ng-change="calculatePrice()" ng-true-value="{{data.bso[formData.location.ID].prices.tuesday}}" ng-false-value="0">Di<br />
        <input type="checkbox" ng-model="location.day.wed" ng-change="calculatePrice()" ng-true-value="{{data.bso[formData.location.ID].prices.wednesday}}" ng-false-value="0">Wo
        <input type="checkbox" ng-model="location.day.thu" ng-change="calculatePrice()" ng-true-value="{{data.bso[formData.location.ID].prices.thursday}}" ng-false-value="0">Do<br />
        <input type="checkbox" ng-model="location.day.fri" ng-change="calculatePrice()" ng-true-value="{{data.bso[formData.location.ID].prices.friday}}" ng-false-value="0">Vr

First the select sets formData with a location ID, then I want to use this ID to select the day prices for the matching location and set those to ng-true-value.

I'm using ng-true-value="{{data.bso[formData.location.ID].prices.monday}}" for this. This doesn't work.

When I set the ID manually like ng-true-value="{{data.bso[0].prices.monday}}" it does work. Why is the result of the select not being picked up by ng-true-value?

This is my json file:

  $scope.data = {
                "bso": [
                  {
                    "ID": 0,
                    "title": "Locatie 1",
                    "prices": {
                        "monday": 130,
                        "tuesday": 130,
                        "wednesday": 200,
                        "thursday":130,
                        "friday": 130
                    }
                  },
                  {
                    "ID": 1,
                    "title": "Locatie 2",
                    "prices": {
                        "monday": 430,
                        "tuesday": 530,
                        "wednesday": 600,
                        "thursday":990,
                        "friday": 730
                    }
                  }
                ]
              };
5
  • What version of Angular are you using? There was a change on ngTrueValue in the last one. Commented Jul 15, 2014 at 12:53
  • I'm using v1.3.0 Beta.13 Commented Jul 15, 2014 at 12:57
  • Use an ng-change to see if the model is being updated at all. Does the formData object exist in your scope? ng-select uses a child scope. Commented Jul 15, 2014 at 13:01
  • It does update.. I'm going to provide a Plunkr, hold on Commented Jul 15, 2014 at 13:04
  • AFAIK, the ng-true-value parse the given expression only once. And the formData.location.ID surely is still undefined at the time the expression is evaluated. Commented Jul 15, 2014 at 14:10

3 Answers 3

17

It seems ng-true-value does not accept non-constant expressions. From the docs(v1.3.0):

Some attributes used in conjunction with ngModel (such as ngTrueValue or ngFalseValue) will only accept constant expressions.

Examples using constant expressions include:

<input type="checkbox" ng-model="..." ng-true-value="'truthyValue'">
<input type="checkbox" ng-model="..." ng-false-value="0">

Examples of non-constant expressions include:

<input type="checkbox" ng-model="..." ng-true-value="someValue">
<input type="checkbox" ng-model="..." ng-false-value="{foo: someScopeValue}">

An ideal workaround probably would be calling a Controller method on ng-click or ng-change inside which you can analyse all the checkboxes for truthy or non-truthy values.

Sign up to request clarification or add additional context in comments.

1 Comment

Just tried this and it doesn't seem to make a difference. I've just added a Plunkr as well: plnkr.co/edit/MDmrqaH1VzLBzjd5eHgT?p=preview
3

Another approach is to delay the creation of the checkbox until the value is ready (on scope or whatever).

In my case I was loading a value via http that wasn't on the scope when the checkbox was created. So I just wrapped it in an ng-if.

          <div class="checkbox" ng-if="viewData.conditionId != undefined">
            <label>
              <input type="checkbox" ng-true-value="{{'\''+ viewData.conditionId + '\''}}" ng-false-value="undefined" ng-model="model.conditionId" required />
              I agree
            </label>
          </div>

Which worked perfectly for my scenario. Yours is a bit different but the same principal should apply - delay creation of the checkbox until you know the value being bound is there.

And yes the stupid quotation marks seem to be necessary.

2 Comments

you may be able to simplify quotes. See stackoverflow.com/a/29019232/4297364
This worked for me as well, although I didn't need the quotation marks because the expressions I wanted were true/false, rather than strings.
2

Expression in the ng-true-value will be evaluated only once, so it won't be dynamic.

One alternative approach is to calculate the values in ng-change callback instead.

Please see my fork http://plnkr.co/edit/9zYS3OZ0sSkXX9rHwcgv?p=preview for the full example.

In html:

<input type="checkbox" ng-model="selectedDays.monday" ng-change="calculatePrice()" /> Mon
<input type="checkbox" ng-model="selectedDays.tuesday" ng-change="calculatePrice()" /> Tue            <br />
<input type="checkbox" ng-model="selectedDays.wednesday" ng-change="calculatePrice()" /> Wed
<input type="checkbox" ng-model="selectedDays.thursday" ng-change="calculatePrice()" /> Thu            <br />
<input type="checkbox" ng-model="selectedDays.friday" ng-change="calculatePrice()" /> Fri

and in controller:

$scope.calculatePrice = function(){
  $scope.formData.location.day = {};

  angular.forEach($scope.selectedDays, function (selected, day) {
    if (selected) {
      $scope.formData.location.day[day.slice(0, 3)] = $scope.data.bso[$scope.formData.location.ID].prices[day];
    }
  });
}

$scope.selectedDays = {};

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.