282

APIと通信して、ユーザー、名前、電子メールなどのプロパティを更新するコントローラーがあります。各ユーザーには'id'、プロファイルページが表示されたときにサーバーから渡されるがあります。

この値をAngularJSコントローラーに渡して、現在のユーザーのAPIエントリポイントがわかるようにします。に値を渡してみましたng-controller。例えば:

function UserCtrl(id, $scope, $filter) {

$scope.connection = $resource('api.com/user/' + id)

とHTMLで

<body ng-controller="UserCtrl({% id %})">

ここで{% id %}、サーバーから送信されたIDを出力します。しかし、エラーが発生します。

作成時にコントローラーに値を渡す正しい方法は何ですか?

4

17 に答える 17

366

ノート:

この答えは古いです。これは、目的の結果を達成する方法の概念実証にすぎません。ただし、以下のいくつかのコメントによると、これは最善の解決策ではない可能性があります。次のアプローチをサポートまたは拒否するドキュメントはありません。このトピックに関する詳細な議論については、以下のコメントのいくつかを参照してください。

元の回答:

ng-initはい、簡単なinit関数を使用して絶対にできると答えました。

これがプランカーでの例です

HTML

<!DOCTYPE html>
<html ng-app="angularjs-starter">
  <head lang="en">
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js"></script>
    <script src="app.js"></script>
  </head>  
  <body ng-controller="MainCtrl" ng-init="init('James Bond','007')">
    <h1>I am  {{name}} {{id}}</h1>
  </body>
</html>

JavaScript

var app = angular.module('angularjs-starter', []);

app.controller('MainCtrl', function($scope) {

  $scope.init = function(name, id)
  {
    //This function is sort of private constructor for controller
    $scope.id = id;
    $scope.name = name; 
    //Based on passed argument you can make a call to resource
    //and initialize more objects
    //$resource.getMeBond(007)
  };


});
于 2013-01-25T22:56:53.043 に答える
147

私はこれに非常に遅れており、これが良い考えであるかどうかはわかりませんが、コントローラー関数に注入$attrs可能なものを含めて、要素で提供される「引数」を使用してコントローラーを初期化できるようにすることができます。

app.controller('modelController', function($scope, $attrs) {
    if (!$attrs.model) throw new Error("No model for modelController");

    // Initialize $scope using the value of the model attribute, e.g.,
    $scope.url = "http://example.com/fetch?model="+$attrs.model;
})

<div ng-controller="modelController" model="foobar">
  <a href="{{url}}">Click here</a>
</div>

繰り返しますが、これが良いアイデアかどうかはわかりませんが、うまくいくようで、別の選択肢です。

于 2014-05-12T15:13:43.520 に答える
39

これも機能します。

Javascript:

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

app.controller('MainCtrl', function($scope, name, id) {
    $scope.id = id;
    $scope.name = name;
    // and more init
});

HTML:

<!DOCTYPE html>
<html ng-app="angularApp">
  <head lang="en">
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js"></script>
    <script src="app.js"></script>
    <script>
       app.value("name", "James").value("id", "007");
    </script>
  </head>
  <body ng-controller="MainCtrl">
    <h1>I am  {{name}} {{id}}</h1>
  </body>
</html>
于 2014-03-15T13:46:53.417 に答える
17

ビューは構成を決定するべきではありません

Angular では、テンプレートが構成を指示することはありません。これは、テンプレート ファイルからコントローラーに引数を渡したいときに本質的に要求されるものです。滑りやすい坂道になります。構成設定がテンプレートにハードコーディングされている場合 (ディレクティブやコントローラー引数属性などによって)、そのテンプレートを 1 回の使用以外に再利用することはできなくなります。すぐにそのテンプレートを再利用する必要がありますが、構成が異なります。そのためには、テンプレートを前処理して、angular に渡される前に変数を挿入するか、大規模なディレクティブを使用して巨人を吐き出します。ラッパー div とその引数を除いて、すべてのコントローラー HTML を再利用できます。小規模なプロジェクトの場合、大したことではありません。大きなもの (angular が優れているもの) の場合、すぐに醜くなります。

代替手段: モジュール

このタイプの構成は、モジュールが処理するように設計されたものです。多くのAngularチュートリアルでは、アプリケーション全体に対して単一のモジュールがありますが、実際には、システムは設計されており、アプリケーション全体の小さな部分をそれぞれラップする多くの小さなモジュールを完全にサポートしています. 理想的には、コントローラー、モジュールなどは別々のファイルで宣言され、特定の再利用可能なチャンクにまとめられます。アプリケーションがこのように設計されている場合、簡単なコントローラー引数に加えて、多くの再利用が可能になります。

以下の例には 2 つのモジュールがあり、同じコントローラーを再利用していますが、それぞれに独自の構成設定があります。その構成設定は、を使用して依存性注入を介して渡されますmodule.value。コンストラクタ依存性注入、再利用可能なコントローラ コード、再利用可能なコントローラ テンプレート (コントローラ div は ng-include で簡単に含めることができます)、HTML なしで簡単に単体テスト可能なシステム、そして最後に再利用可能なものがあるため、これは角度のある方法に準拠しています。ピースをつなぎ合わせる手段としてのモジュール。

次に例を示します。

<!-- index.html -->
<div id="module1">
    <div ng-controller="MyCtrl">
        <div>{{foo}}</div>
    </div>
</div>
<div id="module2">
    <div ng-controller="MyCtrl">
        <div>{{foo}}</div>
    </div>
</div>
<script>
    // part of this template, or a JS file designed to be used with this template
    angular.element(document).ready(function() {
        angular.bootstrap(document.getElementById("module1"), ["module1"]);
        angular.bootstrap(document.getElementById("module2"), ["module2"]);
    });
</script>

<!-- scripts which will likely in be in their seperate files -->
<script>
    // MyCtrl.js
    var MyCtrl = function($scope, foo) {
    $scope.foo = foo;
    }

    MyCtrl.$inject = ["$scope", "foo"];

    // Module1.js
    var module1 = angular.module('module1', []);
    module1.value("foo", "fooValue1");
    module1.controller("MyCtrl", MyCtrl);

    // Module2.js file
    var module2 = angular.module('module2', []);
    module2.value("foo", "fooValue2");
    module2.controller("MyCtrl", MyCtrl);
</script>

実際に見てみましょう: jsFiddle

于 2014-12-30T22:22:08.187 に答える
8

あなたにとって最良の解決策は実際にはディレクティブのようです。これにより、コントローラーを引き続き使用できますが、コントローラーのカスタム プロパティを定義できます。

ラッピング スコープ内の変数にアクセスする必要がある場合は、これを使用します。

angular.module('myModule').directive('user', function ($filter) {
  return {
    link: function (scope, element, attrs) {
      $scope.connection = $resource('api.com/user/' + attrs.userId);
    }
  };
});

<user user-id="{% id %}"></user>

ラッピング スコープ内の変数にアクセスする必要がない場合は、これを使用します。

angular.module('myModule').directive('user', function ($filter) {
  return {
    scope: {
      userId: '@'
    },
    link: function (scope, element, attrs) {
      $scope.connection = $resource('api.com/user/' + scope.userId);
    }
  };
});

<user user-id="{% id %}"></user>
于 2014-11-26T09:47:55.113 に答える
8

ng-initオブジェクトを に渡すためのものでない場合は$scope、いつでも独自のディレクティブを作成できます。だからここに私が得たものがあります:

http://jsfiddle.net/goliney/89bLj/

Javaスクリプト:

var app = angular.module('myApp', []);
app.directive('initData', function($parse) {
    return function(scope, element, attrs) {
        //modify scope
        var model = $parse(attrs.initData);
        model(scope);
    };
});

function Ctrl1($scope) {
    //should be defined
    $scope.inputdata = {foo:"east", bar:"west"};
}

HTML:

<div ng-controller="Ctrl1">
    <div init-data="inputdata.foo=123; inputdata.bar=321"></div>
</div>

しかし、私のアプローチでは、コントローラーで既に定義されているオブジェクトのみを変更できます。

于 2013-11-25T22:00:59.587 に答える
7

$routeProvider から変数を渡すと便利であることがわかりました。

たとえば、1 つのコントローラー MyController を複数の画面に使用し、非常に重要な変数 "mySuperConstant" を内部に渡します。

その単純な構造を使用します。

Router:

$routeProvider
            .when('/this-page', {
                templateUrl: 'common.html',
                controller: MyController,
                mySuperConstant: "123"
            })
            .when('/that-page', {
                templateUrl: 'common.html',
                controller: MyController,
                mySuperConstant: "456"
            })
            .when('/another-page', {
                templateUrl: 'common.html',
                controller: MyController,
                mySuperConstant: "789"
            })

MyController:

    MyController: function ($scope, $route) {
        var mySuperConstant: $route.current.mySuperConstant;
        alert(mySuperConstant);

    }
于 2014-12-01T11:31:10.110 に答える
2

angular-ui-router を使用している場合、これが正しい解決策です: https://github.com/angular-ui/ui-router/wiki#resolve

基本的に、コントローラーがインスタンス化される前に、「解決」する一連の依存関係を宣言します。「状態」ごとに依存関係を宣言できます。これらの依存関係は、コントローラーの「コンストラクター」に渡されます。

于 2015-07-06T22:26:00.607 に答える
1

それを行う 1 つの方法は、パブリック データ メンバーである引数の「容器」として使用できる別のサービスを用意することです。

于 2014-07-10T15:40:00.470 に答える
1

私は自分の特定のユースケースでここにあるソリューションのどれもあまり好きではなかったので、ここでは見られなかったので、私がやったことを投稿することにしました.

ng-repeat ループ内で、コントローラーをディレクティブのように使用したかっただけです。

<div ng-repeat="objParameter in [{id:'a'},{id:'b'},{id:'c'}]">
  <div ng-controller="DirectiveLikeController as ctrl"></div>
</div>

さて、objParameter各 DirectiveLikeController 内の作成時にアクセスする (またはいつでも最新の objParameter を取得する) ために必要なことは、$scope を注入して を呼び出すことだけ$scope.$eval('objParameter')です。

var app = angular.module('myapp', []);
app.controller('DirectiveLikeController',['$scope'], function($scope) {
   //print 'a' for the 1st instance, 'b' for the 2nd instance, and 'c' for the 3rd.
   console.log($scope.$eval('objParameter').id); 
});

私が目にする唯一の本当の欠点は、親コントローラーがパラメーターの名前が であることを知る必要があることですobjParameter

于 2019-04-18T18:36:59.523 に答える
0

いいえ、できません。ng-init をハックhttp://docs.angularjs.org/api/ng.directive:ngInitとして使用できると思います。

于 2013-01-25T14:31:20.560 に答える
0

これは、コントローラーに値を渡したいが、htmlでコントローラーを明示的に宣言していない場合に機能するソリューション(Marcin Wyszynskiの提案に基づく)です(ng-initが必要と思われる)-たとえば、 ng-view を使用してテンプレートをレンダリングし、routeProvider を介して対応するルートの各コントローラーを宣言しています。

JS

messageboard.directive('currentuser', ['CurrentUser', function(CurrentUser) {
  return function(scope, element, attrs) {
    CurrentUser.name = attrs.name;
  };
}]);

html

<div ng-app="app">
  <div class="view-container">
    <div ng-view currentuser name="testusername" class="view-frame animate-view"></div>
  </div>
</div>

このソリューションでは、CurrentUser は任意のコントローラーに注入できるサービスであり、.name プロパティが使用可能になります。

2 つの注意事項:

  • 私が遭遇した問題は、コントローラーのロード後に .name が設定されることです。そのため、回避策として、コントローラーのスコープでユーザー名をレンダリングする前に短いタイムアウトがあります。.name がサービスに設定されるまで待つきちんとした方法はありますか?

  • これは、すべての認証を Angular の外部に保持して、現在のユーザーを Angular アプリに入れる非常に簡単な方法のように思えます。ログインしていないユーザーが、Angular アプリがブートストラップされている html にアクセスするのを防ぐ before_filter を持つことができます。その html 内では、ログインしているユーザーの名前と、ユーザーの詳細を操作したい場合はその ID を補間することができます。 Angular アプリからの http リクエスト経由。ログインしていないユーザーがデフォルトの「ゲスト ユーザー」で Angular アプリを使用できるようにすることができます。このアプローチがなぜ悪いのかについてのアドバイスは大歓迎です - あまりにも簡単すぎて賢明ではありません!)

于 2016-09-02T15:39:07.670 に答える