Javascript 手动应用ngModel指令

Javascript 手动应用ngModel指令,javascript,angularjs,angularjs-directive,angular-ngmodel,Javascript,Angularjs,Angularjs Directive,Angular Ngmodel,我的指令需要使用ngModel 我需要从另一个指令中动态地完成这项工作,因为我想用作用域做一些时髦的事情,并将其从编写HTML的人那里抽象出来 我的第一个想法是使用link函数中的attrs参数提供的$set函数,该函数可以修改HTML,但指令本身不会被编译。然后我们可以将它与$compile提供程序结合起来,它就可以工作了 attrs.$set('ngModel', someVar); $compile(element)(scope); 问题是,如果在指令被无限期地重新应用和重新编译时,我不

我的指令需要使用
ngModel

我需要从另一个指令中动态地完成这项工作,因为我想用作用域做一些时髦的事情,并将其从编写HTML的人那里抽象出来

我的第一个想法是使用
link
函数中的
attrs
参数提供的
$set
函数,该函数可以修改HTML,但指令本身不会被编译。然后我们可以将它与
$compile
提供程序结合起来,它就可以工作了

attrs.$set('ngModel', someVar);
$compile(element)(scope);
问题是,如果在指令被无限期地重新应用和重新编译时,我不(也不能)替换elements标记,这将创建无限递归

然而,我可以摆弄优先事项并使其发挥作用:

module.directive('input', [
  '$compile',
  function($compile) {
    return {
      restrict: 'E',
      scope: {},
      priority: 100, // Set this high enough to perform other directives
      terminal: true, // Make sure this is the last directive parsed
      link: function(scope, element, attrs) {
          var key = 'example';
          attrs.$set('ngModel', key);
          $compile(element, null, 100)(scope);
      }
    };
  }
]);
这很好,但感觉不对:

  • 我现在必须确保元素上的所有其他指令 能够被重新编译,因为它们都会被编译两次

  • 我必须确保没有人使用更高的优先级

所以这让我想到为什么我不能直接注入ngmodel指令并强制对我的元素编译它

module.directive('input', [
  'ngModelDirective',
  function(ngModel) {
    return {
      restrict: 'E',
      scope: {},
      priority: 100, // Set this high enough to perform other directives
      terminal: true, // Make sure this is the last directive parsed
      require: '?^form',
      link: function(scope, element, attrs, formCtrl) {
          var key = 'example';
          attrs.$set('ngModel', key);
          var ngModelFactory = ngModel[0];
          var ngModelLink = ngModelFactory.compile(element);
          ngModelLink.call(this, scope, element, attrs, [ngModelFactory.controller, formCtrl]);
      }
    };
  }
]);
见:


没有抛出错误,但什么也没有发生。似乎这还不足以连接它,所以我的问题是,有人能详细说明我需要做什么吗?在不强制重新编译的情况下,将
ngmodeldirection
链接到我的自定义指令?

我认为不重新编译是不可能的

ngModel
被设计成同一元素中的其他指令和父表单指令之间的协作者。例如,在编译期间:

  • 其他指令(如输入、必需或ng更改)可将其自身的
    $parser
    $formatter
    添加到ngModel
  • ngModel将自身添加到父窗体指令(如果存在)
因此,如果在复杂化过程结束后以某种方式添加了
ngModel
,则上述两个操作将丢失

编辑:如果要分配给ng模型属性的值在编译时是已知的,则可能是这样的:

app.directive('myNgModel', function($compile) {
  return {
    restrict: 'A',
    replace: false,
    priority: 1000,
    terminal: true, // these terminal and priority will stop all other directive from being compiled.
    link: function (scope, element, attrs) {
      var key = 'example';

      attrs.$set('ngModel', key);
      attrs.$set('myNgModel', null); // remove itself to avoid a recusion

      $compile(element)(scope); // start compiling other directives
    }
  };
});

下面是plunker示例:

ngModel
似乎不适合您尝试的操作。但你无论如何都不需要它。您可以双向绑定某些变量并将名称传递到model指令范围:

app.directive("myDirective", function() {
    // ...
    scope: {
        myModel = "=",
        modelName = "myModel"
        // ...
    }
    // ...
});

app.directive("ngModelDirective", function() {
    // ...
    // ...
    transclude: true,
    link: function(scope, element, attrs) {
        var modelName = scope.modelName;
        console.assert(modelName, '`modelName` must be set when using `ngModelDirective`.');
        // TODO: Check if `scope[modelName]` is actually bound
        doSomethingFancyWith(scope, modelName);
    }
});
模板示例:

<myDirective ngModelDirective my-model="..." />


请注意,
doSomethingFancyWith
可以通过绑定到外部世界来读取和写入模型变量。

我已经成功地做到了这一点。这不是最漂亮的东西,但它可以工作,我可以连接我的
input
指令,使用本机
inputDirective
工作,这样它就可以使用
require
或验证特定的输入类型

要根据另一个实现特定
ngModel
功能(如
ngChange
)的标准指令构建此功能,只需将注入的
inputDirective
替换为正确的指令,如
ngChangeDirective

module.directive('input', function() {
  return {
    restrict: 'E',
    scope: {},
    require: '?ngModel',
    priority: -1,
    link: function(scope, element, attrs, ngModel) {
      var key = 'example.property';

      if (ngModel === undefined) {
        attrs.$set('ngModel', key);
        angular.injector(['ng']).invoke([
          'inputDirective',
          'ngModelDirective',
          '$controller',
          '$exceptionHandler',
          '$parse',
          '$animate',
          function(inputDirective, ngModelDirective, $controller, $exceptionHandler, $parse, $animate) {
            var ngModelFactory = ngModelDirective[0];
            var ngModelLink = ngModelFactory.compile(scope); // Get the ngModel linkage function against this scope
            ngModel = $controller(ngModelFactory.controller, {
              $scope: scope,
              $exceptionHandler: $exceptionHandler,
              $attrs: attrs,
              $element: element,
              $parse: $parse,
              $animate: $animate
            }); // Call the ngModel controller and bootstrap it's arguments
            // Call the inputDirective linkage function to set up the ngModel against this input
            inputDirective[0].link(scope, element, attrs, ngModel);
            element.data('$ngModelController', ngModel); // Allow additional directives to require ngModel on this element.
          }
        ]);
      }
    }
  };
});

注意:这对
ngOptions
不起作用,因为它指定了
terminal:true

我想要
ngModel
的原因是它允许用户在不知道我的语法的情况下扩展它,同时也增加了其他人的代码能够很好地使用它的机会。另外,我还需要使用
$modelValue
$viewValue
。我同意在一个封闭的环境中,我可能会编写一个更有效的解决方案,但这是一个库。@ GoGreReHe你是否考虑过手动实现它,只是简单地复制(一些)源代码和?只是为了让你知道我找到了一个工作解决方案(见)+ 1的帮助。只想让你知道我设法解决这个问题(参见)。1用于指出有关指令特定链接的内容。我会在事先不知道的情况下挣扎。