【问题标题】:AngularJS directive with ng-model, ng-model will not set带有 ng-model 的 AngularJS 指令,不会设置 ng-model
【发布时间】:2015-05-05 18:07:20
【问题描述】:

我想对输入字段应用指令,有一个回调函数,并使用ng-model。当我在指令中使用范围对象时,它消除了ng-model 功能。

    var MyCtrl = ['$scope',
    function($scope,){

        $scope.aModel = 'HELLO!';

        $scope.myFunction = function(item){

            $scope.aModel = '';

        };

    }];

app.directive('myDirective',function(){

    return {
        restrict: 'A',
        scope: {
            myCallback: '&'
        },
        link: function(scope,element,attrs){

            element.bind('keyup',function(){

                scope.myCallback({item: 'test'});
                });
            }
       }
    });

HTML

<input type="text" my-directive my-callback="myFunction(item)" ng-model="aModel" />

Problem Plunkr

【问题讨论】:

  • 你有一个错字。此外,您正在尝试使用回调函数更新模型,但模型绑定到触发该函数的输入控件。你想达到什么目标?

标签: javascript html angularjs angularjs-directive


【解决方案1】:

您可以使用scope.$apply(见此updated Plunkr):

app.directive('myDirective',function(){
return {
    restrict: 'A',
    scope: {
        myCallback: '&'
    },
    link: function(scope,element,attrs){

        element.bind('keyup',function(){

            scope.$apply(function() {
              scope.myCallback({item: 'test'});
            });


        });

    }
}});

由于您使用的是隔离范围,因此该函数发生在控制器的上下文之外,并且除非您强制执行新的摘要循环,否则模型不会更新。

【讨论】:

  • 谢谢,所有答案都很好。我的问题是由过时的 Angular 版本引起的。对浪费的努力感到抱歉。
【解决方案2】:

从孤立作用域调用父作用域方法不会运行摘要循环,您需要手动运行摘要循环。 因此,手动运行摘要循环有三种方法,scope.$evalAsync$timeout$apply() 用于运行摘要循环。 其中$evalAsync is better way to run digest cycle,因为如果任何摘要当前正在进行中,那么$scope.$evalAsync() 表达式将被放置在一个异步队列中,该队列在每次$digest 迭代开始时被刷新。

虽然$apply() & $timeout 函数执行将与当前摘要循环执行发生冲突。

指令

app.directive('myDirective',function(){
return {
    restrict: 'A',
    scope: {
        myCallback: '&'
    },
    link: function(scope,element,attrs){

        element.bind('keyup',function(){
          scope.$evalAsync(function(){
            scope.myCallback({item: 'test'});
          })
        });

    }
}});

Updated Plunkr

【讨论】:

  • 谢谢,所有答案都很好。我的问题是由过时的 Angular 版本引起的。对浪费的努力感到抱歉。
  • 但您必须执行 scope.$evalAsync / $timeout 才能更新绑定,如果对您有帮助,您可以接受答案。
【解决方案3】:

一个选项:

app.directive('myDirective',['$timeout', function($timeout){
return {
    restrict: 'A',
    scope: {
        myCallback: '&'
    },
    link: function(scope,element,attrs){
        element.bind('keyup',function(){
           $timeout(function() {
               scope.myCallback({item: 'test'});
           },10) 
        });
    }
}});

$timeout 自动调用 $apply 阶段。

AntiPattern

检查$scope.$$phase 并明确调用$scope.$apply()

var app = angular.module('myApp',[]);
var MyCtrl = ['$scope',function($scope){
    $scope.aModel = 'HELLO!';
    $scope.myFunction = function(item){
        $scope.aModel = item;
        if (!$scope.$$phase) $scope.$apply();
    };
}];

app.directive('MyCtrl',MyCtrl);

app.directive('myDirective',function(){
return {
    restrict: 'A',
    scope: {
        myCallback: '&'
    },
    link: function(scope,element,attrs){
        element.bind('keyup',function(){
            scope.myCallback({item: 'test'});
        });
    }
}});

DEMO

【讨论】:

【解决方案4】:

我有一个过时的 Angular 版本。以为我输了。升级到 v1.2.27,一切都解决了。我的原始代码工作正常。谢谢大家的回答。

【讨论】:

  • 我相信,添加的 plunkr 也是 angular 1.2.27 的,它不起作用
  • 这里不适用于 1.2.17 plunkr plnkr.co/edit/fzAISgUa7OCQfWoerPz8?p=preview,你是怎么做到的
  • 我还需要 AngularJS 'ngRoute' 库
  • 但是没有$scope.$evalAsync 是如何工作的?你能不能让它在 plunkr 中工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-19
  • 2013-03-13
  • 2020-06-21
相关资源
最近更新 更多