AngularJS:无法使用 ngModelController $formatters 格式化 null 或未定义的值
AngularJS: Unable to format null or undefined value with ngModelController $formatters
我有一个 AngularJS 指令,它包含一个文本输入,它有自己的模型,通过指令的 ng-model 从控制器范围传递一个值。
看看这支笔(和下面的代码):http://codepen.io/ericwshea/pen/KwXRyr
问题是有时该模型恰好是空值或未定义值,在这种情况下,我想使用文本输入的 ngModelController 将文本输入中空值的显示格式化为 'NULL'。
如果该值是我在格式化程序中匹配的某个任意字符串,它会起作用,但如果该值是 null(我也用未定义的相同结果进行了测试)。
关于此的任何 insight/workaround,或者这只是 $formatters 的缺点?
HTML:
<div ng-app="app" class="container">
<div ng-controller="ctrl" class="col-md-12">
<form>
<input-directive ng-model="model"></input-directive>
<input-directive ng-model="model2"></input-directive>
<div ng-if="model">Model 1: {{model}}</div>
<div ng-if="model2">Model 2: {{model2}}</div>
</form>
</div>
</div>
JAVASCRIPT:
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.model = null;
$scope.model2 = 'make this null';
})
.directive('inputDirective', function() {
var template =
'<div>'+
'<div class="input-group">'+
'<input type="text" class="form-control" ng-model="localModel">'+
'<span class="input-group-btn">'+
'<button ng-click="save()" class="btn btn-default" type="button">Save</button>'+
'</span>'+
'</div>'+
'</div>';
function link (scope, elem, attr) {
var inputModelCtrl = elem.find('input').controller('ngModel');
function formatter(val) {
if (val === 'make this null') {
return scope.nullValue;
}
if (val === null) {
return scope.nullValue;
}
return val;
}
scope.nullValue = 'NULL';
scope.localModel = scope.ngModel;
scope.save = function() {
scope.ngModel = scope.localModel;
}
inputModelCtrl.$formatters.push(formatter);
}
return {
restrict: 'E',
replace: true,
require: 'ngModel',
template: template,
link: link,
scope: {
ngModel: '='
}
}
})
;
我设法找到了解决方法。我在创建指令时通过在 ngModel 上放置一个 watch 来初始化值,捕获 null 并使其成为 'NULL',angular $formatters 将实际格式化。我将 localModel 的视图值格式化为 ,它起作用了。
为了确保当我将 'NULL' 从指令发送回控制器范围时模型值是正确的,我在 ngModelController 上使用 $parser 来监视 'NULL' 并转换它为空。
为了使它完整循环,ngModel 指令中的 $watch 使得如果值在指令之外设置为 null,则 localModel 将重新初始化为 'NULL' 并格式化为适当的显示。
这可能看起来很荒谬,但实际的现实世界指令是自定义 select 菜单,如您所想,它需要此功能。
您可以在此处查看更改:http://codepen.io/ericwshea/pen/KwXRyr
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.model = null;
$scope.getModel = function() {
return $scope.model === null ? 'null' : $scope.model;
}
$scope.setToNull = function() {
$scope.model = null;
}
})
.directive('inputDirective', function() {
var template =
'<div>'+
'<div class="input-group">'+
'<input type="text" class="form-control" ng-model="localModel">'+
'<span class="input-group-btn">'+
'<button ng-click="save()" class="btn btn-default" type="button">Save</button>'+
'</span>'+
'</div>'+
'</div>';
function link (scope, elem, attr, ngModelCtrl) {
var inputModelCtrl = elem.find('input').controller('ngModel');
var nullDisplay = '<NULL>';
function ngModelParser(val) {
if (val === 'NULL') return null;
return val;
}
function localModelFormatter(val) {
if (val === 'NULL') return nullDisplay;
return val;
}
scope.save = function() {
ngModelCtrl.$setViewValue(scope.localModel);
console.log(ngModelCtrl.$modelValue);
}
scope.$watch('ngModel', function(val) {
if (val === null) val = 'NULL';
scope.localModel = val;
})
inputModelCtrl.$formatters.push(localModelFormatter);
ngModelCtrl.$parsers.push(ngModelParser);
}
return {
restrict: 'E',
replace: true,
require: 'ngModel',
template: template,
link: link,
scope: {
ngModel: '='
}
}
})
;
我希望这对遇到类似问题的任何人有所帮助,即使这种情况非常具体(具体到我不得不自己回答!)
我有一个 AngularJS 指令,它包含一个文本输入,它有自己的模型,通过指令的 ng-model 从控制器范围传递一个值。
看看这支笔(和下面的代码):http://codepen.io/ericwshea/pen/KwXRyr
问题是有时该模型恰好是空值或未定义值,在这种情况下,我想使用文本输入的 ngModelController 将文本输入中空值的显示格式化为 'NULL'。
如果该值是我在格式化程序中匹配的某个任意字符串,它会起作用,但如果该值是 null(我也用未定义的相同结果进行了测试)。
关于此的任何 insight/workaround,或者这只是 $formatters 的缺点?
HTML:
<div ng-app="app" class="container">
<div ng-controller="ctrl" class="col-md-12">
<form>
<input-directive ng-model="model"></input-directive>
<input-directive ng-model="model2"></input-directive>
<div ng-if="model">Model 1: {{model}}</div>
<div ng-if="model2">Model 2: {{model2}}</div>
</form>
</div>
</div>
JAVASCRIPT:
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.model = null;
$scope.model2 = 'make this null';
})
.directive('inputDirective', function() {
var template =
'<div>'+
'<div class="input-group">'+
'<input type="text" class="form-control" ng-model="localModel">'+
'<span class="input-group-btn">'+
'<button ng-click="save()" class="btn btn-default" type="button">Save</button>'+
'</span>'+
'</div>'+
'</div>';
function link (scope, elem, attr) {
var inputModelCtrl = elem.find('input').controller('ngModel');
function formatter(val) {
if (val === 'make this null') {
return scope.nullValue;
}
if (val === null) {
return scope.nullValue;
}
return val;
}
scope.nullValue = 'NULL';
scope.localModel = scope.ngModel;
scope.save = function() {
scope.ngModel = scope.localModel;
}
inputModelCtrl.$formatters.push(formatter);
}
return {
restrict: 'E',
replace: true,
require: 'ngModel',
template: template,
link: link,
scope: {
ngModel: '='
}
}
})
;
我设法找到了解决方法。我在创建指令时通过在 ngModel 上放置一个 watch 来初始化值,捕获 null 并使其成为 'NULL',angular $formatters 将实际格式化。我将 localModel 的视图值格式化为 ,它起作用了。
为了确保当我将 'NULL' 从指令发送回控制器范围时模型值是正确的,我在 ngModelController 上使用 $parser 来监视 'NULL' 并转换它为空。
为了使它完整循环,ngModel 指令中的 $watch 使得如果值在指令之外设置为 null,则 localModel 将重新初始化为 'NULL' 并格式化为适当的显示。
这可能看起来很荒谬,但实际的现实世界指令是自定义 select 菜单,如您所想,它需要此功能。
您可以在此处查看更改:http://codepen.io/ericwshea/pen/KwXRyr
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.model = null;
$scope.getModel = function() {
return $scope.model === null ? 'null' : $scope.model;
}
$scope.setToNull = function() {
$scope.model = null;
}
})
.directive('inputDirective', function() {
var template =
'<div>'+
'<div class="input-group">'+
'<input type="text" class="form-control" ng-model="localModel">'+
'<span class="input-group-btn">'+
'<button ng-click="save()" class="btn btn-default" type="button">Save</button>'+
'</span>'+
'</div>'+
'</div>';
function link (scope, elem, attr, ngModelCtrl) {
var inputModelCtrl = elem.find('input').controller('ngModel');
var nullDisplay = '<NULL>';
function ngModelParser(val) {
if (val === 'NULL') return null;
return val;
}
function localModelFormatter(val) {
if (val === 'NULL') return nullDisplay;
return val;
}
scope.save = function() {
ngModelCtrl.$setViewValue(scope.localModel);
console.log(ngModelCtrl.$modelValue);
}
scope.$watch('ngModel', function(val) {
if (val === null) val = 'NULL';
scope.localModel = val;
})
inputModelCtrl.$formatters.push(localModelFormatter);
ngModelCtrl.$parsers.push(ngModelParser);
}
return {
restrict: 'E',
replace: true,
require: 'ngModel',
template: template,
link: link,
scope: {
ngModel: '='
}
}
})
;
我希望这对遇到类似问题的任何人有所帮助,即使这种情况非常具体(具体到我不得不自己回答!)