无法在指令 linkFn 中获取控制器引用

Posted

技术标签:

【中文标题】无法在指令 linkFn 中获取控制器引用【英文标题】:Can't get controller reference in directive linkFn 【发布时间】:2018-08-13 13:57:05 【问题描述】:

我正在尝试将angular-unit-converter 指令移植到 angularjs@1.4.5 中的打字稿。但是我无法让 angularjs 为 require 指令注入控制器。

它抛出

无法读取未定义的属性“$parsers”

因为ngModelundefined

这是我的尝试

// typescript conversion of https://github.com/alexandernst/angular-unit-converter
import  Decimal  from "decimal.js";
import  IDirective, IDirectiveFactory, IDirectiveLinkFn, IScope, INgModelController, IAttributes, IAugmentedJQuery  from "angular";

interface IUnitConverterScope extends IScope 
    [key: string]: any;
    convertFrom;
    convertTo;


export class UnitConverterDirective implements IDirective<IUnitConverterScope> 
    public link;
    public restrict = "A";
    public require: "ngModel";
    public template = "";
    public scope = 
        convertFrom: "@",
        convertTo: "@"
    ;

    constructor() 
        // It's important to add `link` to the prototype or you will end up with state issues.
        // See http://blog.aaronholmes.net/writing-angularjs-directives-as-typescript-classes/#comment-2111298002 for more information.
        this.link = this._link.bind(this);
    

    public static Factory(): IDirectiveFactory<IUnitConverterScope> 
        const directive = (/*list of dependencies*/) => 
            return new UnitConverterDirective(/*list of dependencies*/);
        ;

        directive["$inject"] = [];

        return directive;
    

    private _link(scope: IUnitConverterScope, element: IAugmentedJQuery, attrs: IAttributes, ngModel: INgModelController) 
        console.log(ngModel);
        Decimal.config(
            precision: 10
        );

        const units = 
            // Size/distance
            "mm": 0.001,
            "cm": 0.01,
            "m": 1,
            "km": 1000,
            "in": 0.0254,
            "ft": 0.3048,
            "yd": 0.9144,
            "mi": 1609.344,

            // Weight
            "mg": 0.001,
            "g": 1,
            "kg": 1000,
            "oz": 28.3495231,
            "lb": 453.59237
        ;

        scope.do_convertFrom = (value) => 
            if (!scope.convertFrom || scope.convertFrom === "")  return value; 

            let from = new Decimal(units[scope.convertFrom]);
            let to = new Decimal(units[scope.convertTo]);
            return (new Decimal(value).dividedBy(from.dividedBy(to))).toNumber();
        ;

        scope.do_convertTo = (value) => 
            if (!scope.convertTo || scope.convertTo === "")  return value; 

            let from = new Decimal(units[scope.convertFrom]);
            let to = new Decimal(units[scope.convertTo]);
            return (new Decimal(value).times(from.dividedBy(to))).toNumber();
        ;

        let p = (viewValue) => 
            let m = viewValue.match(/^\-?\d+((\.|\,)\d+)?$/g);
            if (m !== null) 
                return scope.do_convertFrom(parseFloat(viewValue));
            
        ;
        let f = (modelValue) => 
            return scope.do_convertTo(parseFloat(modelValue));
        ;

        ngModel.$parsers.push(p);
        ngModel.$formatters.push(f);

        scope.$watch("[convertFrom, convertTo]", () => 
            ngModel.$modelValue = "";
        );
    

可以看到直播DEMO(打开控制台查看错误)

如果我只写普通的 JS 就可以了 -> http://plnkr.co/edit/inuTNJ5OGhPHWmD09WWD?p=preview

我做错了什么?

【问题讨论】:

需要注意的是,这样的类设计不适用于 TS 中的指令,类只是提供了额外的样板,但没有明显的好处。它可能只是类型化的指令工厂函数。 【参考方案1】:

发生这种情况是因为从未定义过require。应该是

public require = "ngModel";

而不是

public require: "ngModel";

此类错误可以通过启用 TypeScript strictNullChecks 编译器选项来消除。

【讨论】:

天啊!我不敢相信我错过了:/

以上是关于无法在指令 linkFn 中获取控制器引用的主要内容,如果未能解决你的问题,请参考以下文章

Angular 控制器和指令将值从控制器获取到指令中

在使用自定义指令的时候,使用了一个引用传递的值来管理状态

对指令进行单元测试 - 无法强制使用虚假数据

如何使用范围变量将值从控制器获取到指令中

在主视图控制器的子容器视图中获取 tableView 的引用

iOS如何获取对带有segue的storyboard容器中嵌入的视图控制器的引用?