0

いくつかのデータを含むディレクティブがあり、それらをリンクするコントローラーを持たずに、2番目のコンポーネント(ディレクティブまたはその他)の別の場所に補間したいとします。

たとえば、angularjs Webページのzippyを取り上げますが、入力からzippyディレクティブ<div ng-controller="Ctrl3">にデータを入札する代わりに、2つの別個のコンポーネントがあります。

    <!-- first component with data -->
    <div ng-controller="aCtrl">

    Title: <input ng-model="title"> <br>
    Text: <textarea ng-model="text"></textarea>
    </div>

    <hr>
    <!-- a second component wanting to show the data -->
    <div class="zippy" zippy-title="Details: {{title}}...">{{text}}</div>

私の質問は、Angularjsでそれらをうまくリンクするにはどうすればよいですか?

サービスをパススルーしてデータの変更を登録しようとしましたが、ディレクティブへのインジェクションまたはコントローラーを介してサービスをDOMにバインドしようとしましたが失敗しました。

(ディレクティブに含まれるデータを別のディレクティブ「ウィンドウ」に表示したいのですが、データをバインドするためだけにすべてのコードをコントローラーでラップしたくありません)

それをうまく行う方法はありますか?

4

2 に答える 2

0

$rootScopeこれは、でカスタムイベントをトリガーし、ディレクティブのコントローラーでイベントをリッスンするサービスを使用する1つのソリューションです。

app.factory('SharedData',function($rootScope){
    return{
        data:{text : 'World', title:'Foo bar'},
        upDate:function(prop,val){
           this.data[prop]=val;
           $rootScope.$emit('dataUpdate',prop)
        }
    }
});


app.controller('aCtrl', function ($scope,SharedData) {
    angular.forEach(SharedData.data,function(value,key){
        $scope[key] = value;
        $scope.$watch(key,function(){
            SharedData.upDate(key,$scope[key]);
        });
    });
});

app.directive('zippy',function($rootScope,SharedData){
    return{
        restrict:'C',
        replace:false,
        scope:{},
        controller:function($scope) {
            $rootScope.$on('dataUpdate',function(event,prop) {
                $scope[prop] = SharedData.data[prop];
            });
        }
    }
});

プランカーデモ

于 2013-03-24T20:55:10.740 に答える
0

イベントを発行したり、ディレクティブを親コントローラーにラップしたりする以外に、別のオプションがあります(これらのオプションに問題はありません)。もう1つのオプションは、任意のディレクティブコントローラーを登録し、それらの登録済みコントローラーを他の関連または非関連のディレクティブで使用できる汎用サービス/ファクトリを用意することです。

directiveCommunicator以下に、ディレクティブコントローラを取得、設定、および設定解除できるというサービスがあります(必要に応じてファクトリを使用できますが、サービスを使用するのが私の好みです)。foo次に、 andと呼ばれる別の2つbarのディレクティブがあります。これらのfooディレクティブは、使用するコントローラーを登録します。このコントローラーは、ディレクティブによって使用されbarます。fooおよびbarディレクティブは親/子に関連していないことに注意してください

// Service used to register/use any arbitrary controller
app.service('directiveCommunicator',
    function()
    {
        var _controllers = {};

        this.get =
            function(id)
            {
                if (!(id in _controllers)) {
                    return null;
                }

                return _controllers[id];
            };

        this.set =
            function(id, controller)
            {
                _controllers[id] = controller;
            };

        this.unset =
            function(id)
            {
                if (!(id in _controllers)) {
                    return;
                }

                delete _controllers[i];
            }
    }
);

app.directive('foo',
    [
        'directiveCommunicator',
        function(directiveCommunicator)
        {
            return {
                'restrict': 'A',
                'scope':
                    {
                        'colour': '='
                    },
                'controller':
                    function($scope)
                    {
                        // We register out controller with a unique ID so we can use it in other directives
                        directiveCommunicator.set('colourBox', this);

                        // We also unregister it once we get destroyed, otherwise we'll be leaking memory
                        $scope.$on('$destroy',
                            function()
                            {
                                directiveCommunicator.unset('colourBox');
                            }
                        );

                        this.changeColour =
                            function(colour)
                            {
                                $scope.$apply(
                                    function()
                                    {
                                        $scope._colour = colour;
                                    }
                                );
                            }
                    },
                'link':
                    function($scope, $element, $attr)
                    {
                        $scope._colour = $attr.colour;

                        $scope.$watch('_colour',
                            function()
                            {
                                $element.attr('class', $scope._colour);
                            }
                        );
                    }
            }
        }
    ]
);

app.directive('bar',
    [
        'directiveCommunicator',
        function(directiveCommunicator)
        {
            return {
                'restrict': 'A',
                'scope':
                    {
                        'colour': '='
                    },
                'link':
                    function($scope, $element, $attr)
                    {
                        $element.text($attr.colour);

                        $element.bind('click',
                            function()
                            {
                                // We get the registered controller and call the 'changeColour' method on it
                                var ctrl = directiveCommunicator.get('colourBox');

                                ctrl.changeColour($attr.colour);
                            }
                        );
                    }
            }
        }
    ]
);

Plunkerのデモを少し作成して、実際に見fooてみbarました。ディレクティブは、foo関連するコントローラーの背景を変更できる小さな正方形のdivです。は、のコントローラーメソッドを呼び出し、指定された属性に基づいて色を変更する、bar関連のない別のディレクティブです。foochangeColour

まだ本番環境でこのセットアップを使用しておらず、コントローラーの登録解除も処理する必要がありますが、機能するはずです。また、メソッドの3番目の引数をコントローラーのスコープにすることもできます。この引数は、directiveCommunicator.setメソッドが$ destroy / unregisterセットアップに自動的に追加するため、これ以上呼び出す必要はありdirectiveCommunicator.unsetません。

于 2015-08-20T11:16:36.150 に答える