I have an input field in a form with some validations. It works like a charm.
It basically looks like this:
<input
class="form-control"
type="number"
ng-model="zipcode"
ng-minlength="5"
ng-maxlength="5"
id="zipcode"
name="zipcode"
required
>
A working plunkr is here: http://plnkr.co/edit/H0h59kG75T5MGE9cAhSo?p=preview
But now I also want to react to every input change - whether valid or not. So for example if the input field contains "123" it is not valid and the value is not transferred to my model - thats fine. But I still want to get the value to do some intermediate requests to a webservice.
Any Ideas?
First call the form element in your controller, then use the $viewValue attribute :
View :
<form name="form">
<input
...
ng-model="zipcode"
ng-change="getRawValue(form)"
name="zipcode"
required
>
</form>
Controller:
$scope.getRawValue = function(form) {
var rawValue = form.zipcode.$viewValue;
}
Angular 1.3 introduced a real answer for this: allowInvalid in ngModelOptions.
Example:
<input
type="text"
name="userName"
ng-model="user.name"
ng-model-options="{allowInvalid: true}"
>
Here is what i came up with for your scenario.
Basically you can write a directive which requires ngModel (ngModelController). The ngModelController has a array of parsers which it call to parse the view value in a pipeline manner. If validation fail these parsers do not update the model. If you inject a custom parser at the start of this parsers array, you can get the each view change value and do anything you want with it.
See my plunkr here http://plnkr.co/edit/ruB42xHWj7dBxe885OGy?p=preview (See console)
The basic code would be
ngModelCtrl.$parsers.splice(0,0,(function (viewValue) {
console.log("The view value is:"+viewValue)
return viewValue;
}));
Also see ngModelController documenation
Related
In my Angular app, I'm setting the placeholders in my form through some code in the controller (showing particular text for particular times of day).
When a user begins typing into any field of that form, I want all placeholders to be cleared.
To do this I understand I need to use $dirty using $watch
$scope.$watch('myForm.$dirty', function() {
//clear the placeholders
}, true);
My question is watch quite performance intensive in this situation or is there a more optimised way?
Thanks.
If you use $dirty and $watch it will work but it will clear all placeholders before you begins type or on controller load.
So, you can try this its work for me.
<div ng-controller="Ctrl">
<input type="text" ng-model="name1" ng-change="change()" placeholder={{placeholder1}}>
<input type="text" ng-model="name2" ng-change="change()" placeholder={{placeholder2}}>
<input type="text" ng-model="name3" ng-change="change()" placeholder={{placeholder3}}>
</div>
function Ctrl($scope) {
$scope.placeholder1="name";
$scope.placeholder2="city";
$scope.placeholder3="address";
$scope.change=function() {
$scope.placeholder1="";
$scope.placeholder2="";
$scope.placeholder3="";
};
}
I'm having an issue on updating or assigning the value or data into the model using ng-value.
I would like to copy any values in the DisplayName model to CopyDisplayName and using below directives i was able to do that, But the problem is the model CopyDisplayName doesn't have any value when I submit my changes. It can only have if I inputted it manually.
<input type="Text" ng-model="DisplayName" ng-disabled="true" />
<input type="Text" ng-model="CopyDisplayName" ng-value="DisplayName" />
Forgot to include that the DisplayName is disabled.. the data will came from service call.
ngValue
Binds the given expression to the value of or input[radio], so that when the element is selected, the ngModel of that element is set to the bound value.
You can take a look in this documentation.
So basically, the one you're doing right now will not work.
You can do this in your angular controller:
$scope.copyValue = function () {
$scope.copyDisplayName = $scope.displayName;
}
In html:
<input type="text" ng-model="displayName" ng-change="copyValue()" />
Just assign one variable to another:
// in the controller
$scope.CopyDisplayName = $scope.DisplayName;
If you need to keep them in sync (and for some reason, you don't want to just use the same variable), then you can keep them updated via ng-change:
<input type="Text" ng-model="DisplayName" ng-change="CopyDisplayName = DisplayName" />
Directives like ng-value (or ng-checked) only toggle the attributes in the DOM - they do not alter the View Model.
You can add $watch on DisplayName as:
$scope.$watch('DisplayName',function(newValue, oldValue){
console.log(newValue +":"+oldValue)
$scope.CopyDisplayName = newValue;
});
To have copy updated you need copy value by reference. For that you need to wrap displayName to object:
$scope.model = {DisplayName: 'val'}; and make a copy of it: $scope.modelCopy = $scope.model;
<input type="Text" ng-model="model.DisplayName" ng-disabled="true" />
<input type="Text" ng-model="modelCopy.DisplayName" ng-value="DisplayName" />
JSFiddle
what you can do in controller is watch the model and copy that value whenever it is changed($watch will do that for you) you dont need ngChange on the HTML.
$scope.$watch('displayName', function() {
$scope.copyDisplayName = $scope.displayName;
});
In my custom directive, I need to update the validity of another input. The directive is something like this :
<customDirective="foo">, in which the value foo is the name of another ngModel.
In my direcitve, I can get its model by :
var foo = scope[attrs.foo];.
But how can I get its ngModelController, to set its validity? Just like this :
fooModelController.$setValidity('customDirective', true);
EDIT :
In html, the input is defined as :
<input type="text" name="dateDebut" id="dateDebut" class="form-control" ng-model="formData.dateDebut" customDirective="dateFin" required>
<input type="text" name="dateFin" id="dateFin" class="form-control" ng-model="formData.dateFin" customDirective="dateDebut" required>
I get the dom node by angular.element.find(document.querySelctor('#dateDebut'));
angular.element(document.querySelctor('#dateDebut')).controller('ngModel') -- this will give the ngModelController defined on #dateDebut element.
Here is the plnkr: http://plnkr.co/edit/qXyxEb2QHyhuRUttNMXn?p=preview
I'm looking to do use some of the validation features in an Angular Directive that I am building up. However, the directive may or may not be inside of a form. Is there a way to access the validation status of a model without trying to access the state of a form?
My template is along the lines of....
<select id="{{$id}}key" ng-model="newItem.key"
ng-options="key as key.label for key in tableKeys" required>
</select>
<span class="error" ng-show="newItem.key.$error.required">Required!</span>
<input id="{{$id}}value" type="text" ng-model="form.newItem.value" required/>
<span class="error" ng-show="newItem.value.$error.required">Required!</span>
<button ng-click="addItem()">Add Item</button>
(Not seeing any validation messages here)
On top of it, I want to addItem to check the state of validation as well
$scope.addItem = function(){
if(<do something to check validation>)
{
<do some other thing>
}
Any help would be much appreciated!
Thanks,
Andrew
My understanding is that you want to avoid using the form.xyz.$error attributes for error checking.
I do not know how to do it using a directive, but I do know how to do it using the controller.
In that case, you can use the $scope.$watch function on your model.
It would be something like this:-
1.) In your controller,
$scope.$watch('newItem.key',function(){
if( <condition to validate> ==true)
{
$scope.selectError ="errorMessage";
}
});
2.) In your HTML
<select id="{{$id}}key" ng-model="newItem.key"
ng-options="key as key.label for key in tableKeys" required>
</select>
<span class="error" ng-show="selectError">{{selectError}}</span>
Note: This is only for the select element. You can bind the text input to a model, and do the same for it as well.
The $scope.$watch function will watch out for any changes to the specified model, and will execute the accompanying code whenever any change occurs.
Is there anyway that I can bind two model values to one input field?
Suppose I have input field which I want to be the value of two variables in the scope something like:
<input type="text" model="sn_number; id" >
You cannot, but there are some workarounds.
1. Use ngChange to update the other model
<input type="text"
ng-model="sn_number"
ng-change="id=sn_number"/>
2. You could watch a model, and when in changes, update another
$scope.$watch('sn_number', function(v){
$scope.id = v;
});
You would need to watch also for changes in id if you want to keep them in sync.
Example here
You can bind fields immediately, not only in ng-change, and actually it isn't data binding, its only angular expression
<label>Name</label>
<input type="text" ng-model="name" value="{{name}}"/>
<label>Key</label>
<input type="text" ng-model="key" value="{{key=name}}" />
It would make no sense to bind an input to two variables in the model. Binding works both ways, so if the model is updated, the field is updated and vice-versa. If you were to bind to two variables, what would be the single source of truth?
However you can use ng-change to call a method on the controller which can set two variables when the field changes.
with ng-init
<div ng-controller="ctrl" ng-init="model = { year: '2013', month:'09'}">
or
<div ng-repeat="c in contact" ng-init="likes = { food: 'steak', drink:'coke'}">