Javascript AngularJS自定义指令双向绑定在材料升级后损坏

Javascript AngularJS自定义指令双向绑定在材料升级后损坏,javascript,angularjs,angular-material,angular-ngmodel,angular-directive,Javascript,Angularjs,Angular Material,Angular Ngmodel,Angular Directive,我在Angular 1.6.1和material 1.1.1下编写了一个小指令。 它是一个简单的锁定/解锁按钮图标 我不得不将材料更新为1.1.3(对于日期选择器),但从那时起,该指令不再起作用 我不明白为什么材料更新会这样做。。。。 下面的plunker可以工作,但如果将材质版本更改为1.1.2,它将停止工作 index.html: <html lang="en" > <head> <meta name="viewport" content="width=d

我在Angular 1.6.1和material 1.1.1下编写了一个小指令。 它是一个简单的锁定/解锁按钮图标

我不得不将材料更新为1.1.3(对于日期选择器),但从那时起,该指令不再起作用

我不明白为什么材料更新会这样做。。。。 下面的plunker可以工作,但如果将材质版本更改为1.1.2,它将停止工作

index.html:

<html lang="en" >
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.3/angular-material.css">
  <link rel="stylesheet" href="//fonts.googleapis.com/icon?family=Material+Icons">
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-aria.js"></script>

  <script src="//cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.1/angular-material.js"></script>
  <!-- <script src="//cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.1/angular-material.js"></script> -->

  <script src="script.js"></script>

</head>
<body ng-app="app" ng-controller="controller as ctrl">
  <ju-lock ng-model="ctrl.lock"></ju-lock>|{{ctrl.lock}}|
</body>
</html>

|{{ctrl.lock}}|
script.js:

  angular
    .module('app', ['ngMaterial'])
    .directive('juLock', function(){
        return {
            restrict: 'E',
            scope: {
                bindModel: '=ngModel'
            },
            template: 
                '<md-button class="md-icon-button">'+
                '<md-icon class="material-icons">lock_open</md-icon>'+
                '</md-button>|{{bindModel}}',
            link: function(scope, element, attributes){
                element.on('click', function (ev) {
                    scope.bindModel = !scope.bindModel;
                });
                scope.$watch('bindModel', function(){
                    angular.element(element[0].querySelector('.material-icons')).text(scope.bindModel ? 'lock' : 'lock_open');
                });
            }
        };
    })
    .controller('controller', function(){
        var vm = this;
        vm.lock=true;
    });
angular
.module('app',['ngMaterial']))
.directive('juLock',function(){
返回{
限制:'E',
范围:{
bindModel:'=ngModel'
},
模板:
''+
“锁定打开”+
“|{bindModel}}”,
链接:功能(范围、元素、属性){
元素。打开('点击',功能(ev){
scope.bindModel=!scope.bindModel;
});
作用域:$watch('bindModel',function(){
angular.element(元素[0].querySelector('.material icons')).text(scope.bindModel?'lock':'lock_open');
});
}
};
})
.controller('controller',function(){
var vm=这个;
vm.lock=true;
});

在询问stack社区之前,我已经尽可能多地进行了调查,是否有人对此有所了解?

我不确定版本之间的确切问题,但检查一下,这段代码将适用于两个版本

关键点是使用来自angularJs的
ng click
,而不是依赖于
元素。on()
,如果您注入
jQuery
或不注入
jQuery,这可能会有所不同。另外,这种方式更具声明性

我做的唯一改变就是你的指令

.directive('juLock', function(){
        return {
            restrict: 'E',
            scope: {
                bindModel: '=ngModel'
            },
            template: 
                '<md-button ng-click="bindModel = !bindModel" class="md-icon-button">'+
                  '<md-icon class="material-icons">{{lock_text}}</md-icon>'+
                '</md-button>|{{bindModel}}',
            link: function(scope, element, attributes){
              scope.lock_text = '';
                scope.$watch('bindModel', function(){
                    scope.lock_text = scope.bindModel ? 'lock' : 'lock_open';
                });
            }
        };
    })
指令('juLock',函数(){ 返回{ 限制:'E', 范围:{ bindModel:'=ngModel' }, 模板: ''+ “{{lock_text}}”+ “|{bindModel}}”, 链接:功能(范围、元素、属性){ scope.lock_text=''; 作用域:$watch('bindModel',function(){ scope.lock_text=scope.bindModel?'lock':'lock_open'; }); } }; })

我还删除了您手表中的dom检查,我更多地是以角度样式进行检查

避免在自定义指令中使用
ng model
作为属性。如果这样做,不要使用隔离作用域双向绑定。使用该属性实例化的

主要问题是需要通过以下方式通知AngularJS框架范围的更改:

Angular通过提供自己的事件处理循环来修改普通JavaScript流。这将JavaScript分为经典执行上下文和角度执行上下文。只有在角度执行上下文中应用的操作才能受益于角度数据绑定、异常处理、属性监视等。。。用于从JavaScript输入角度执行上下文

请记住,在大多数地方(控制器、服务)
$apply
已由处理事件的指令为您调用。只有在实现自定义事件回调时,或者在使用第三方库回调时,才需要显式调用
$apply

-


也不是操纵DOM来更改锁定和解锁图标。它可以通过和指令完成:

app.directive('juLock', function(){
    return {
        restrict: 'E',
        scope: {
            bindModel: '=myModel'
        },
        template: 
            '<md-button class="md-icon-button">'+
            '<md-icon ng-show="bindModel" class="material-icons">lock</md-icon>'+
            '<md-icon ng-hide="bindModel" class="material-icons">lock_open</md-icon>'+
            '</md-button>|{{bindModel}}',
        link: function(scope, element, attributes){
            element.on('click', function (ev) {
                scope.bindModel = !scope.bindModel;
                //USE $apply
                scope.$apply();
            });
            /*
            scope.$watch('bindModel', function(){
                angular.element(element[0].querySelector('.material-icons')).text(scope.bindModel ? 'lock' : 'lock_open');
            });
            */
        }
    };
})
app.directive('juLock',function(){
返回{
限制:'E',
范围:{
bindModel:'=myModel'
},
模板:
''+
“锁”+
“锁定打开”+
“|{bindModel}}”,
链接:功能(范围、元素、属性){
元素。打开('点击',功能(ev){
scope.bindModel=!scope.bindModel;
//使用$apply
作用域:$apply();
});
/*
作用域:$watch('bindModel',function(){
angular.element(元素[0].querySelector('.material icons')).text(scope.bindModel?'lock':'lock_open');
});
*/
}
};
})

避免在自定义指令中将
ng model
用作属性。如果这样做,不要使用隔离作用域双向绑定。使用该属性实例化的属性。@glorfindel您不需要使用回程机器。感谢您发现,我的机器人无法检测到这种情况,图像已移动到。我的浏览器甚至无法加载,我自己也从未做过角度项目。
app.directive('juLock', function(){
    return {
        restrict: 'E',
        scope: {
            bindModel: '=myModel'
        },
        template: 
            '<md-button class="md-icon-button">'+
            '<md-icon ng-show="bindModel" class="material-icons">lock</md-icon>'+
            '<md-icon ng-hide="bindModel" class="material-icons">lock_open</md-icon>'+
            '</md-button>|{{bindModel}}',
        link: function(scope, element, attributes){
            element.on('click', function (ev) {
                scope.bindModel = !scope.bindModel;
                //USE $apply
                scope.$apply();
            });
            /*
            scope.$watch('bindModel', function(){
                angular.element(element[0].querySelector('.material-icons')).text(scope.bindModel ? 'lock' : 'lock_open');
            });
            */
        }
    };
})