web-dev-qa-db-ja.com

Angularディレクティブはng-repeatの内部を評価しません

私は次の設定をしています:

アプリ/ディレクティブ

var app = angular.module("MyApp", []);

app.directive("adminRosterItem", function () {
    return {
        restrict: "E",
        scope: {
            displayText: "@"
        },
        template: "<td>{{ displayText }}</td>", // should I have this?
        link: function(scope, element, attrs){
            // What do I put here? I don't seem to have any
            // element to initialize (set up event handlers, for example)
        },
        compile: function(?,?,?){} // should I have this? If so, what goes inside?
    }
});

コントローラ

function PositionsController($scope) {
           $scope.positions = [{ Name: "Quarterback", Code: "QB" },
                               { Name: "Wide Receiver", Code: "WR" }
                              ]; 
}

HTML:

<div ng-app="MyApp">
    <div ng-controller="PositionsController">            
        <table>
            <tr ng-repeat="position in positions">
                <admin-roster-item displayText="{{ position.Name + ' (' + position.Code + ')' }}"></admin-roster-item>
             </tr>
         </table>       
    </div>
</div>

これは非常に単純な例ですが、レンダリングすることができません。おそらく、チュートリアルが私に教えていない何かがあるか、それは秘密ですAngular知識?

<tr ng-repeat="..." />内のディレクティブを削除して代わりに<td>{{ displayText }}</td>を配置すると、すべてのレコードが表示されます。

ただし、このディレクティブを複数のアプリで再利用できるように、(最終的には)単一の<td>{{}}</td>よりもディレクティブを複雑にする必要があります。

だから、私は本当にng-repeat内に入るディレクティブを適切に作成する方法を尋ねていますか?何が足りないのですか?上記のコードから何を取り除く必要がありますか?

10
Mickael Caruso

ディレクティブの開始位置と終了位置について考える必要があることに同意します。これは、配列内の各アイテムにバインドされたディレクティブを示すplnkrです http://plnkr.co/edit/IU8fANreYP7NYrs4swTW?p=preview

親スコープによって定義されたコレクションの列挙をディレクティブにカプセル化する場合は、少し注意が必要です。以下が「ベストプラクティス」であるかどうかはわかりませんが、それは私がそれをどのように処理したかです-- http://plnkr.co/edit/IU8fANreYP7NYrs4swTW?p=preview

ディレクティブに依存して反復を実行する場合、トランスクルージョンに関与します。これは、(私が理解しているように)親で定義されたコンテンツを取得し、それをディレクティブにプッシュしてから評価することを意味する、構成されたWordです。私はangularを数か月間使用してきましたが、反復するように指示を求めるのはにおいだと思い始めており、常にそれを中心に設計することができました。

8
Jason

理論的な側面をすべて無視すると、2つの簡単な変更を加えるだけでコードを機能させることができます。

  1. 属性名に大文字と小文字を混在させないでください。 displaytextnotdisplayText
  2. 置く <td>ディレクティブの外側、テンプレート内のタグ

そうすればうまくいくでしょう。それらは両方ともAngularバグだと思います。

9
Malvolio

これに取り組む正しい方法は、次のようにオブジェクトを管理者名簿アイテムに送信することだと思います。

<tr ng-repeat="position in positions">
  <admin-roster-item pos="position">         
  </admin-roster-item>
</tr>

およびディレクティブ内:

var app = angular.module("MyApp", []);

app.directive("adminRosterItem", function () {
  return {
    restrict: "E",
    scope: {
        pos: "@"
    },
    template: "<td>{{ formattedText }}</td>", // should I have this?
    link: function(scope, element, attrs){
        // all of this can easily be done with a filter, but i understand you just want to     
        // know how it works
        scope.formattedText = scope.pos.Name + ' (' + scope.pos.Code + ')';
    }
  }
});

PS。私はこれをテストしませんでした!

2
user1695032

Ng-repeatの子としてディレクティブを作成する代わりに、カスタムディレクティブをng-repeatと同じレベルに維持してみてください。

<tr ng-repeat="position in positions" admin-roster-item displayText="{{ position.Name + ' (' + position.Code + ')' }}"></tr>

さらに、カスタムディレクティブを属性として使用できるようにします。 AngulaJSではng-repeatsの優先度を1000と定義しているため、カスタムディレクティブを作成すると、ng-repeatではうまく機能しない場合があります。

2番目のオプション(最初のディレクティブが失敗した場合にのみ試してください)は、カスタムディレクティブの優先度をngRepeatの優先度よりも高く設定することです(つまり、1001)。

1

同様の問題が発生しました。ビューにディレクティブ( 'mydirective')が含まれている場合、ビューのng-repeatが評価されませんでした。

私のディレクティブの定義は

angular.module('myApp')
  .directive('myDirective', function () {
    return {
      templateUrl: 'components/directives/mydirective.html',
      restrict: 'EA',
      controller: 'MyDirectiveController',
      controllerAs: 'vm',
      link: function (scope, element, attrs) {
      }
    };
  });

私のビューコントローラーの定義は

  angular.module('myApp')
    .component('myView', {
      templateUrl: 'app/views/myview.html',
      controller: myViewComponent,
      controllerAs: "vm"
    });

'controllerAs'パラメーターを使用すると、両方のコントローラーが 'vm'によって参照されていることがわかります。これが問題の理由です。ディレクティブがビューに存在する場合、angularは常に、ビューではなくディレクティブコントローラーで定義された「vm」を参照します。

コントローラ参照に別の名前を付けると、問題が解消されました

さて、私のディレクティブの定義は

angular.module('myApp')
  .directive('myDirective', function () {
    return {
      templateUrl: 'components/directives/mydirective.html',
      restrict: 'EA',
      controller: 'MyDirectiveController',
      controllerAs: 'directiveVM',
      link: function (scope, element, attrs) {
      }
    };
  });

私のビューコントローラーの定義は

  angular.module('myApp')
    .component('myView', {
      templateUrl: 'app/views/myview.html',
      controller: myViewComponent,
      controllerAs: "viewCtrlVM"
    });

それが役に立てば幸い。

0
Chandru

まったく同じ問題がありました。 ng-repeat、table-> tr-> td-> directiveにカスタムディレクティブがあり、ng-repeatおよびArray.sortを使用してテーブルを並べ替えると、テーブルの順序が変更されましたが、ディレクティブは再レンダリングされませんでした。問題は私が使っていたということでした

track by $index

ng-repeatからインデックスごとにトラックを削除し、修正しました。

0
Tomas Katz