AngularJS 多个指令要求 ngModel
AngularJS Multiple directives asking for ngModel
这是我要完成的 jsfiddle example。
我正在尝试构建一个美国 phone 数字输入,其中视图显示为 (333) 555-1212,但该模型绑定到数字整数 3335551212。
我的目的是将自定义验证器添加到 NgModelController
,这就是我有 require: ng-model
的原因;有没有隔离范围和 NgModelController
的更简单的解决方案,但我需要两者。
您会在控制台中立即看到一个错误:Error: Multiple directives [ngModel, ngModel] asking for 'ngModel' controller on: <input ng-model="user.mobile numeric" name="telephone" type="tel">
-- 以为我在这里使用了隔离范围...
我创建了 this fiddle,它消除了您在控制台中出现的大部分错误。希望这至少能够让您走上正轨。
我更改了模板,以便您可以看到过滤器确实有效。
它现在在文本框下方有纯文本的典型 {{ngModel | FilterName}}
。
唯一真正的问题是在文本框中显示它。我相信你不会有任何问题。我会在早上查看,以防您对此仍有疑问。
编辑:好的,看来您已经解决了。干得好!
感谢您查看@mimir137,但我似乎已经解决了它:
http://jsfiddle.net/hr121r18/8/
指令使用的是 replace: true
,最终结构如下:
<form ng-controller="FooCtrl" class="ng-scope">
<p>Enter US phone number</p>
<input ng-model="user.mobile numeric" name="telephone" type="tel">
</form>
模板和标记都要求 ng-model
,这导致了问题描述中的症状性错误。一旦我删除它,它就会导致这个标记(注意包装元素 phone-number
):
<form ng-controller="FooCtrl" class="ng-valid ng-scope ng-dirty ng-valid-parse" abineguid="BC0D9644F7434BBF80094FF6ABDF4418">
<p>Enter US phone number</p>
<phone-number ng-model="user.mobile" class="ng-untouched ng-valid ng-isolate-scope ng-dirty ng-valid-parse">
<input ng-model="numeric" name="telephone" type="tel" class="ng-valid ng-dirty ng-touched">
</phone-number>
</form>
但是删除这个需要对 $render
进行更改;传递给 link 函数的 elem
现在是 phone-number
,因此您需要挖掘以获取其中的 input
并为其设置值:
ngModel.$render = function () {
elem.find('input').val($filter('phonenumber')(ngModel.$viewValue));
};
还有一些其他问题。 $render()
还需要从观察者调用。
决赛:
var app = angular.module('myApp', []);
// i want to bind user.mobile to the numeric version of the number, e.g. 3335551212, but
// display it in a formatted version of a us phone number (333) 555-1212
// i am trying to make the directive's scope.numeric to have two-way binding with the controller's
// $scope.user.mobile (using isolate scope, etc.).
app.controller('FooCtrl', function ($scope) {
$scope.user = {
mobile: 3335551212
};
});
app.directive('phoneNumber', ['$filter', function ($filter) {
return {
restrict: 'E',
template: '<input ng-model="numeric" name="telephone" type="tel">',
require: 'ngModel',
scope: {
numeric: '=ngModel'
},
link: function (scope, elem, attrs, ngModel) {
// update $viewValue on model change
scope.$watch('numeric', function () {
ngModel.$setViewValue(scope.numeric);
ngModel.$render();
});
// $modelValue convert to $viewValue as (999) 999-9999
ngModel.$formatters.push(function (modelValue) {
return $filter('phonenumber')(String(modelValue).replace(/[^0-9]+/, ''));
});
// $viewValue back to model
ngModel.$parsers.push(function (viewValue) {
var n = viewValue;
if (angular.isString(n)) {
n = parseInt(n.replace(/[^0-9]+/g, ''));
}
return n;
});
// render $viewValue through filter
ngModel.$render = function () {
elem.find('input').val($filter('phonenumber')(ngModel.$viewValue));
};
}
};
}]);
app.filter('phonenumber', function () {
return function (number) {
if (!number) {
return '';
}
number = String(number);
var formattedNumber = number;
var c = (number[0] === '1') ? '1 ' : '';
number = number[0] === '1' ? number.slice(1) : number;
var area = number.substring(0, 3),
exchange = number.substring(3, 6),
subscriber = number.substring(6, 10);
if (exchange) {
formattedNumber = (c + '(' + area + ') ' + exchange);
}
if (subscriber) {
formattedNumber += ('-' + subscriber);
}
return formattedNumber;
}
});
HTML
<form ng-controller="FooCtrl">
<p>Enter US phone number</p>
<phone-number ng-model='user.mobile'></phone-number>
</form>
这是我要完成的 jsfiddle example。
我正在尝试构建一个美国 phone 数字输入,其中视图显示为 (333) 555-1212,但该模型绑定到数字整数 3335551212。
我的目的是将自定义验证器添加到 NgModelController
,这就是我有 require: ng-model
的原因;有没有隔离范围和 NgModelController
的更简单的解决方案,但我需要两者。
您会在控制台中立即看到一个错误:Error: Multiple directives [ngModel, ngModel] asking for 'ngModel' controller on: <input ng-model="user.mobile numeric" name="telephone" type="tel">
-- 以为我在这里使用了隔离范围...
我创建了 this fiddle,它消除了您在控制台中出现的大部分错误。希望这至少能够让您走上正轨。
我更改了模板,以便您可以看到过滤器确实有效。
它现在在文本框下方有纯文本的典型 {{ngModel | FilterName}}
。
唯一真正的问题是在文本框中显示它。我相信你不会有任何问题。我会在早上查看,以防您对此仍有疑问。
编辑:好的,看来您已经解决了。干得好!
感谢您查看@mimir137,但我似乎已经解决了它:
http://jsfiddle.net/hr121r18/8/
指令使用的是 replace: true
,最终结构如下:
<form ng-controller="FooCtrl" class="ng-scope">
<p>Enter US phone number</p>
<input ng-model="user.mobile numeric" name="telephone" type="tel">
</form>
模板和标记都要求 ng-model
,这导致了问题描述中的症状性错误。一旦我删除它,它就会导致这个标记(注意包装元素 phone-number
):
<form ng-controller="FooCtrl" class="ng-valid ng-scope ng-dirty ng-valid-parse" abineguid="BC0D9644F7434BBF80094FF6ABDF4418">
<p>Enter US phone number</p>
<phone-number ng-model="user.mobile" class="ng-untouched ng-valid ng-isolate-scope ng-dirty ng-valid-parse">
<input ng-model="numeric" name="telephone" type="tel" class="ng-valid ng-dirty ng-touched">
</phone-number>
</form>
但是删除这个需要对 $render
进行更改;传递给 link 函数的 elem
现在是 phone-number
,因此您需要挖掘以获取其中的 input
并为其设置值:
ngModel.$render = function () {
elem.find('input').val($filter('phonenumber')(ngModel.$viewValue));
};
还有一些其他问题。 $render()
还需要从观察者调用。
决赛:
var app = angular.module('myApp', []);
// i want to bind user.mobile to the numeric version of the number, e.g. 3335551212, but
// display it in a formatted version of a us phone number (333) 555-1212
// i am trying to make the directive's scope.numeric to have two-way binding with the controller's
// $scope.user.mobile (using isolate scope, etc.).
app.controller('FooCtrl', function ($scope) {
$scope.user = {
mobile: 3335551212
};
});
app.directive('phoneNumber', ['$filter', function ($filter) {
return {
restrict: 'E',
template: '<input ng-model="numeric" name="telephone" type="tel">',
require: 'ngModel',
scope: {
numeric: '=ngModel'
},
link: function (scope, elem, attrs, ngModel) {
// update $viewValue on model change
scope.$watch('numeric', function () {
ngModel.$setViewValue(scope.numeric);
ngModel.$render();
});
// $modelValue convert to $viewValue as (999) 999-9999
ngModel.$formatters.push(function (modelValue) {
return $filter('phonenumber')(String(modelValue).replace(/[^0-9]+/, ''));
});
// $viewValue back to model
ngModel.$parsers.push(function (viewValue) {
var n = viewValue;
if (angular.isString(n)) {
n = parseInt(n.replace(/[^0-9]+/g, ''));
}
return n;
});
// render $viewValue through filter
ngModel.$render = function () {
elem.find('input').val($filter('phonenumber')(ngModel.$viewValue));
};
}
};
}]);
app.filter('phonenumber', function () {
return function (number) {
if (!number) {
return '';
}
number = String(number);
var formattedNumber = number;
var c = (number[0] === '1') ? '1 ' : '';
number = number[0] === '1' ? number.slice(1) : number;
var area = number.substring(0, 3),
exchange = number.substring(3, 6),
subscriber = number.substring(6, 10);
if (exchange) {
formattedNumber = (c + '(' + area + ') ' + exchange);
}
if (subscriber) {
formattedNumber += ('-' + subscriber);
}
return formattedNumber;
}
});
HTML
<form ng-controller="FooCtrl">
<p>Enter US phone number</p>
<phone-number ng-model='user.mobile'></phone-number>
</form>