-2

カスタム ディレクティブを作成しており、jQuery に依存しないようにしようとしています。jQuery を使用せずにこれを行うには、スコープ (親と子) が直接対話する必要がある場合があります。私は確かに「悪い習慣」をできるだけ避けたいので、私の質問は次のとおりです。

子スコープで親スコープの関数を直接呼び出すのは悪い習慣ですか? もしそうなら、スコープを管理するコントローラーまたは要素を取得する方法はありますか?

これが必要な理由は、ディレクティブのネストされたスコープが複数存在する可能性があるためです。そして、必ずしも現在のスコープの直接の親ではない非常に特定のものにアクセスする必要があります (それは祖先ですが)。

編集:ユースケースの詳細

モジュールには 2 つのディレクティブが含まれています。いずれも、任意の数の親ディレクティブにネストできます。この子ディレクティブはそれに応じて親ディレクティブを必要としますが、ネストされた親の場合、最も近い親のコントローラーのみを取得します。

通常、これは次のように使用されます。

<element parent-attr-dir="val">
    <element child-attr-dir="val"></element>
</element>

属性の値が一致する必要があることに注意してください。これは、どの「祖先」にアタッチするかを決定するものです。

高度な使用法は次のようになります。

<element parent-attr-dir="value1">
    <element parent-attr-dir="value2">
        <element child-attr-dir="value1">Will run on top most ancestor</element>
        <element child-attr-dir="value2">Will run on immediate parent</element>
    </element>
    <element parent-attr-dir="value3">
        <element child-attr-dir="value3">Will run on immediate parent</element>
        <element child-attr-dir="value1">Will run on top most ancestor</element>
    </element>
    <element child-attr-dir="val">Will not run!!</element>
</element>

編集:問題の解決策

これは機能しますが、悪いかどうかを知る必要があります。

var _p = scope;
while (_p !== null) {
    if (_p.doSomething 
    &&  /* some other criteria. */ ) {
        _p.doSomething(scope);
    }
    _p = _p.$parent;
}

編集:jQueryを使用したソリューション

これは機能しますが、jQLite には親 (セレクター) がなく、親 () だけがあるため、jQuery が必要です。

$(element).parents('[attrname=value]').controller('moduleName').funcName()
4

1 に答える 1

2

1 つの解決策は、子に親ディレクティブを要求し、親にオプションで親ディレクティブを要求することです。次に、子は直接の親コントローラーのメソッドを呼び出し、基準値を渡します。親コントローラーが基準を満たさない場合は、呼び出しを独自の親 (存在する場合) に転送するか、何も起こりません。ソリューションのスケッチ:

app.directive("parentAttrDir", function() {
    return {
        require: ["?^parentAttrDir","parentAttrDir"],
        link: function(scope,elem,attrs,controllers) {
            var parentAttrDir = controllers[0],
                thisController = controllers[1],
                criterion = attrs.parentAttrDir;
            thisController.parent = parentAttrDir;
            thisController.criterion = criterion;
        },
        controller: function($scope) {
            this.doSomething = function(data,criterion) {
                if( this.criterion === criterion ) {
                    // actually do something with the data
                }
                else if( this.parent != null ) {
                    return this.parent.doSomething(data,criterion);
                }
            };
        }
    };
});

app.directive("childAttrDir", function() {
    return {
        require: "^parentAttrDir",
        link: function(scope,elem,attrs,parentAttrDir) {
            var criterion = attrs.childAttrDir;
            // EXAMPLE USAGE FROM CHILD
            scope.doSomeAction = function(data) {
                parentAttrDir.doSomething(data,criterion);
            };
        }
    };
});
于 2013-10-16T14:33:21.230 に答える