21

I've this routes.

// index.html
<div ng-controller="mainCtrl">
    <a href='#/one'>One</a>
    <a href='#/two'>Two</a>
</div>​​​​​​​​​
<div ng-view></div>

And this is how I'm loading the partials into my ng-view.

// app.js
​var App = angular.module('app', []);​​​​​​​
App.config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/one', {template: 'partials/one.html', controller: App.oneCtrl});
    $routeProvider.when('/two', {template: 'partials/two.html', controller: App.twoCtrl});
  }]);

When I click the links, it shows me the appropriate markup inside the ng-view. But when I try to include partials/two.html inside partials/one.html using ng-include, it shows it properly but creates a different scope so I'm not able to interact with it.

// partials/two.html - markup
<div ng-controller="twoCtrl">I'm a heading of Two</div>

// partials/one.html - markup
<div ng-controller="oneCtrl">I'm a heading of One</div>
<div ng-include src="'partials/two.html'"></div>

​ How do I resolve this problem? Or Is there any other way to achieve the same result?

temporary_user_name
  • 35,956
  • 47
  • 141
  • 220
codef0rmer
  • 10,284
  • 9
  • 53
  • 76

4 Answers4

70

You can write your own include directive that does not create a new scope. For example:

MyDirectives.directive('staticInclude', function($http, $templateCache, $compile) {
    return function(scope, element, attrs) {
        var templatePath = attrs.staticInclude;
        $http.get(templatePath, { cache: $templateCache }).success(function(response) {
            var contents = element.html(response).contents();
            $compile(contents)(scope);
        });
    };
});

You can use this like:

<div static-include="my/file.html"></div>
Hongli
  • 18,682
  • 15
  • 79
  • 107
Marius
  • 964
  • 9
  • 12
  • What does `$compile(contents)(scope);` do ? , pls – vimal1083 Aug 04 '14 at 09:26
  • 1
    @Vimal $compile runs the compiler which compiles an HTML string or DOM into a template and produces a template function, which can then be used to link scope and the template together. In essence, it takes in HTML, reads it for angularJS directives, sets them up, and then links them to the scope (the (scope) at the end). It's what "compiles" all those lovely directive attributes, bindings, etc. from HTML into functioning Javascript. [Read about the compiler in the docs](https://docs.angularjs.org/api/ng/service/$compile) – Colton McCormack Aug 05 '14 at 20:48
  • 5
    If you want to pass expressions to the staticInclude directive in this example, you need to change "attrs.staticInclude" to "scope.$eval(attrs.staticInclude)". This will evaluate the expression within the scope so you can have a dynamic path (i.e. includes in ng-repeat blocks) – Sean Dawson Oct 21 '14 at 14:49
  • 1
    @NoxHarmonium, `$sce.parseAsResourceUrl(attrs.staticInclude)(scope)` or `scope.$eval(attrs.staticInclude)` - which is more proper? – happy_marmoset Dec 31 '14 at 19:56
5

The documentation for ngInclude states "This directive creates new scope." so this is by design.

Depending on the type of interaction you are looking for you may want to take a look at this post for one way to share data/functionality between the two controllers via a custom service.

Community
  • 1
  • 1
Gloopy
  • 37,767
  • 15
  • 103
  • 71
  • 2
    The scope this directive creates is inherited from parent scope, which means you are allowed to access and modify properties/methods from the parent scope. – Umur Kontacı Sep 15 '12 at 12:20
  • Umur, how do you access properties/methods of the child scope from its parent? – cayblood Mar 20 '14 at 18:28
5

So this isn't an answer to this question but i made it here looking for something similar and hopefully this will help others.

This directive will include a partial without creating a new scope. For an example you can create a form in the partial and control that form from the parent controller.

Here is a link to the Repo that i created for it.

good luck :-)

-James Harrington

James Harrington
  • 3,138
  • 30
  • 32
  • 1
    This is exactly what I was looking for. Thank you. Preventing the form from getting it's own scope and allowing the parent controller access to form data. – Tyguy7 Jan 19 '15 at 07:23
4

You can actually do this without using a shared service. $scope.$emit(...) can dispatch events to the $rootScope, which can listen for them and rebroadcast to the child scopes.

Demo: http://jsfiddle.net/VxafF/

Reference: http://www.youtube.com/watch?v=1OALSkJGsRw (see the first comment)

codef0rmer
  • 10,284
  • 9
  • 53
  • 76