web-dev-qa-db-fra.com

Comment spécifier un modèle pour une directive ngInclude dans AngularJS?

Je voudrais utiliser le même modèle HTML à 3 endroits, juste à chaque fois avec un modèle différent. Je sais que je peux accéder aux variables à partir du modèle, mais les noms seront différents.

Existe-t-il un moyen de passer un modèle à ngInclude?

C'est ce que j'aimerais réaliser, bien sûr l'attribut add-variable ne fonctionne pas maintenant. Ensuite, dans mon modèle inclus, j'accéderais à detailsObject et à ses propriétés.

<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>

Si j'ai adopté une mauvaise approche en utilisant ng-include, y a-t-il autre chose que je devrais essayer?

44
Tomas Grosup

REMARQUE: ce n'est pas ma réponse d'origine, mais voici comment je procéderais après avoir utilisé angular pour un peu.

Je créerais une directive avec le modèle html comme balisage passant dans les données dynamiques à la directive comme vu dans ce violon .

Étapes/notes pour cet exemple:

  1. Définissez une directive avec un balisage dans le templateUrl et les attributs utilisés pour transmettre les données à la directive (nommée type dans cet exemple).
  2. Utilisez les données de directive dans le modèle (nommé type dans cet exemple).
  3. Lorsque vous utilisez la directive dans le balisage, assurez-vous de transmettre les données de la portée du contrôleur à la directive (<address-form type="billing"></address-form> (où la facturation accède à un objet sur la portée du contrôleur).
  4. Notez que lors de la définition d'une directive, le nom est encadré de chameau, mais lorsqu'il est utilisé dans le balisage, il est délimité par des tirets minuscules (c'est-à-dire qu'il est nommé addressForm dans le js mais address-form en html). Plus d'informations à ce sujet peuvent être trouvées dans les documents angular ici .

Voici le 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' };
});

Avec balisage:

<div ng-controller="MyCtrl">
    <address-form type="billing"></address-form>
    <address-form type="delivery"></address-form>
</div>

RÉPONSE ORIGINALE (ce qui est complètement différent de l'utilisation d'une directive BTW).

Remarque: Le violon de ma réponse originale ci-dessous ne semble plus fonctionner en raison d'une erreur (mais le garder ici au cas où il serait toujours utile)

Il y a eu une discussion à ce sujet sur le groupe Google, vous pouvez voir ici .

Il semble que cette fonctionnalité ne soit pas prise en charge, mais vous pouvez utiliser le correctif de Brice comme décrit dans ce message .

Voici l'exemple de code de son 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>
20
Gloopy

Il existe une solution assez simple, même si je dois admettre que ce n'est pas ce que Misko recommanderait. Mais si la création d'une directive est une exagération pour vous et que l'obtention du correctif de Brice n'est pas possible, alors ce qui suit vous aidera.

<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>

Il est assez évident pourquoi cela fonctionne. Voir un exemple ici: http://jsfiddle.net/Cndc6/4/

61
Denis Pshenov

Il y a un pull pour résoudre ce problème, mais il semble qu'il soit mort: https://github.com/angular/angular.js/pull/1227

Sans modifier le code source Angular cela résoudra le problème d'une manière réutilisable et pas trop hacky:

directive('newScope', function() {
    return {
        scope: true,
        priority: 450,
    };
});

Et un exemple:

<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>

En voici un Plunker en action: http://plnkr.co/edit/El8bIm8ta97MNRglfl3n

14
John Culviner
<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);
                }
            };
        }
    };
});

Il s'agit d'une directive qui combine new-scope de réponse de John Culviner avec le code de Angular ng-init.

Pour être complet, il s'agit de Angular 1.2 26 ng-init source , vous pouvez voir que le seul changement dans la directive new-scope est l'ajout de scope: true

{
  priority: 450,
  compile: function() {
    return {
      pre: function(scope, element, attrs) {
        scope.$eval(attrs.ngInit);
      }
    };
  }
}
6
Ande

Solution Quick'n'dirty:

<div ng-init="details=document||language||projectSummary.ProjectResults">
5
Tomas Grosup

Je t'entends! ng-include n'est pas réutilisable car il a accès à la portée globale. C'est un peu bizarre.

Il devrait y avoir un moyen de définir des variables locales. tiliser une nouvelle directive au lieu de ng-include est une solution plus propre.

L'utilisation idéale ressemble à:

<div ng-include-template="'Partials/SummaryDetails.html'" ng-include-variables="{ 'detailsObject': language }"></div>

La directive est:

.directive(
  'ngIncludeTemplate'
  () ->
    {
      templateUrl: (elem, attrs) -> attrs.ngIncludeTemplate
      restrict: 'A'
      scope: {
        'ngIncludeVariables': '&'
      }
      link: (scope, elem, attrs) ->
        vars = scope.ngIncludeVariables()
        for key, value of vars
          scope[key] = value
    }
)

Vous pouvez voir que la directive n'utilise pas la portée globale. Au lieu de cela, il lit l'objet à partir de ng-include-variables et ajoute ces membres à sa propre portée locale.

C'est propre et générique.

1
Tanin