Angular 指令使用 Typescript 接收对象作为属性

Posted

技术标签:

【中文标题】Angular 指令使用 Typescript 接收对象作为属性【英文标题】:Angular directive receiving object as attribute using Typescript 【发布时间】:2017-02-14 09:17:12 【问题描述】:

我正在使用 Angular 1.5.8 和 Typescript 进行开发 我有一个指令,它在另一个指令(当然还有另一个控制器)的范围内使用。假设 Directive1,Controller1 和 Directive2,Controller2。 鉴于Controller1已经有用户信息,我想通过Directive2将这个用户信息传递给Controller2,以防止再次从后端获取信息。 我不确定这是否可以做到,但如果是这样的话那就太好了:)

下面是帮助我解释的代码:

Directive1 html

<div>
    ...
    <directive2 user="ctrl.loggedUser"></directive2>
    ...
</div>

loggedUser 通过调用后端加载到 Controller1 构造函数中。

Directive2 和 Directive2Ctrl 打字稿代码:

class Directive2 implements ng.IDirective 
    controller = "Directive2Ctrl";
    controllerAs = "d2Ctrl";
    bindToController = 
        user: "@"
    ;
    restrict = "E";
    templateUrl = "directive2.html";

    static factory(): ng.IDirectiveFactory 
        const directive = () => new Directive2();
        return directive;
    

angular
    .module("app")
    .controller("Directive2Ctrl", Directive2Ctrl)
    .directive("directive2", Directive2.factory());


class Directive2Ctrl implements IDirective2Ctrl 
    public user: User;

    constructor(user: User) 
         // user is undefined
    

    $onInit(user: User): void 
        // user is undefined
    

我找不到将用户对象传递给 Directive2Ctrl 的方法(甚至不确定是否可行)。

【问题讨论】:

视图中应该是user="ctrl.loggedUser"(没有大括号),bindToController定义中应该是user: "="(而不是@) 我应该使用控制器还是指令中的范围?还是应该在不需要使用范围的情况下工作? 不,如果您使用绑定到控制器语法,则不需要显式使用范围 【参考方案1】:

使用“范围”属性而不是“bindToController”属性,并将“@”替换为“=”。 然后我为我的特定范围使用一个接口来获得自动完成。

export interface IMyDirectiveScope extends ng.IScope 
    user: any;


export class Myirective 
    public restrict: string = 'E';
    public templateUrl = "/mytemplate.html";
    public link: (scope: IMyDirectiveScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ngModel: ng.INgModelController) => void;
    public scope = 
        user: "="
    ;

    constructor() 
        var context = this;
        context.link = (scope: IMyDirectiveScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ngModel: ng.INgModelController) => 
           //INSERT YOUR CODE
           //console.log(scope.user);
        ;
    

    public static Factory() 
        var directive = () => 
            return new MyDirective();
        ;

        return directive;
    

在您的 html 中,删除您的花括号。

<div>
    ...
    <directive2 user="ctrl.loggedUser"></directive2>
    ...
</div>

【讨论】:

我尝试创建一个 plunker,但不确定如何在 plunker 上编译 typescript。 为了编译,你需要在你的 .ts 文件中添加你的导入。【参考方案2】:

如果您想在应用程序的不同位置之间共享数据,只需将其放入服务中,然后在需要数据的任何地方使用 DI。

也就是说,获取数据,将其存储在服务中并使用 DI 使数据在不同位置可用。无需通过多层绑定传递数据,更容易使用服务。

var mod = angular.module('testApp', ['ngRoute']);

mod.config(['$routeProvider',
  function($routeProvider) 
    $routeProvider.
      when('/intern', 
        template: '<div class="outer" ng-controller="InternController">User.firstName <div class="nested" ng-controller="NestedController">NestedUser.lastName<test-dir></test-dir></div></div>',
        resolve: 
          userResolve: function($q, $timeout, User) 
            var deferred = $q.defer();
          
            // mock server call, which returns server data
            $timeout(function() 
              var mockUserResp = 
                firstName: 'John',
                lastName: 'Rambo'
              ;
              User.setUser(mockUserResp);
            
              deferred.resolve();
            , 1000);
          
            return deferred.promise;
          
        
      ).
      otherwise(
        redirectTo: '/intern'
      );
  ]);

