0

I have a reusable template called profile.html. It looks something like this:

<div>
  {{firstName}}

</div>

I have it embedded in another template which is bound to a dedicated controller:

<div ng-include src="'templates/profile.html'"></div>

I want a child $scope created for this div. In the controller for the parent template, I have something like:

$scope.profile = theProfile;

I want the child scope for the profile.html template to be the parent $scope.profile. Something akin to:

<div ng-include src="'templates/profile.html'" ng-scope="{{profile}}"></div>

How can I do this?

2
  • 1
    Why don't you just write {{profile.firstName}}? Commented Apr 14, 2015 at 17:44
  • You can't transform an arbitrary object into a scope. Commented Apr 14, 2015 at 17:59

2 Answers 2

1

It looks like you're basically reinventing directives, by trying to set both the template and scope like that. Also, $scope is an object with a large amount of other properties/objects on it, so setting it to a be another object would be... problematic.

The following would create a directive that merges a passed in profile to the $scope using angular copy, if you really want to do it that way. I'd recommend just using a $scope.profile, though.

.directive('profile', [function(){
    return{
        templateUrl:'templates/profile.html',
        scope:{profile:'='},
        controller: function($scope){
            angular.copy($scope.profile, $scope) // if you really, really want the properties right on the scope.

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

2 Comments

It seems tightly coupled that every place that ng-includes profile.html must have a property "profile" on its controller, no?
Indeed, which is why a directive is a much better solution for this. In general, I've found ng-include to be rarely useful, mostly just for getting around recursive directive issues. If you want a "profile" component that has both a template and a scope associated with it, that's exactly the problem a directive is designed to solve.
1

ngInclude automatically creates a child scope. You shouldn't need to explicitly pass some data to it since it can access its parent scope via prototypical inheritance (this might become a problem if your template changes the scope).

The problem here is that your template expects a firstName property to exist in the scope, but it doesn't. So you could change your template to

<div>
  {{profile.firstName}}
</div>

but that would couple the template to the profile object, which might be a bad idea.

Another solution would be to manually create the firstName property in the correct scope:

<div ng-include src="'templates/profile.html'" 
     ng-init="firstName=profile.firstName">
</div>

I'm not very fond of this solution, though, because it can easily get out of hand if the template needs more properties and it breaks the template encapsulation to some extent.

And finally, you could wrap that template within a directive:

directive('whateverMakesSense', function() {
    return {
        restrict: 'E',
        template: '<div>{{data.firstName}}</div>',
        scope: { data: '=' }        
    };
});

...

<whatever-makes-sense data="profile"></whatever-makes-sense>

If you find yourself using that template in many places, I suggest you go for the custom directive approach. It will give you more control, things will be better encapsulated and as a bonus your markup will be more semantic - if you use anything but whatever-makes-sense, of course. :)

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.