问题
Does ngModel controller in directive have any option to show something different from ngModel value in view, or i have to write custom html directive for input?
I wrote a comma-separator directive. everything is fine, but ngModel value change from Number to String with ,
.
I mean can i have input with value 1000000
but it shows 1,000,000
in view?
Update:
In the input box shows 1,000,000
, but its value be 1000000
.
Update 2
I know about $formatters
and $parsers
. but the problem is $formatters
doesn't harm real value, but it works when ngModel changed directly, not by typing in input element, and $parsers
watch all changes, but change real value too.
回答1:
use filter to achieve this
HTML
<div ng-controller="demoController">
<input type="text" value="{{val | number}}">
</div>
controller:
var app = angular.module('demoApp', []);
app.controller('demoController', ['$scope', '$http', function($scope, $http, $cookies, $location){
$scope.val = 1000000;
}]);
回答2:
You can use ngModel.$formatters
:
ngModel.$formatters.push(function (number) {
return convertToCommaSeparatedString(number);
});
In this case model will remain number but input will show formatted string.
See documentation
回答3:
To answer your question...
"I mean can i have input with value 1000000 but it shows 1,000,000 in view?"
I'm assuming you want a Number as the model, but a comma separated String in the input as the user types. Based on this assumption, I can answer your question with a YES, you can do this; here's how...
Link: CodePen Working Example
NOTE
This example is created in a way that will only allow digits to be entered in to the input. You can change this as you like in each $filter.
Also a word of caution to only use filters that you create that clean the data when it enters the filter. Angular filters are mostly for static values, so they don't work when you want to filter values as they are entered.
i.e. In this case, if we didn't clean the data by removing (/\D/g) all non-digits, we would be splitting, joining, and reversing with commas (and anything else) in the string and the result would crash.
HTML
<div ng-app="myApp" ng-controller="myCtrl">
<input ng-model="inputValueModel" type="text" format-my-view-only />
Model Value is Number: {{ inputValueModel || "Empty" }}
</div>
JS
var app = angular.module("myApp", []).controller("myCtrl", function($scope){});
app.directive("formatMyViewOnly", function($filter){
// You don't have to use $filter, you can do inline work as well as
// functions inside of this directive. I use $filters for code reuse.
return {
require: "ngModel",
restrict: "A",
link: function(scope, elem, attrs, input){
input.$parsers.push(function(value){
value = $filter("addCommas")(value);
input.$setViewValue(value); // Set view value.
input.$render();
// Then return Number to model.
return +$filter("onlyNumbers")(value); // Unary Operator converts string to Number. Remove it if you want model to be a string as well.
});
} // end link.
}; // end return.
});
app.filter('onlyNumbers', function(){
return function(numbers){
if(invalid(numbers)){ return ""; }
return numbers.replace(/\D/g, "");
};
function invalid(number){
return !number || notString(number) || noNumbersExists(number);
}
function notString(string){
return typeof string != "string";
}
function noNumbersExists(number){
return number.replace(/\D/g, "").length === 0;
}
});
app.filter('addCommas', function(){
return function(stringOfNums){
if(invalid(stringOfNums)){ return ""; }
return commaSeparated(stringOfNums.replace(/\D/g, ""));
};
function commaSeparated(numbers){
if(!numbers){return "";}
return numbers.split("").reverse().join("")
.match(/.{1,3}/g).reverse().join(",");
}
function invalid(number){
return !number || notString(number) || noNumbersExists(number);
}
function notString(string){
return typeof string != "string";
}
function noNumbersExists(number){
return number.replace(/\D/g, "").length === 0;
}
});
来源:https://stackoverflow.com/questions/35066118/angular-ngmodel-different-view-and-value