我创建了自定义指令来封装 uib-datepicker-popup:
'use strict';
angular.module( 'frontendApp' )
.directive( 'inputDate', function(){
var controller = function(){
var vm = this;
function init() {
vm.formats = [ 'dd.MMMM yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate' ];
vm.format = vm.formats[ 0 ];
vm.altInputFormats = [ 'M!/d!/yyyy' ];
vm.dateOptions = {
datepickerMode: 'day',
formatYear: 'yy',
maxDate: new Date(),
minDate: new Date( 1900, 1, 1 ),
startingDay: 1
};
vm.datepicker = {
opened: false
};
};
init();
vm.showDatePicker = function(){
vm.datepicker.opened = true;
};
};
var template = '<div ng-switch on="readonly" >' +
'<div ng-switch-when="true" class="form-control" readonly>' +
'<div readonly name="readonlyText">{{ngModel | date : \'d.MMMM yyyy\'}}</div>' +
'</div>' +
'<div ng-switch-default class="input-group">' +
'<input class="form-control" type="text" uib-datepicker-popup="{{vm.format}}" ng-model="ngModel" ng-model-options="{timezone:\'UTC\'}" is-open="vm.datepicker.opened" datepicker-options="vm.dateOptions" ng-required="true" show-button-bar="false" alt-input-formats="vm.altInputFormats" />' +
'<span class="input-group-btn">' +
'<button type="button" class="btn btn-default" ng-click="vm.showDatePicker()"><i class="glyphicon glyphicon-calendar"></i></button>' +
'</span>' +
'</div>' +
'</div>';
return{
controller: controller,
controllerAs: 'vm',
bindToController: true,
template: template,
restrict: 'EA',
scope :true,
require:'ngModel',
link: function( scope, element, attrs, ngModel ){
// Bring in changes from outside:
scope.$watch( 'ngModel', function(){
if( ngModel ) {
scope.$eval( attrs.ngModel + ' = ngModel' );
}
} );
// Send out changes from inside:
scope.$watch( attrs.ngModel, function( val ){
if( val ) {
scope.ngModel = val;
}
} );
if( attrs.readonly === 'true' ) {
scope.readonly = true;
}
}
};
} );
html 部分是:
<input-date ng-model="form.flight.date"></input-date>
问题:如果出现弹出窗口,则表明scope.ngModel已从attrs.ngModel正确初始化。我在观察器内有一个日志,它向我显示观看 attrs.ngModel 工作得很好,但是观看“ngModel”或scope.ngModel 只能在我使用日期选择器之前工作。只要不触发日期选择器,它就可以完美工作。 刚刚发现,如果我删除它,它会完美地工作 “ng-switch-default”。将其替换为 ng-show/ng-hide 可使指令完全按预期工作。
谁能解释一下为什么吗?
最佳答案
您看到的行为绝对正确。当您使用 ng-if
、ng-switch
、ng-repeat
等结构指令时,它会创建一个新作用域并复制父范围的所有属性。您的模型是一个基元(字符串),因此它会完全复制到新范围并在此范围内进行更改,而不会传播到父级模型。
你能做的是:
- 使用对象而不是字符串来传递
ng-model
,我个人觉得这里很尴尬 - 从 Controller 对象而不是范围中使用
ng-model
继续使用第二种方法:您已经使用了 bindToController
和一个通过 scope: true
隔离的作用域,因此不必使用观察者跟踪模型,而是将其绑定(bind)到 Controller :
return {
bindToController: true,
scope: {
ngModel: '='
},
...
所以理想情况下,您甚至不需要链接功能并在模板中代替
'<div readonly name="readonlyText">{{ngModel | date : \'d.MMMM yyyy\'}}</div>'
使用
'<div readonly name="readonlyText">{{vm.ngModel | date : \'d.MMMM yyyy\'}}</div>'
为什么 ng-hide
仍然有效?它不会创建新的范围。
关于javascript - 自定义 Angular Directive(指令)中的 ng-switch 打破了双向绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36665000/