55 votes

Confus au sujet de Angularjs transcluded et d'isoler les étendues et les liaisons

J'ai du mal à comprendre la portée de modèles et de leurs liaisons dans le respect des directives qui ont une portée limitée.

Je reçois que le fait de restreindre le champ d'application d'une directive signifie que contrôleur.$la portée et de la directive.la portée n'est plus la même chose. Cependant, je suis confus au sujet de la façon dont la mise de modèles au sein de la directive modèle ou dans le html affecte la liaison de données. Je sens que je vais manquer de quelque chose de fondamental et de passer j'ai besoin de comprendre cela.

Prenez le code suivant (violon ici: http://jsfiddle.net/2ams6/)

JavaScript

var app = angular.module('app',[]);
app.controller('Ctrl',function($scope){
});
app.directive('testel', function(){
    return {
        restrict: 'E',
        scope: {
            title: '@'
        },
        transclude: true,
        template:   '<div ng-transclude>'+
                    '<h3>Template title: {{title}}</h3>' +
                    '<h3>Template data.title:{{data.title}}</h3>' +
                    '</div>'
    }    
}); 

HTML

<div ng-app='app'>
    <div ng-controller="Ctrl">
        <input ng-model="data.title">
        <testel title="{{data.title}}">
            <h3>Transclude title:{{title}}</span></h3>
            <h3>Transclude data.title:{{data.title}}</h3>
        </testel>
    </div>
</div>

Le modèle met à jour uniquement {{title}} dans le modèle, et {{data.title}} dans la transclusion. Pourquoi ne pas {{title}} dans la transclusion, ni {{data.title}} dans le modèle?

Déplacement de l'entrée à l'intérieur de la transclusion comme (violon ici: http://jsfiddle.net/eV8q8/1/):

<div ng-controller="Ctrl">
    <testel title="{{data.title}}">
        <input ng-model="data.title">
         <h3>Transclude title: <span style="color:red">{{title}}</span></h3>

         <h3>Transclude data.title: <span style="color:red">{{data.title}}</span></h3>

    </testel>
</div>

maintenant signifie seulement transclude {{data:title}} est mis à jour. Pourquoi pas non plus de modèle {{title}} ou {{data.title}}, ni transclude {{title}}?

Et enfin, le déplacement de l'entrée à l'intérieur du modèle, comme (violon ici: http://jsfiddle.net/4ngmf/2/):

template: '<div ng-transclude>' +
            '<input ng-model="data.title" />' +
            '<h3>Template title: {{title}}</h3>' +
            '<h3>Template data.title: {{data.title}}</h3>' +
            '</div>'

Maintenant signifie que seul modèle {{data.title}} est mis à jour. Encore une fois, pourquoi ne pas les 3 autres liaisons?

J'espère qu'il y est quelque chose d'évident me regarder en face et je suis absent. Si vous me l'avoir, je vais vous acheter une bière, ou de vous donner quelques points, ou quelque autre chose. Merci beaucoup.

113voto

Mark Rajcok Points 85912

Vos violons de créer trois portées:

  1. un champ d'application associés avec le contrôleur Ctrl, en raison d' ng-controller
  2. une directive transcluded portée, en raison de l' transclude: true
  3. une directive isoler portée, en raison de l' scope: { ... }

Dans fiddle1, avant de nous taper quoi que ce soit dans la zone de texte nous avons les éléments suivants:

enter image description here

Portée 003 est le champ d'application associés avec le contrôleur. Puisque nous n'avons pas de type dans la zone de texte encore, il n'y a pas d' data de la propriété. En isoler portée 004, nous voyons qu'un title de la propriété a été créé, mais il est vide. Il est vide parce que le parent n'a pas un data.title bien encore.

Après avoir tapé my title dans la zone de texte, nous avons maintenant:

enter image description here

Contrôleur de portée 003 a maintenant un nouveau data propriété de l'objet (c'est pourquoi il est de couleur jaune), qui a un title bien maintenant réglé my title. Depuis isoler le champ d'application de la propriété title est un moyen lié aux données de la valeur interpolée de data.title, il obtient également la valeur my title (la valeur est de couleur jaune, car il a changé).

Le transcluded portée fait hérite de la manette de la portée, de sorte que l'intérieur de la transcluded HTML, angulaire pouvez suivre la chaîne de prototype et de trouver $scope.data.title de la portée parent (mais $scope.title il n'y existe pas).

L'isolat de la portée n'a accès qu'à ses propres propriétés, ainsi que les biens title.

Dans fiddle2, avant de taper, nous avons la même image que dans fiddle1.

Après avoir tapé my title:

enter image description here

D'où le nouveau data.title des biens ont montré, sur la transcluded portée. L'isolat champ d'application est toujours à la recherche d' data.title sur le contrôleur de portée, mais ce n'est pas là cette fois, de sorte que son title la valeur de la propriété reste vide.

Dans fiddle3, avant de taper, nous avons la même image que dans fiddle1.

Après avoir tapé my title:

enter image description here

D'où le nouveau data.title des biens ont montré, sur l'isoler de la portée. Aucun des autres étendues d'avoir accès à l'isoler de la portée, de sorte que la chaîne de caractères my title n'apparaissent pas n'importe où ailleurs.

22voto

dewd Points 891

Après avoir lu toutes les réponses, y compris la Marque du fantastique schémas, c'est ma compréhension de la portée et de l'héritage par ma question. J'aimerais avoir des commentaires sur où ce schéma tombe, afin que je puisse mettre à jour de façon appropriée. J'espère qu'il fournit simplement à un point de vue différent de ce que Mark a présenté:

Scope inheritance

8voto

Roy Truelove Points 6532

Bien demandé, btw! Espère que ma réponse est aussi éloquent..

La réponse a à voir avec la façon dont transcluded éléments sont à leur portée.

Pour résumer, vous avez deux périmètres:

  1. Le contrôleur du champ d'application, qui a $scope.data.title. (Ajouté implicitement par votre input élément)
  2. Du champ de la directive, qui a $scope.title.

Lorsque vous changez le contrôleur $scope.data.title, de la directive - $scope.title également des changements.

Vous avez aussi deux sections de HTML, le transcluded et le modèle. Ce qui se passe est que le transcluded HTML est dans le contrôleur de la portée, et le modèle HTML est dans le cadre de la directive portée. Ainsi, le transcluded HTML ne sais rien à propos de title, et le modèle de champ ne sais rien à propos de data.title

C'est en fait exactement ce que Transclusion a été prévu pour les - de permettre à l'enfant les éléments d'une directive garder leur parent, dans ce cas, le contrôleur de la portée. De par sa conception, transcluded éléments ne sais pas qui leur à une directive, et donc n'ont pas accès à du champ de la directive.

La Directive de modèles, d'autre part, n'aura accès qu'à du champ de la directive.

J'ai modifié ton code un peu pour les noms un peu plus clair (même fonctionnalité, tout de même)

http://jsfiddle.net/yWWVs/2/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X