I would like to use the same HTML template in 3 places, just each time with a different model. I know I can access the variables from the template, but there names will be different.
Is there a way to pass a model to the ngInclude?
This is what I would like to achieve, of course the attribute add-variable does not work now. Then in my included template, I would acces the detailsObject and its properties.
<pane title="{{projectSummary.ProjectResults.DisplayName}}">
<h2>{{projectSummary.ProjectResults.DisplayName}}</h2>
<ng-include src="'Partials/SummaryDetails.html'" init-variable="{'detailsObject': projectSummary.ProjectResults}"></ng-include>
</pane>
<pane title="Documents" header="true"></pane>
<pane ng-repeat="document in projectSummary.DocumentResults" title="{{document.DisplayName}}">
<h2>{{document.DisplayName}}</h2>
<ng-include src="'Partials/SummaryDetails.html'" add-variable="{'detailsObject': document}"></ng-include>
</pane>
<pane ng-repeat="header in [1]" title="Languages" header="true"></pane>
<pane ng-repeat="language in projectSummary.ResultsByLanguagePairs" title="{{language.DisplayName}}">
<h2>{{document.DisplayName}}</h2>
<ng-include src="'Partials/SummaryDetails.html'" add-variable="{'detailsObject': language}"></ng-include>
</pane>
If I took a bad approach with using ng-include, is there something else I should try?
There is a rather simple solution, although I must admit, it's not what Misko would recommend. But if creating a directive is an overkill for you and getting Brice's patch is not feasible then the following will help you.
<div ng-repeat="name in ['A']" ng-include="'partial.html'"></div>
<div ng-repeat="name in ['B']" ng-include="'partial.html'"></div>
<script type="text/ng-template" id="partial.html">
<div>{{ name }}</div>
</script>
It's quite evident why it works. See an example here: http://jsfiddle.net/Cndc6/4/
NOTE: this is not my original answer but this is how I'd do this after using angular for a bit.
I would create a directive with the html template as the markup passing in the dynamic data to the directive as seen in this fiddle.
Steps/notes for this example:
templateUrl
and attribute(s) used to pass data into the directive (named type
in this example). type
in this example).<address-form type="billing"></address-form>
(where billing is accessing an object on the controller scope).addressForm
in the js but address-form
in the html). More info on this can be found in the angular docs here.Here is the js:
var myApp = angular.module('myApp',[]);
angular.module('myApp').directive('addressForm', function() {
return {
restrict: 'E',
templateUrl: 'partials/addressform.html', // markup for template
scope: {
type: '=' // allows data to be passed into directive from controller scope
}
};
});
angular.module('myApp').controller('MyCtrl', function($scope) {
// sample objects in the controller scope that gets passed to the directive
$scope.billing = { type: 'billing type', value: 'abc' };
$scope.delivery = { type: 'delivery type', value: 'def' };
});
With markup:
<div ng-controller="MyCtrl">
<address-form type="billing"></address-form>
<address-form type="delivery"></address-form>
</div>
ORIGINAL ANSWER (which is completely different than using a directive BTW).
Note: The fiddle from my original answer below doesn't appear to work anymore due to an error (but keeping it here in case it is still useful)
There was a discussion about this on the Google Group you can see it here.
It looks like this functionality is not supported out of the box but you can use Brice's patch as described in this post.
Here is the sample code from his jsfiddle:
<script id="partials/addressform.html" type="text/ng-template">
partial of type {{type}}<br>
</script>
<div ng-controller="MyCtrl">
<ng-include src="'partials/addressform.html'" onInclude="type='billing'"></ng-include>
<ng-include src="'partials/addressform.html'" onLoad="type='delivery'"></ng-include>
</div>
There is a pull to fix this but it looks like it's dead: https://github.com/angular/angular.js/pull/1227
Without modifying the Angular source code this will solve the problem in a reusable not-too-hacky-feeling way:
directive('newScope', function() {
return {
scope: true,
priority: 450,
};
});
And an example:
<div new-scope ng-init="myVar = 'one instance'" ng-include="'template.html'"></div>
<div new-scope ng-init="myVar = 'another instance'" ng-include="'template.html'"></div>
Here is a Plunker of it in action: http://plnkr.co/edit/El8bIm8ta97MNRglfl3n
Quick'n'dirty solution:
<div ng-init="details=document||language||projectSummary.ProjectResults">
<div new-scope="myVar = 'one instance'" ng-include="'template.html'"></div>
directive('newScope', function () {
return {
scope: true,
priority: 450,
compile: function () {
return {
pre: function (scope, element, attrs) {
scope.$eval(attrs.newScope);
}
};
}
};
});
This is a directive that combines new-scope
from John Culviner's answer with code from Angular's ng-init
.
For completeness, this is the Angular 1.2 26 ng-init source, you can see the only change in the new-scope directive is the addition of scope: true
{
priority: 450,
compile: function() {
return {
pre: function(scope, element, attrs) {
scope.$eval(attrs.ngInit);
}
};
}
}