1. ホーム
  2. angularjs

[解決済み] AngularJSで独自のスコープ*を持つカスタムディレクティブ内から親スコープにアクセスするにはどうすればよいですか?

2022-03-26 14:28:28

質問

ディレクティブ内の "parent"スコープにアクセスする方法を探しています。 スコープ、transclude、require、変数(またはスコープ自体)を上から渡すなど、どのような組み合わせでもかまいません。 しかし、完全にハチャメチャなものやメンテナンス不可能なものは避けたいのです。 例えば、今すぐできることとして $scope を反復処理する。 $sibling のスコープから概念的な "parent"を探します。

私が本当に欲しいのは、次のようなものです。 $watch を親スコープで表現することができます。 それができれば、こっちでやろうとしていることが実現できる。 AngularJS - 変数で部分的にレンダリングする方法は?

重要な注意事項 は、ディレクティブが同じ親スコープ内で再利用可能でなければならないことです。 そのため、デフォルトの動作 (scope: false) ではうまくいきません。 私はディレクティブのインスタンスごとに個別のスコープが必要で、そのためには $watch を親スコープに存在する変数に変換します。

コードサンプルは1000字の価値がありますから。

app.directive('watchingMyParentScope', function() {
    return {
        require: /* ? */,
        scope: /* ? */,
        transclude: /* ? */,
        controller: /* ? */,
        compile: function(el,attr,trans) {
            // Can I get the $parent from the transclusion function somehow?
            return {
                pre: function($s, $e, $a, parentControl) {
                    // Can I get the $parent from the parent controller?
                    // By setting this.$scope = $scope from within that controller?

                    // Can I get the $parent from the current $scope?

                    // Can I pass the $parent scope in as an attribute and define
                    // it as part of this directive's scope definition?

                    // What don't I understand about how directives work and
                    // how their scope is related to their parent?
                },
                post: function($s, $e, $a, parentControl) {
                    // Has my situation improved by the time the postLink is called?
                }
            }
        }
    };
});

解決方法は?

参照 AngularJSのスコーププロトタイピング/プロトタイピング継承のニュアンスを教えてください。

要約すると、ディレクティブがその親にアクセスする方法 ( $parent ) のスコープは、そのディレクティブが作成するスコープの種類に依存します。

  1. デフォルト( scope: false ) - ディレクティブは新しいスコープを作らないので、ここでは継承はありません。 ディレクティブのスコープは、親/コンテナと同じスコープになります。 リンク関数では、最初のパラメータ (通常は scope ).

  2. scope: true - ディレクティブは、親スコープをプロトタイプ的に継承した新しい子スコープを作成します。 親スコープで定義されたプロパティは、ディレクティブが使用できるようになります。 scope (プロトタイプ継承のため)。 ただ、プリミティブスコープのプロパティに書き込むと、ディレクティブスコープに新しいプロパティが作成されます(同じ名前の親スコープのプロパティは隠されたり、影になったりします)。

  3. scope: { ... } - ディレクティブは、新しい分離/隔離されたスコープを作成します。 これはプロトタイプ的に親スコープを継承するものではありません。 親スコープにアクセスするには $parent しかし、これは通常推奨されません。 代わりに、ディレクティブが使用されるのと同じ要素で、どの親スコープのプロパティ (や関数) を必要とするかを = , @ および & という表記があります。

  4. transclude: true - ディレクティブは、新しい "transcluded" の子スコープを作成し、それはプロトタイプ的に親スコープから継承されます。 ディレクティブが分離スコープも作成する場合、transcluded と分離スコープは兄弟になります。 ディレクティブが $parent プロパティは、同じ親スコープを参照しています。

    Angular v1.3アップデート : ディレクティブが孤立したスコープも作成する場合、トランスクルードされたスコープは孤立したスコープの子として扱われるようになりました。 transcluded スコープと isolate スコープは兄弟ではなくなりました。 また $parent プロパティは、分離されたスコープを参照するようになりました。

上記リンクに4種類すべての例と写真があります。

ディレクティブのコンパイル関数でスコープにアクセスすることはできません(ここに書いてある通りです。 https://github.com/angular/angular.js/wiki/Dev-Guide:-Understanding-Directives ). ディレクティブのスコープにアクセスできるのは、リンク関数内です。

見ている。

上記1.と2.について: 通常、ディレクティブが必要とする親プロパティを属性で指定し、それを $watch します。

<div my-dir attr1="prop1"></div>

scope.$watch(attrs.attr1, function() { ... });

オブジェクトのプロパティを監視している場合は、$parse を使用する必要があります。

<div my-dir attr2="obj.prop2"></div>

var model = $parse(attrs.attr2);
scope.$watch(model, function() { ... });

上記3.(スコープの分離)については、ディレクティブのプロパティにつける名前に注意して @ または = という表記があります。

<div my-dir attr3="{{prop3}}" attr4="obj.prop4"></div>

scope: {
  localName3: '@attr3',
  attr4:      '='  // here, using the same name as the attribute
},
link: function(scope, element, attrs) {
   scope.$watch('localName3', function() { ... });
   scope.$watch('attr4',      function() { ... });