Is there a way in angular to check when a user has typed something into a field.
So when they start typing I can do something like:
console.log('the user has started');
If the field is bound to some variable in the scope (let say foo, you can do the following:
$scope.$watch('foo', function(value){
console.log('the user has started', value);
});
You can use ng-dirty like this:
<form name="myform">
<span ng-show="myform.myinput.$dirty"> the user has started </span>
<input type="text" ng-model="mod" name="myinput" />
</form>
Take a look at this
Related
I have one input field:
<input type="text" name="title" ng-model="genreData.title" class="form-control"
ng-class="{'error': addGenreForm.title.$invalid && !addGenreForm.title.$pristine}"
placeholder="Genre name" ng-minlength="minlength" required autofocus>
When I succesfully submit form this input is got class="error" after this:
$scope.genreData = {};
How can I fix it?
You've got to inject the form in the ng-submit function and then call the form's controller built in function $setPristine().
e.g.
View:
<form name="myForm" ng-submit="submitForm(myForm)">
<!--Input Fields-->
</form>
Controller:
$scope.submitForm = function(form) {
//Do what ever I have to do
//Then reset form
form.$setPristine();
}
I think setting
$scope.addGenreForm.$setPristine() and $scope.addGenreForm.$setUntouched
can work after submitting your form
Please share some plunker so I can help more if you still have any issues
What is the "AngularJS way" of doing a form submit when any of its inputs have been clicked (or changed)?
<form ng-submit="submit($event)" id="myForm">
<input type="checkbox" name="foo" value="bar" ng-click="???"/>
</form>
I'm tempted to use jQuery and simply doing ng-click="$('#myForm').submit()", but it's probably worth learning it properly.
I have tried doing ng-click="submit($event)", but the error here is the $event object within the scope of the input instead of the entire form (correct me if I'm wrong, this is what I'm getting from the documentation).
Well, you can do something like this for sure by triggering the AngularJS submit event:
$scope.change = function($event) {
$timeout(function() {
angular.element($event.target.form).triggerHandler('submit');
});
};
where
<input type="checkbox" name="foo" value="bar" ng-click="change($event)" />
However I think it's better to simply use the same function in ngClick as used in ngSubmit.
Demo: http://plnkr.co/edit/tJIYD9ZVjYzwA2aXJobo?p=preview
ng-change is what worked for me using a text input:
<form>
<select data-ng-model="headerName" data-ng-options="header for header in headers"
data-ng-change="calculateCorrelations()"></select>
</form>
Angular only updates the model from an input[email] after the user has entered a valid email address. How can I add a {{binding}} somewhere on the page that will update with the email value as the user types -- even before the user has typed in a valid email address?
Here's what I've tried so far:
<div ng-app>
<div ng-controller="MyCtrl">
<form name="MyForm" novalidate>
Name: <input type="text" name="name" ng-model="contact.name" /><br/>
Name as you type: {{contact.name}}<br/>
Email: <input type="email" name="email" ng-model="contact.email" /><br/>
Email as you type: {{contact.email}} (doesn't work)<br/>
Also doesn't work: {{$document.forms.MyForm.elements.email.value}}
</form>
</div>
</div>
Controller:
function MyCtrl($scope) {
$scope.contact = {};
}
(fiddle)
The name updates in real-time like I want, but the email doesn't.
I'd like to leave the email validation enabled. I just need some way to bind the un-validated input[email] text, so it updates as the user types.
Update 2014/7/8
I'd like to add an explicit requirement that the type="email" remains unchanged. I do not want to change the semantics of the markup to workaround a limitation of the framework. If need be, I'd rather pull in a complementary dependency (such as jQuery) to shim in the needed functionality.
I'm not opposed to handling validation in the controller — as suggested by rageandqq and charlietfl — if it could be done easily. Looking around though, it looks like it could be tricky (given my requirements).
That is how angularjs works. If you use <input type="email" /> angular is not going to bind your input till input will be valid in this case value must be a proper e-mail address.
please read more here : https://github.com/angular/angular.js/issues/1426
The workaround I've come up with so far is to use jQuery to listen for the input change and update an object on $scope that I've called formRaw. It works. Still, I'm hoping someone will come along and show me a better way.
The updated example:
<div ng-app>
<div ng-controller="MyCtrl">
<form name="MyForm" novalidate>
Name: <input type="text" name="name" ng-model="contact.name" /><br/>
Name as you type: {{contact.name}}<br/>
Email: <input type="email" name="email" ng-model="contact.email" /><br/>
Email Model: {{contact.email}}<br/>
Email Form: {{formRaw.email}}
{{q}}
</form>
</div>
</div>
And controller:
function MyCtrl($scope) {
$scope.contact = {};
$scope.formRaw = {};
$('input[type=email]').on('keyup change', function () {
var input = $(this);
$scope.formRaw[input.attr('name')] = input.val();
$scope.$digest(); // FIXME: there's got to be a better way
});
}
(fiddle)
The type="email" attribute on your E-mail input is what is causing the DOM binding to mess up.
Changing it to type="text" works allows your {{contact.email}} to display correctly.
Edited JSFiddle.
I am trying to check the name of the file before the user hits submit. Can I get the filename like we get the content of the input field?
Something like:
<input name="posterTitle" type="text" ng-model="posterTitle">
{{posterTitle}}
Similarly in:
<input name="posterFileName" ng-model="posterFileName" type="file" />
Using Angularjs you might need to use an onchange event to bind the input name inside controller. see the example :
<input name="posterFileName" type="file" onchange="angular.element(this).scope().fileName(this)"/>
Inside controller
$scope.fileName= function(element) {
$scope.$apply(function($scope) {
$scope.posterTitle= element.files[0].name;
});
};
Hope this will help.
a couple of links I've found that may help a bit:
http://api.jquery.com/file-selector/
jQuery: get the file name selected from <input type="file" />
for example, sing name or ID attribute:
$('input[type=file]').change(function(e){
$in=$(this);
$in.next().html($in.val());
});
Ok, so I am creating a form like so:
<form novalidate class="simple-form" action="" name="mainForm" ng-submit="doSubmit()" method="POST">
<div ng-form name="giftForm" class="panel-body">
<input type="text"
id="x_amount"
name="x_amount"
class="form-control input-lg"
ng-model="giftForm.amount"
ng-required="true">
</div>
<div class="row">
<button type="submit" class="btn" ng-disabled="mainForm.$invalid">Submit</button>
</div>
</form>
This works for validation, i.e. that mainForm.$invalid only highlights enables the button after the input has text. However, using batarang, I noticed that the scope looks like so:
{"giftForm":{"x_amount":{},"amount":"a"}}
So it is creating model values based on the name and the declared ng-model. If I change them to be the same like so:
<input type="text"
id="x_amount"
name="x_amount"
class="form-control input-lg"
ng-model="giftForm.x_amount"
ng-required="true">
The submit shows the correct scope of:
{"giftForm":{"x_amount":"a"}}
But the input field initially shows with [Object object] in the input, which makes me think I am confusing something here..... I can't have that in all of the input fields.
I'd like the name and the model to be the same. That would seem to be the progressive enhancement way and would allow a normal non-ajax post by simply removing the ng-submit method and the ajax way would look like:
$http({
method : 'POST',
url : 'formAction.do',
data : $.param(angular.toJson($scope.mainForm)),
headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
})
.success(function(data) {
//success
})
.error(function(data, status, headers, config) {
//error
});
Anybody has insight into what I am missing or if my architecture is flawed from the ground-up, I'd appreciate the wisdom....
I'd like the name and the model to be the same.
You could do that, but you'd have to have a separate scope, and therefor a separate controller for your form.
More importantly, though, this isn't going to buy you anything. The input name attributes are primarily used for validation display, and not much else.
Your use of $http concerns me more. It looks like you're thinking in a JQuery mindset. I'd challenge you to throw JQuery out the window for a while until you get used to Angular.
Here's what people generally do with forms (From the model structure to the naming and validation):
View:
<form name="myForm" ng-submit="sendFoo()">
<div>
<label for="name">name</label>
<input type="text" id="name" name="name" ng-model="foo.name" required/>
<span ng-show="myForm.name.$error.required">required</span>
</div>
<div>
<label for="email">email</label>
<input type="email" id="email" name="email" ng-model="foo.email" required/>
<span ng-show="myForm.email.$error.required">required</span>
<span ng-show="myForm.email.$error.email">invalid email</span>
</div>
<button type="submit" ng-disabled="myForm.$invalid">Submit</div>
</form>
Controller:
app.controller('MyCtrl', function($scope, $http) {
$scope.foo = {
name: 'Someone Special',
email: 'test#monkey.com'
};
$scope.sendFoo = function (){
$http.post('/Some/Url/Here', $scope.foo)
.then(function(result) {
$scope.result = result.data;
});
});
});
You'll notice that the name of the form and the names of the inputs are only used for validation on those <span> tags. Like so: <span ng-show="[formName].[fieldName].$error.[validationName]">invalid message</span>. That object is available on the $scope at $scope.formName, but there usually isn't a reason to access it directly in your controller.
I hope this helps you (or someone).
Naming a form places a variable in scope with that name. Under it, it puts properties named after the form fields names. However, you already have a model in the scope with the same name as the form: giftForm. This causes confusion: the template overwrites the model and/or vice versa.
So, give another name to one of them, eg name the model giftModel.