【问题标题】:AngularJS - Is it possible to change the value of ngModel attribute on directive in link or compile?AngularJS - 是否可以在链接或编译中更改指令上的 ngModel 属性的值?
【发布时间】:2013-10-24 23:28:53
【问题描述】:

我正在尝试创建一个指令,该指令将根据属性值将 ngModel 属性添加到标记中。例如:

angular.module('myModule').
  directive('myDirective', function() {
    return {
      link: function(scope, elem, attrs) {
        var modelName = 'myPrefix.' + attrs.name;
        attrs.$set('ngModel', modelName);
      }
    };
  });

这样这个html:

<input name="foo" my-directive></input>

编译成

<input name="foo" ng-model="myPrefix.foo" my-directive></input>

它接受输入的名称,附加一个前缀,并将 ngModel 属性设置为该值。

当我尝试在链接函数中执行此操作时,似乎 input 没有注册到 formController,因此 form.foo 返回未定义。

有可能完成我想做的事情吗?

编辑:

似乎在 HTML 上设置了 ngModel 属性,但它没有在表单中注册,或者 ngModelController 没有被实例化。如果我在范围内查看ngModel 的值,当我修改输入时它不会改变。

【问题讨论】:

    标签: javascript angularjs angularjs-directive


    【解决方案1】:

    您应该查看NgModelController 的文档。它会回答你的问题。为了进一步解释,这里是要点:

    您可以捕获link: 函数的第四个参数,即您的ng-model 值。您可以使用该对象来读取和设置模型。

    link: function(scope, element, attrs, ngModel) {
        if(!ngModel) return; // do nothing if no ng-model
    
        // Specify how UI should be updated
        ngModel.$render = function() {
          element.html(ngModel.$viewValue || '');
        };
    
        // Listen for change events to enable binding
        element.on('blur keyup change', function() {
          scope.$apply(read);
        });
        read(); // initialize
    
        // Write data to the model
        function read() {
          var html = element.html();
          // When we clear the content editable the browser leaves a <br> behind
          // If strip-br attribute is provided then we strip this out
          if( attrs.stripBr && html == '<br>' ) {
            html = '';
          }
          ngModel.$setViewValue(html);
        }
    }
    

    希望对您有所帮助。

    【讨论】:

    • 实际上在我的情况下,不能保证在标签上创建 ngModel 属性,因此不会实例化 ngModelController。换句话说,我希望我的指令先编译,添加 ngModel 属性,然后我希望编译器识别出添加了一个 ngModel 属性,然后实例化 ngModelController
    • 提前知道这可能会有所帮助。根据文档here Attributes 部分下的示例,您所做的应该适用于观察 ngModel。
    • 你是对的,它确实添加了属性,但是输入并没有修改模型,所以看起来它没有正确注册。
    【解决方案2】:

    我能够通过使用模板函数来实现目标。我认为它在链接函数中不起作用,因为它发生在收集所有指令之后,因此编译器无法识别已添加 ngModel 指令。不过,我不确定为什么它在编译函数中不起作用(即使我将优先级设置为 100)。

    这是指令的工作版本:

    angular.module('myModule').
      directive('myDirective', function() {
        return {
          replace: true,
          template: function(elem, attr) {
            var newElem = '<input ng-model="model.' + attr.name + '">';
            return newElem;
          }
        };
      });
    

    【讨论】:

    • 链接发生在编译器之后,所以要让你的原始代码工作,你需要调用类似 $compile(elem)(scope) 的东西来重新编译并获取你对 DOM 的更改,但事情是,您不希望在链接函数中使用它,它会导致代码再次运行(并再次等),这也需要一小部分额外代码来检查。模板函数将在指令之后编译,这就是它解决您的问题的原因。
    猜你喜欢
    • 2016-07-06
    • 2014-05-03
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2018-02-08
    • 2019-10-28
    相关资源
    最近更新 更多