0

I have the following code (see below) in whichI use ng-include. The ng-model="numLines" creates a binding of the value in the box and the function changeNumLines() specified in ng-change is called every time the value inside the input box changes. The value of the $scope.numLines inside the changeNumLines() is supposed to be the new changed value. However, it is not. The value that I output to the console is always "1" no matter what input is typed in the box.

However, if I do not use ng-include and just copy paste the partial html file: structCustomRows.htm into index.html instead of ng-include line everything works fine.

So, why is this happening with ng-include and how can I get around it? Thanks.

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>

  <base href="/">

</head>

<script>

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

app.controller('CustomRowsCtrl', ['$scope', function($scope) {

    $scope.numLines = 1;

    $scope.changeNumLines = function() {

        console.log("DEBUG: changeNumLines()");
        console.log(String($scope.numLines));
    }

}]);

</script>

<body ng-app="parserUI">

    <h2>Header</h2>
    <div ng-controller="CustomRowsCtrl">
      <div ng-include src="'app/partials/structCustomRows.htm'"></div>
    </div>  <!-- ng-controller="CustomRowsCtrl" -->

</body>
</html>

structCustomRows.htm

<input type="text" ng-model="numLines" ng-change="changeNumLines()">
jazzblue
  • 2,411
  • 4
  • 38
  • 63

4 Answers4

3

Looking at the docs, it says that "This directive creates new scope". Meaning the $scope.numLines in your controller is actually in the parent scope of your ngInclude directive.

The simplest way to fix this is to put the controller definition in the ngInclude to make it all the same scope. Otherwise, you will have to access the parent scope using something like $scope.$parent.numLines.

Matthew Green
  • 10,161
  • 4
  • 36
  • 54
  • Thanks, the issue is that I want to reuse the same controller code in another place where the controller is specified in $routeProvider. Therefore, I cannot refer to $parent nor include controller definition in ngInclude. If you know how to get around it, please, let me know. Thanks. – jazzblue Sep 16 '15 at 22:43
2

When you use ng-include, Angular creates a new scope, causing your variable to be overwritten to the new scope, instead of the one you wanted. As the new scope is an instance of the original scope (the one you want), you can create an object on CustomRowsCtrl; the objects are copied to the new scope as a reference, enabling you to share the same object in between child and parent scope.

Obs.: You can also use $parent, as suggested on the link below, but using pointers is a lot cleaner and if you use multiple nesting, you won't need to use $parent.$parent and so on.

Example:

On the controller:

$scope.selection = {} 

On the HTML:

ng-model="selection.numLines"

More about ng-include scope: AngularJS - losing scope when using ng-include

Community
  • 1
  • 1
Pedro Moreira
  • 965
  • 5
  • 8
1

It's all about scope creation in Angular.

The directive ng-include create a new scope and you've defined the numLines in the parent scope, i.e the scope of the controller.

If you want to see the changes in your parent scope, you'll have either to write ng-model="$parent.numLines" in the included Html template or simply use the onload attribute of the ng-include directive : onload="numLines = numLines"

matiou
  • 156
  • 1
  • 7
0

ng-include directive creates its new scope, There is so many work round for tackle this problem.

  1. Create your own directive of static include which does not creates its own scope. for example.

    app.directive('staticInclude', ['$http', '$templateCache', '$compile', function ($http, $templateCache, $compile) { return function (scope, element, attrs) { var templatePath = attrs.staticInclude;

        $http.get(templatePath, { cache: $templateCache }).success(function (response) {
            var contents = $('<div/>').html(response).contents();
            element.html(contents);
            $compile(contents)(scope);
        });
    };
    

    }]);

so you can use this directive, its not create own scope.

Your html looks like

    <body ng-app="parserUI">

    <h2>Header</h2>
    <div ng-controller="CustomRowsCtrl">
      <div static-include=="app/partials/structCustomRows.htm"></div>
    </div>  <!-- ng-controller="CustomRowsCtrl" -->

</body>
  1. You include controller in template means your file 'app/partials/structCustomRows.htm' has main div which initialize its relevant controller.
Kashif Mustafa
  • 1,152
  • 6
  • 20