mod.factory('User', function() 
  var _user = null;
  return 
    setUser: function(user) 
      _user = user;
    ,
    getUser: function() 
      return _user;
    
    
);

mod.controller('InternController', function($scope, User) 
  $scope.User = User.getUser();
);

mod.controller('NestedController', function($scope, User) 
  $scope.NestedUser = User.getUser();
);

mod.directive('testDir', function(User) 
  return 
    restrict: 'EA',
    scope: ,
    template: '<div class="dir">firstName is a cool guy.</div>',
    link: function(scope) 
      scope.firstName = User.getUser().firstName;
    
  ;
);
.outer 
  border: 1px solid green;


.nested 
  border: 1px solid blue;


.dir 
  border: 1px solid orange;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.12/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.12/angular-route.min.js"></script>


<div ng-app="testApp">
  <div ng-view></div>
</div>

【讨论】:

但我不想再次获取数据。因为 Controller1 已经获取了用户数据并且我使用的指令在 Controller1 HTML 中,所以我想将它作为参数传递。我认为 $scope 用于此目的,但我不清楚如何使它在我的 Typescript 实现上工作。 啊,也许我误会了你。你的意思是从后端提取数据一次,然后通过服务将其提供给任何控制器?我认为那会好很多。你有那个样本吗? 没错,我添加了一个短代码 sn-p,它演示了 Angular 应用程序中的一个常见问题。通常,对于某些状态数据,必须从服务器获取(用 $timeout 调用模拟)。然后,这些数据通常在多个位置共享。希望这个例子有所帮助。【参考方案3】:

应该是这样的。但如果它仍然不适合你,你可以创建一个简单的 plunker,我会在那里修复它。干杯!

<div>
    ...
    <directive2 user="ctrl.loggedUser"></directive2>
    ...
</div>

`

class Directive2 implements ng.IDirective 
    controller = "Directive2Ctrl";
    controllerAs = "d2Ctrl";
    scope = ,
    bindToController = 
        user: "="
    ;
    restrict = "E";
    templateUrl = "directive2.html";

    static factory(): ng.IDirectiveFactory 
        return () => new Directive2();
    

angular
    .module("app")
    .controller("Directive2Ctrl", Directive2Ctrl)
    .directive("directive2", Directive2.factory());


class Directive2Ctrl implements IDirective2Ctrl 
    public user: User;

    $onInit(user: User): void 
        // user should be available
        console.log(this.user);
    

【讨论】:

我创建了这个 plunker,虽然它还没有工作(我不知道如何在 Plunker 中编译 typescript)。 plnkr.co/edit/0VSQhvrG2yIKhCQ2nJny?p=info">Plunker</…>【参考方案4】:

抱歉,不知您是否还需要设置 scope =

【讨论】:

Directive2 不需要 Directive1。它需要一个用户。在这种情况下,它是在具有用户的控制器范围内使用的,但它不一定是 Controller1。 我想,我有点困惑,你能不能在绑定到控制器时将你的范围设置为 user:"=",而不是 user:'@' 我已经尝试过 scope = ;以及用 = 更改 @ 但仍然没有成功。【参考方案5】:

首先要做我要求的,范围需要正确使用。

这是另一个很好地解释了正确使用范围的问题:

How can I define my controller using TypeScript?

【讨论】:

以上是关于Angular 指令使用 Typescript 接收对象作为属性的主要内容,如果未能解决你的问题,请参考以下文章

typescript 使用指令将控制集中在角4 #angular

在 TypeScript Angular 指令中调用函数?

typescript Angular - 选择一个类的指令

typescript Angular Bootstrap下拉指令

typescript Angular 2悬停类指令

Angular 与 Typescript 和指令中未定义的注入服务