web-dev-qa-db-ja.com

親のスコープにアクセスするカスタム子ディレクティブ

AngularJSアプリに2つのカスタムディレクティブがあります。 1つは親として機能し、もう1つは子として機能します。子ディレクティブ内の親のスコープにアクセスしようとしています。しかし、希望する出力が得られません。

<div ng-controller="CountryCtrl">
{{myName}}
    <div ng-controller="StateCtrl">
        <state nameofthestate="'Tamilnadu'">
            <city nameofthecity="'Chennai'"></city>
        </state>
    </div>
</div>

私のスクリプトは次のようになります

var app = angular.module("sampleApp",[]);
app.controller("CountryCtrl",function($scope){
    $scope.myName = "India";
});
app.controller("StateCtrl",function($scope){
});
app.directive("state",function(){return {
    restrict : 'E',
    transclude: true,
    scope : { myName  : '=nameofthestate'},
    template:"**   {{myName}} is inside {{$parent.myName}}<br/><ng-transclude></ng-transclude>"
}});
app.directive("city",function(){return {
    restrict : 'E',
    require:'^state',
    scope : { myName  : '=nameofthecity'},
    template:"****   {{myName}} is inside {{$parent.myName}} which is in {{$parent.$parent.myName }}<br/> "
}});

https://jsbin.com/nozuri/edit?html,js,output で利用可能な対応するJSFiddle

私が得ている出力は

India
** Tamilnadu is inside India
**** Chennai is inside India which is in Tamilnadu

期待される出力は

India
** Tamilnadu is inside India
**** Chennai is inside Tamilnadu which is in India

誰も私がここで間違っていることを教えてもらえますか?

Cityディレクティブ$ parentは、状態ディレクティブのトランスクルージョンされたスコープです。

状態ディレクティブのトランスクルードされたスコープは、コントローラーである状態ディレクティブの$ parentを継承するため、$ parent.MyName = Indiaである理由です。

Transcludedスコープの$ parentは、stateディレクティブ隔離されたスコープ(scope = {})であるため、$ parent。$ parent.MyName = Tamilnadu(Angular 1.3 updateの一部)

enter image description here

何が起こるかの詳細: AngularJSのカスタムスコープ*独自のスコープ*から親スコープにアクセスする方法

transclude:true-ディレクティブは新しい「トランスクルードされた」子スコープを作成します。これは典型的には親スコープから継承します。ディレクティブが分離スコープも作成する場合、トランスクルードスコープと分離スコープは兄弟です。各スコープの$ parentプロパティは、同じ親スコープを参照します。

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

また、Matthewの答えは、親子の指示のやり取りについては正しいです。

28
kwangsa

これはあなたのために働きますか? この回答 から適応。

トランスクルードされたコンテンツの親要素にアクセスする簡単な方法はないため、親コントローラーを子に挿入してそのスコープにアクセスします。

  var app = angular.module('myApp', []);

  app.controller("CountryCtrl",function($scope){
      $scope.myName = "India";
  });

  app.controller("StateCtrl",function($scope){
  });

  app.directive("state",function(){return {
      restrict : 'E',
      transclude: true,
      scope : { myName  : '=nameofthestate'},
      template:"**   {{myName}} is inside {{$parent.myName}}<br/><ng-transclude></ng-transclude>",
      controller: function ($scope) {
        this.getName = function () {
          return $scope.myName;
        }
      }
  }});

  app.directive("city",function(){return {
      restrict : 'E',
      require:'^state',
      scope : { myName  : '=nameofthecity'},
      template:"****   {{myName}} is inside {{parentName}} which is in {{$parent.myName }}<br/> ",
      link: function(scope, element, attrs, ctrl) {
        scope.parentName = ctrl.getName();
      }
  }});
15
Matthew King

AngularJSがtranscludeに遭遇すると、HTMLを複製してから、テンプレートまたはtemplateUrlのコンテンツに置き換えます。次に、ng-transcludeに遭遇すると、トランスクルードされたコンテンツをコンパイルしますが、ディレクティブの分離されたスコープではなく親スコープにリンクします。したがって、トランスクルードされたコンテンツは引き続き親コントローラーとそのコンテンツにアクセスできますが、ディレクティブHTMLは分離されたスコープ(または場合によっては新しいスコープ)を持ちます。

AngularJSの稼働中

2
gr3g

私の指令の解決策をチェックしてください、それは多くのparrentsで動作します。私がしたことは、トランスクルードを削除し、パラメータを要求することでした。汚いhtmlを気にせず、jsを見てください。

    CRM.directive('inputwv', function ($compile) {
    var getTemplate = function(contentType) {
        var template = '';

        switch(contentType) {
                case '3':
                    template = '<input type="number" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index )" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px;width:100px">'
                    break;
                case '0':
                    template = '<input type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index )" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">'
                    break;
                case '1':
                    template = '<input type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index )" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">'
                    break;
                case '2':
                    template = '<textarea class="materialize-textarea teal-text" type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index )" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">'
                    break;
                case '4':
                    template = '<input type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index )" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">'
                    break;
                case '5':
                    template = '<input type="date" class="datepicker" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index )" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px"><script type="text/javascript">$(\'.datepicker\').pickadate({selectMonths: true, selectYears: 15});</script>'
                    break;
                default:
                    template = '<textarea class="materialize-textarea teal-text" type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index )" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">'
            }

        return template;
}

    var linker = function(scope, element, attrs) {
        element.html(getTemplate(attrs.typ)).show();

        $compile(element.contents())(scope);
    }

    return {
        restrict: "E",
        link: linker
    };
});
1
Paweł Smołka