1

I have a problem with my code. In my app I have 2 controllers one is to load all the data and the second is to display a tab.

Here's the setup:

<div class="row" ng-app="quotation_list">
    <div class="col-md-12" ng-controller="quoteList">
        <section ng-controller="PanelController as panel">

           <div class="panel pane-default" ng-show="panel.isSelected(1)">
              ...
              <div class="row">
                        <div class="form-group">
                            <label>VAT(%): </label>
                            <input type="number" class="form-control text-right" ng-model="vat_rate" />
                        </div>
                    </div>
              <button class="btn btn-default" type="button" ng-click="computePercentage()">TEST VALUE</button>
           </div>
        </section>
    </div>
</div>

And I am trying to get the value of the model vat_rate but what I got is undefined value

Here's my function for that:

var quotationList = angular.module('quotation_list', ['jsonFormatter','ui.bootstrap','ckeditor']);

    quotationList.controller('quoteList', function($scope, $http) {

    //some codes ...
    $scope.computePercentage = function() {
        console.log($scope.vat_rate);
    }

});

I don't know where's my error. And one more question is it fine if I create a controller inside a controller? Just like what I did?

Ok that's all I hope you can help me. :)

Jerielle
  • 7,144
  • 29
  • 98
  • 164
  • you're mixing methods here. some of your HTML is using `$scope` and some of it is using `controller as`. also, you haven't shown which of the controllers your function is on, and which you are *expecting* to have the `vat_rate` in. – Claies Jul 08 '15 at 04:47
  • 1
    also, due to the way JavaScript prototype inheritance work and the way angular controllers work http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs , you should ALWAYS be bound to object properties rather than primitive properties (i.e. the "dot rule"). – Claies Jul 08 '15 at 04:51
  • ok, so based on the edit you just made, you are trying to run a function and access the property from the outer controller, but because it's not an object property, it's scoped as a property on the inner controller. – Claies Jul 08 '15 at 04:52
  • I really would recommend that you consider refactoring the outer controller to use `controller as`, in the way that the inner controller is defined, and don't rely upon `$scope`. aside from making the code more uniform to work with, it would also make it much more clear which controller is in control of which properties. (something like `quoteList.vat_rate` is much more clear). – Claies Jul 08 '15 at 04:57
  • yes, so you mean there's no way to access the scope variable from the outer controller? – Jerielle Jul 08 '15 at 04:58
  • well, there *are* ways that you can access nested ***objects***, but not primitive properties like what you are using here. – Claies Jul 08 '15 at 04:59

2 Answers2

3

yes you can create a controller inside controller.

<body ng-controller="firstController">
    <span>{{scopeinFirstController}}</span>
    <div ng-controller="secondController">
        <span>{{scopeinSecondController}}</span>
        <div ng-controller="lastController">
            <span>{{scopeinlastController}}</span>
        </div>
    </div>
</body>
Amar Gohil
  • 163
  • 2
  • 12
1

As I pointed out in comments, you are mixing styles here, which is making it difficult to access your property in the correct scope. Also, because your property is a primitive value without prior assignment, and not an object, it is subject to JavaScript Prototype Inheritance issues.

Here is how I would recommend refactoring your outer controller to make use of controller as, simplify the controller somewhat, and make it plainly obvious which controller your properties belong to. This has an added side benefit of automatically enforcing the "dot rule" with regard to Prototype Inheritance.

var quotationList = angular.module('quotation_list',
                            ['jsonFormatter','ui.bootstrap','ckeditor']);

    quotationList.controller('quoteListController', function($http) {

    var quoteList = this; //store a reference to this for easy use

    //some codes ...

    quoteList.computePercentage = function() {
        console.log(quoteList.vat_rate);
    }    
});

And the HTML:

<div class="row" ng-app="quotation_list">
    <div class="col-md-12" ng-controller="quoteListController as quoteList">
        <section ng-controller="PanelController as panel">

           <div class="panel pane-default" ng-show="panel.isSelected(1)">
              ...
              <div class="row">
                  <div class="form-group">
                      <label>VAT(%): </label>
                      <input type="number" class="form-control text-right" ng-model="quoteList.vat_rate" />
                  </div>
              </div>
              <button class="btn btn-default" type="button" ng-click="quoteList.computePercentage()">TEST VALUE</button>
           </div>
        </section>
    </div>
</div>
Community
  • 1
  • 1
Claies
  • 22,124
  • 4
  • 53
  • 77
  • Thanks sir, what do you mean by this? `Also, because your property is a primitive value without prior assignment, and not an object,` in every model I create should I make it an object? – Jerielle Jul 08 '15 at 05:16
  • Ok I got it. Thank you so much. I will study your provided link and hopefully I can understand it. Thanks again :) – Jerielle Jul 08 '15 at 05:20
  • 1
    I couldn't begin to explain it better than the answer to the question I linked, but essentially, in your first sample, because the `vat_rate` is a primitive number, it's actually bound to the `PanelController` `$scope`. but because it wasn't assigned in the JavaScript, it's "hidden" from other scopes. – Claies Jul 08 '15 at 05:20
  • 1
    like in the other answer, where he has `firstController`, `secondController`, `lastController`, any primitive strings, numbers ,etc in `lastController` are not visible in `secondController` or above. – Claies Jul 08 '15 at 05:22
  • 1
    and if you had a variable with the same name in more than one, they each would have a different value; ex. if you had `myNum` in `lastController` and `myNum` in `secondController`, `secondController.myNum !== lastController.myNum`. – Claies Jul 08 '15 at 05:25