Angular-styleguide: 親コントローラーのプロパティにアクセスするためのグッドプラクティス

作成日 2015年07月28日  ·  13コメント  ·  ソース: johnpapa/angular-styleguide

controllerAs構文を使用して、親コントローラーの単純なプロパティにアクセス/変更するための良い方法は何ですか? 以下の例をご覧ください。 $scope.$parent.parent経由でアクセスするのは好きではありません。 このような些細なロジックのサービスを作成せずに、どのようにして同様の状況に対処しますか。

<div ng-controller="Parent as parent">

  <div ng-if="parent.showMessage">
    Some simple message.
  </div>

  <div ng-controller="ChildOne as childOne"></div>

</div>
app.controller('Parent', function () {
    var self = this;
    self.showMessage = true;
});

app.controller('ChildOne', function ($scope) {
    var self = this;
    self.foo = 'bar';
    // Some simple logic.
    if (self.foo === 'bar') {
        $scope.$parent.parent.showMessage = false;
    }
});
question

最も参考になるコメント

よりコンポーネント指向のアプローチを使用する:

<html ng-app="myApp">
  <body>
    <div ng-controller="ParentCtrl as vm">
      <my-directive on-foo-eq-bar="vm.updateMessage(msg)"></my-directive>
    </div>

    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
    <script>
      angular.module('myApp', [])
        .controller('ParentCtrl', function($window) {
          var vm = this;
          vm.updateMessage = function(msg) {
            $window.alert(msg);
          };
        })
        .directive('myDirective', function() {
          return {
            scope: {
              onFooEqBar:'&'
            },
            controllerAs:'vm',
            controller: function($scope) {
              var self = this;
              self.foo = 'bar';
              // Some simple logic.
              if (self.foo === 'bar') {
                $scope.onFooEqBar({msg: false});
              }
            }
          };
        });
    </script>
  </body>
</html>

全てのコメント13件

実際の例を挙げていただけますか? 親が子コントローラーが使用/変更するオブジェクトをすでに知っていて、data-ng-modelを介してそのオブジェクトを子コントローラーに渡す状況のみを考えることができます。 これを行うと、親コントローラーはオブジェクトにアクセスできます。 このように、コントローラーはお互い、またはお互いのスコープを知る必要はありません。

それとも、私が思っていることとは違うことをしているのですか?

@dietergeertsございます。 あなたの例では、ng-modelを使用してプリミティブ値を子に渡しても、子がその値を変更しても影響はありません。

子にいくつかの単純なロジックが当てはまる場合は、基本的に最初のdivを表示する必要があります。

(ChildOneはルートに接続されているため、子の最初のdivを貼り付けることはできません)

@Bekt 、それはその効果をもたらす可能性があります。data-ng-ifは= "parent.object.property == 'some_value'"である可能性があります。もちろん、ロジックの内容とそのロジックの複雑さによって異なります。

それらがui-routerを使用してルートを介して設定され、それらが子ルートである場合、両方がオブジェクトを使用できます。

一般に、親に何かを尋ねなければならないのは非常に悪い考えです。それは、コントローラーが自己完結型ではないことを意味します。 通常、そのような「コミュニケーション」を行うにははるかに優れた方法があります。 それが、あなたが望むことをするためのより良い方法があるかもしれないので、私があなたが持っている実際の状況を尋ねていた理由です。

私は物事を切り離しておくのが好きです。 しかし、絶対的なものはほとんどありません...一般的に、私のディレクティブ、コントローラー、サービス...私はそれらが自己完結型であることが好きで、外部の側面が必要な場合は、それらを注入またはバインドします。 特定のコンテキストで使用されるものに依存するのは好きではありません。 意味がありますか?

私はこれを解決して、次のように子コントローラーをカプセル化します。

<div ng-controller="Parent as parent">

  <div ng-if="parent.showMessage">
    Some simple message.
  </div>

  <div child-one parent="parent"></div>

</div>
app.controller('Parent', function () {
    var self = this;
    self.showMessage = true;
});

app.directive('childOne', function() {
    return {
        controllerAs: 'childOne',
        controller: function($scope, $attrs) {
            var parent = $scope.$eval($attrs.parent);

            var self = this;
            self.foo = 'bar';
            // Some simple logic.
            if (self.foo === 'bar') {
                parent.showMessage = false;
            }
        }
    };
});

または、2番目のコントローラーでng-initを使用します。

<div ng-controller="ChildOne as childOne" ng-init="childOne.setParent(parent)"></div>

よりコンポーネント指向のアプローチを使用する:

<html ng-app="myApp">
  <body>
    <div ng-controller="ParentCtrl as vm">
      <my-directive on-foo-eq-bar="vm.updateMessage(msg)"></my-directive>
    </div>

    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
    <script>
      angular.module('myApp', [])
        .controller('ParentCtrl', function($window) {
          var vm = this;
          vm.updateMessage = function(msg) {
            $window.alert(msg);
          };
        })
        .directive('myDirective', function() {
          return {
            scope: {
              onFooEqBar:'&'
            },
            controllerAs:'vm',
            controller: function($scope) {
              var self = this;
              self.foo = 'bar';
              // Some simple logic.
              if (self.foo === 'bar') {
                $scope.onFooEqBar({msg: false});
              }
            }
          };
        });
    </script>
  </body>
</html>

@dbabaioff @leandrocosta :ありがとう、興味深い提案。

親に$on 、子に$broadcastました。

良い会話ですが、ここでガイドに追加するものは何もありません、IMO

:+1:

親コントローラーで$ rootScopeのイベントをサブスクライブします

$rootScope.$on('myEvent', function(data){/*do something*/})

次に、子で、$ rootScopeを使用してイベントを発生させます

$rootScope.$emit('myEvent', someData);

イムホ、コントローラーの代わりに2つのコンポーネントを用意し、必要に応じて子コンポーネントにプロパティを注入し、それらを設定する場合は、子から親に何かを出力する方がはるかに優れています。 はるかにパフォーマンスが高く、推論が簡単で、単体テストが簡単です。

$ rootScopeとイベントの使用は、最近では行われていません。

プロパティが存在するかどうかを確認してから、以下に示すように値を割り当てることができます。

if($ scope。$ parent.showMessage){
var parent = $ scope。$ parent;
while(!parent.hasOwnProperty( 'showMessage')){
親=親['$親'];
}
parent.showMessage = false;
}

これを壊して申し訳ありませんが、誰かがここに着陸した場合に備えて、私の解決策は、次のように、子コントローラーを直接コンポーネントに変換してから、更新関数を親から子にバインドすることです。

<div ng-controller="Parent as parent">

  <div ng-if="parent.showMessage">
    Some simple message.
  </div>

  <child-one update-parent="parent.showMessage = value"></child-one>

</div>
app.controller('Parent', function () {
    var self = this;
    self.showMessage = true;
});

app.component('childOne', /* component def stuff including updateParent: '&' in bindings */);

function childOneController() {
    var self = this;
    self.foo = 'bar';
    // Some simple logic.
    if (self.foo === 'bar') {
        self.updateParent({value: false});
    }
});
このページは役に立ちましたか?
0 / 5 - 0 評価

関連する問題

annabellor picture annabellor  ·  9コメント

sgbeal picture sgbeal  ·  7コメント

robrothedev picture robrothedev  ·  6コメント

MrOutput picture MrOutput  ·  5コメント

jusefb picture jusefb  ·  9コメント