Angular: when using ng-include, number variable become NaN

790 views Asked by At

I have a problem when i try to fragment my html with ng-include:

This is what my index.html page looks like when it works (prix=price, TVA=tax):

<!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <link type="text/css" rel="stylesheet" href="style.css" />
        <title> TVA </title>
    </head>
    <body>
        <div>
            <div ng-app="app" ng-controller="appCtrl">
                <input ng-model="tva" placeholder="TVA" /><br />
                <input ng-model="prix" placeholder="Prix" />
                <select ng-model="taxe">
                    <option>HT</option>
                    <option>TTC</option>
                </select>
                <button id="btn" ng-click="calcul()">Calculer</button>
                <p>{{ total }}</p>
           </div>
     </div>
     <script src="angular.min.js"></script>
     <script src="script.js"></script>
     </body>
     </html>

The script.js :

app = angular.module('app', []);

app.controller('appCtrl', ['$scope', function ($scope) {
    $scope.calcul = function() {
        if ($scope.taxe == "TTC") {
            $scope.total = parseInt($scope.prix) + $scope.prix * $scope.tva /100;
        } else if($scope.taxe == "HT") {
            $scope.total = 1/(1+$scope.tva/100)*$scope.prix;
        }
    };
}]);

So this works, the result is an number (the price with or without tax).

When I use the ng-include like this:

<div>
    <div ng-app="app" ng-controller="appCtrl">
        <div ng-include="'tva.html'"></div>
        <input ng-model="prix" placeholder="Prix" />
        <select ng-model="taxe">
            <option>HT</option>
            <option>TTC</option>
        </select>
        <button id="btn" ng-click="calcul()">Calculer</button>
        <p>{{ total }}</p>
    </div>
</div>

I only tried to replace the first input with a new HTML page.

The tva.html :

<input ng-model="tva" placeholder="TVA" /><br />

Now the results show "NaN" (I put those codes on a server so that I can check online). Why is this?

3

There are 3 answers

0
Pankaj Parkar On BEST ANSWER

@Josh Beam Answered & explained ng-include creates a child scope on creating the DOM. I'd suggest you to use dot rule in angular that will follow prototypal inheritance on that object and you object value will access in child scope.

Now your object structure will changed to $scope.model={}; and this model will have all the input values. like all will become like model.prix, model.taxe & model.tva so that the prototypal inheritance will follow.

Markup

<div ng-app="app" ng-controller="appCtrl">
    <div ng-include="'tva.html'"></div>
    <br />
    <input ng-model="model.prix" placeholder="Prix" />
    <select ng-model="model.taxe">
      <option>HT</option>
      <option>TTC</option>
    </select>
    <button id="btn" ng-click="calcul()">Calculer</button>
    <p>{{ total }}</p>
</div>

Code

app.controller('appCtrl', ['$scope', function ($scope) {
  $scope.model = {};
    $scope.calcul = function() {
        if ($scope.model.taxe == "TTC") {
            $scope.total = parseInt($scope.model.prix) + $scope.model.prix * $scope.model.tva /100;
        } else if($scope.model.taxe == "HT") {
            $scope.total = 1/(1+$scope.model.tva/100)*$scope.model.prix;
        }
    };
}]);

tva.html

<input ng-model="model.tva" placeholder="TVA" /><br />

Demo Plunkr

0
Josh Beam On

Short answer: don't use ng-include in this instance.

Long answer: ng-include creates a new child scope, so ng-model inside the ng-include isn't appCtrl's TVA. I don't see a reason here to use ng-include anyway, your code is fine without it.

So basically you're getting NaN (not a number) because $scope.TVA is never set when using the ng-include... you're attempting to multiply an undefined variable by another number, which returns NaN:

output

0
jherax On

The reason for that is the ng-include creates a new scope under the scope when the HTML was included, but you can access to the parent scope by specifying $parent

<input ng-model="$parent.tva" placeholder="TVA" /><br />

A better approach is give an alias to your controller, so it will be clear semantically to children controllers accessing to a specific parent.

<div ng-app="app" ng-controller="appCtrl as vmMain">
    <div ng-include="'tva.html'"></div>

... and in the other file:

<input ng-model="vmMain.tva" placeholder="TVA" /><br />