我有一个控制器负责与API通信,以更新用户的属性,名称,电子邮件等。每个用户都有一个“id”,当查看配置文件页面时,这个“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。但是会有错误。

在创建控制器时将值传递给控制器的正确方法是什么?


当前回答

看起来对你来说最好的解决方案实际上是一个指令。这允许你仍然拥有你的控制器,但是为它定义自定义属性。

如果你需要访问包装范围内的变量,使用这个:

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>

其他回答

我对此很晚了,我不知道这是否是一个好主意,但你可以在控制器函数中包括$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>

同样,不知道这是否是一个好主意,但它似乎有效,是另一种选择。

This is an expansion of @Michael Tiller's excellent answer. His answer works for initializing variables from the view by injecting the $attrs object into the controller. The problem occurs if the same controller is called from $routeProvider when you navigate by routing. Then you get injector error Unknown provider : $attrsProvider because $attrs is only available for injection when the view is compiled. The solution is to pass the variable (foo) through $routeParams when initializing controller from route and by $attrs when initializing controller from view. Here's my solution.

从路线

$routeProvider.
        when('/mypage/:foo', {
            templateUrl: 'templates/mypage.html',
            controller: 'MyPageController',
            caseInsensitiveMatch: true,
            resolve: {
                $attrs: function () {
                    return {};
                }
            }
        });

它处理一个url,如'/mypage/bar'。正如你所看到的,foo是通过url param传递的,我们为$attrs提供了一个空白对象,因此注入器没有错误。

从视图

<div ng-controller="MyPageController" data-foo="bar">

</div>

现在是控制器

var app = angular.module('myapp', []);
app.controller('MyPageController',['$scope', '$attrs', '$routeParams'], function($scope, $attrs, $routeParams) {
   //now you can initialize foo. If $attrs contains foo, it's been initialized from view
   //else find it from $routeParams
   var foo = $attrs.foo? $attrs.foo : $routeParams.foo;
   console.log(foo); //prints 'bar'

});

如果使用angular-ui-router,那么这是正确的解决方案:https://github.com/angular-ui/ui-router/wiki#resolve

基本上,在控制器实例化之前声明一组要“解析”的依赖项。你可以为你的每个“状态”声明依赖关系。然后将这些依赖项传递到控制器的“构造函数”中。

如果ng-init不是用来将对象传递到$scope,你可以编写自己的指令。这就是我得到的结果:

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

Javasript:

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>

但是我的方法只能修改已经在控制器中定义的对象。

你可以在设置路由时这样做。

 .when('/newitem/:itemType', {
            templateUrl: 'scripts/components/items/newEditItem.html',
            controller: 'NewEditItemController as vm',
            resolve: {
              isEditMode: function () {
                return true;
              }
            },
        })

以后用它作为

(function () {
  'use strict';

  angular
    .module('myApp')
    .controller('NewEditItemController', NewEditItemController);

  NewEditItemController.$inject = ['$http','isEditMode',$routeParams,];

  function NewEditItemController($http, isEditMode, $routeParams) {
    /* jshint validthis:true */

    var vm = this;
    vm.isEditMode = isEditMode;
    vm.itemType = $routeParams.itemType;
  }
})();

所以在这里,当我们设置路由时,我们发送:itemType并稍后从$routeParams中检索它。