Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular passing scope to ng-include

I have a controller that I wrote that I use in multiple places in my app with ng-include and ng-repeat, like this:

<div   ng-repeat="item in items"   ng-include="'item.html'"   ng-controller="ItemController" ></div> 

In the controller/template, I expect the item value to exist, and the whole thing is built around this idea. Now, though, I need to use the controller in a slightly different way, without the ng-repeat, but still need to be able to pass in an item. I saw ng-init and thought it could do what I needed, like this:

<div   ng-init="item = leftItem"   ng-include="'item.html'"   ng-controller="ItemController" ></div> <div   ng-init="item = rightItem"   ng-include="'item.html'"   ng-controller="ItemController" ></div> 

But that does not seem to be working. Anyone have any ideas how I can pass in a variable for scope in a singular instance like this?

Edit: The controller above this is loading in the leftItem and rightItem values, something like this:

.controller('MainController', function($scope, ItemModel) {     ItemModel.loadItems()         .then(function(items) {             $scope.$apply(function() {                 $scope.leftItem = items.left;                 $scope.rightItem = items.right;             });         }); }); 
like image 889
kbjr Avatar asked Sep 05 '14 04:09

kbjr


People also ask

Does Ng-include create a new scope?

In this case, where you need to load templates from other domains or other protocols, then you can add them to your trusted resource URL list, which will set the url as a trusted url in your application. The ng-include directive is executed at priority level -400 and creates new scope every time it is invoked.

What is required with Ng-include directive?

The ng-include directive includes HTML from an external file. The included content will be included as childnodes of the specified element. The value of the ng-include attribute can also be an expression, returning a filename. By default, the included file must be located on the same domain as the document.

Does ng repeat create a new scope?

Directives that Create Scopes In most cases, directives and scopes interact but do not create new instances of scope. However, some directives, such as ng-controller and ng-repeat, create new child scopes and attach the child scope to the corresponding DOM element.

What is ngInit?

The ngInit directive allows you to evaluate an expression in the current scope. This directive can be abused to add unnecessary amounts of logic into your templates. There are only a few appropriate uses of ngInit : aliasing special properties of ngRepeat , as seen in the demo below.


2 Answers

Late to the party, but there is a little angular 'hack' to achieve this without implementing a dumb directive.

Adding a built-in directive that will extend your controller's scope (like ng-if) everywhere you use the ng-include will actually let you isolate the variable name for all the included scopes.

So:

<div ng-include="'item.html'"   ng-if="true"   onload="item = rightItem"> </div> <div ng-include="'item.html'"   ng-if="true"   onload="item = leftItem"> </div> 

You can then bind your template item.html to the item variable several times with different items.

Here is a plunker to achieve what you want

The problem was the item keeps changing in the controller scope that only holds one reference to item variable which is erased at each onload instruction.

Introducing a directive that extends the current scope, lets you have a isolated scope for all the ng-include. As a consequence the item reference is preserved and unique in all extended scope.

like image 178
Piou Avatar answered Sep 23 '22 16:09

Piou


You can use the onload attribute that ngInclude provides to do this:

<div ng-include="'item.html'"      ng-controller="ItemController"      onload="item = rightItem"> </div> 

Link to the documentation.

EDIT

Try doing something like this in the parent scope:

$scope.dataHolder = {}; 

Then when the asynchronous data is received, store the data on dataHolder:

$scope.dataHolder.leftItem = items.leftItem; $scope.dataHolder.rightItem = items.rightItem; 

Now when ng-include loads the template, it will create a child scope that inherits the properties of the parent. So $scope.dataHolder will be defined in this child scope (initially as an empty object). But when your asynchronous data is received, the reference to the empty object should then contain the newly received data.

like image 24
Sunil D. Avatar answered Sep 22 '22 16:09

Sunil D.