简体   繁体   English

AngularJS - 是否可以在链接或编译中更改指令上的ngModel属性的值?

[英]AngularJS - Is it possible to change the value of ngModel attribute on directive in link or compile?

I am trying to create a directive that will add an ngModel attribute to a tag based on the attribute value. 我正在尝试创建一个指令,该指令将基于属性值将ngModel属性添加到标记。 For example: 例如:

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

So that this html: 这个html:

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

is compiled into 编译成

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

It takes the name of the input, attaches a prefix, and sets the ngModel attribute to that value. 它接受输入的名称,附加前缀,并将ngModel属性设置为该值。

When I try to do this in the link function, it seems like the input isn't being registered with the formController, so that form.foo returns undefined. 当我尝试在链接函数中执行此操作时,似乎input未使用formController注册,因此form.foo返回undefined。

Is it possible to accomplish what I'm trying to do? 是否有可能完成我想要做的事情?

EDIT: 编辑:

It seems like the ngModel attribute is being set on the HTML, but it is not being registered with the form, or the ngModelController is not being instantiated. 似乎在HTML上设置了ngModel属性,但它没有在表单中注册,或者没有实例化ngModelController。 If I look at the value of ngModel in the scope, it does not change when I modify the input. 如果我查看范围中ngModel的值, ngModel在修改输入时它不会更改。

You should check out the docs for the NgModelController . 您应该查看NgModelController的文档。 It will answer your question. 它会回答你的问题。 For further explanation, here's the gist: 有关进一步说明,请参阅以下内容:

You can capture a fourth argument to the link: function, which is your ng-model value. 您可以捕获link:的第四个参数link: function,这是您的ng-model值。 You use that object to read and set the 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);
    }
}

Hope that helps. 希望有所帮助。

I was able to accomplish the goal by using a template function. 我能够通过使用模板功能来完成目标。 I think it doesn't work in the link function because it occurs after all of the directives have been collected, so the compiler doesn't recognize that an ngModel directive has been added. 我认为它在链接函数中不起作用,因为它发生在收集了所有指令之后,因此编译器无法识别添加了ngModel指令。 I'm not sure why it doesn't work in the compile function, though (even if I set the priority to 100). 我不确定为什么它在编译函数中不起作用(即使我将优先级设置为100)。

Here's the working version of the directive: 这是该指令的工作版本:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM