I made the following code (jsFiddle) to get the input of a text field:
var app = angular.module('myApp', [
'my.controllers'
]);
var controllers = angular.module('my.controllers', []);
controllers.controller('MyController', function($scope) {
});
controllers.controller('listdata', function($scope, $http) {
$scope.editItem = function(event) {
var fieldTitle = $(event.currentTarget).attr("data-id");
var fieldValue = event.target.value;
console.log(fieldTitle + " : " + fieldValue);
};
})
In this case the function only returns the field name and field value of which the text is changed. What is the correct way to get all values of all input fields, when one of the fields is changed?
Regarding to your question
"What is the correct way to get all values of all input fields, when one of the fields is changed?",
this fiddle shows you one of the correct ways to get all the results on field change.
The basic idea is to use ng-model directive for input fields: in fact, your code
var fieldTitle = $(event.currentTarget).attr("data-id");
var fieldValue = event.target.value;
It's a sign you are not thinking in a angular way (and i suggest you to read this excellent answer to get an idea of what you should do).
The solution
Use ng-model to bind your variables to your scope, and ng-change to intercept changes in them:
<input type="text" ng-model="id" ng-change="editItem(id)">
<input type="text" ng-model="title" ng-change="editItem(title)">
<input type="text" ng-model="number" ng-change="editItem(number)">
and in your controller:
$scope.editItem = function (value) {
console.log("currentValue" + value);
console.log("ID:" + $scope.id + " Title: " + $scope.title +" Number:" + $scope.number);
};
First of all you have'nt used ng-model directive in your input box hence it will definetly give error if you use ng-change and ng-blur on that particular input.
<input type="text" data-id="id" ng-model="itemList.input1" ng-change="editItem()">
<input type="text" data-id="title" ng-model="itemList.input2" ng-blur="editItem()">
<input type="text" data-id="number" ng-model="itemList.input3" ng-blur="editItem()">
Here is an
jsfiddle where i have console.log a object which returns you all three values when blur or change from a input.
Related
I will have N number of input fields and every field will have a value CHANGE without getting in or out of focus. How can I detect value change of every input field.
I only found one question related and using that I tried following but it is not working. can Any one help further
for (var i=0;i<$scope.customers.product.length;i++)
{
//i m trying to get unique ids and bining input fields for change
$('#total-i').on('input', function() {
alert($(this).val()); // get the current value of the input field.
});
}
//there will be multiple of input fields having unique ids
<input id="total-{{$index}}" value={{cust.price*cust.quantity}}"/>
It should be easy and possible with ng-change provided you have ng-model associated to input.
<input id="total-{{$index}}" value={{cust.price*cust.quantity}}" ng-model="total" ng-change="updatemethod()"/>
total and updatemethod() should be part of controller $scope.
I'd create an object to associate with the ng-model and then watch it. Since you didn't provide a Codepen of fiddle instance to meddle with, I'm not sure this works, check it out.
//for each index
$.each(modelObject, function(key, value) {
//set a watcher
var watchString = "modelObject[" +key + "]";
$scope.$watch(watchString, function (newValue, oldValue) {
$scope.update(modelObject[key]);
});
});
The question you linked in your question is not about Angular (it uses jQuery). Where is the Angular way to do it (considering you are showing inputs with ng-repeat):
<div ng-repeat="i in items">
<input ng-model="i" ng-change="update(i)"/>
</div>
With this code, whenever you will update i (eg: when you will change the input value), the update(i) method will be triggered.
Here is a tiny example of what I'm explaining:
function MyCtrl($scope) {
$scope.items = ['1', '2', '3', '4', '5'];
$scope.update = function(item) {
alert(item + ' has been changed!');
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="MyCtrl">
<div ng-repeat="i in items">
<input type="text" ng-model="i" ng-change="update(i)" />
</div>
</div>
I'm building an angular directive, where I have two number inputs and both together represent an age range.
What I want to achieve is being able to use this directive the following way:
<input-age-range
name="ageRange"
ng-model="filterUpdateVM.ageRange">
</input-age-range>
<span ng-if="myCtrlVM.form.ageRange.$error.ageRange">
Please, enter a valid age range.
</span>
and be able to show a custom error when the entered age range is not correct.
My directive html template looks this way:
<div class="col-md-3">
<input type="number"
class="form-control"
placeholder="Minimum age"
name="ageMin"
min="18"
max="80"
ng-change="checkAndValidateAgeRange()"
ng-model="ageRange.ageMin"
ng-model-options="{allowInvalid: true}">
</div>
<div class="col-md-3">
<input type="number"
class="form-control"
placeholder="Maximum age"
name="ageMax"
min="18"
max="80"
ng-change="checkAndValidateAgeRange()"
ng-model="ageRange.ageMax"
ng-model-options="{allowInvalid: true}">
</div>
Every time the user types anything in an input, I wish to check the if the entered range is correct:
Both ages should be numbers
Both ages should be between 18 and 80
ageMin <= ageMax
So far ng-model-options="{allowInvalid: true}" will let the ngChange function inside my directive to be triggered in case any of the ages entered is not between the desired age range (18-80) - this way I can do some checking and set an input error if there's any and show it.
My problem here is that if the age entered at first is not a number, ngChange is not called: it won't be able to do the error checking so there won't be any errors to be shown. How can I have my ngChange function called in this case, without changing my input type="number"?
EDIT: Jsfiddle added: http://jsfiddle.net/afkf96qh/
Finally after a day of trying to figure out what was going on, I achieved the behavior I was looking for.
First of all, ng-model-options="{allowInvalid: true}" had nothing to do in solving my problem, so I removed that out of my input. My directive html template looks this way now:
<div class="col-md-3">
<input type="number"
class="form-control"
placeholder="Minimum age"
name="ageMin"
min="18"
max="80"
ng-model="ageRange.ageMin"
ng-change="checkAndValidateAgeRange()">
</div>
<div class="col-md-3">
<input type="number"
class="form-control"
placeholder="Maximum age"
name="ageMax"
min="18"
max="80"
ng-model="ageRange.ageMax"
ng-change="checkAndValidateAgeRange()">
</div>
The problem that caused not triggering ng-change="checkAndValidateAgeRange()" was the way I was initializing the ageRange variable at the ngModel $render function:
angular
.module('myModule')
.directive('myDirective', myDirective);
function myDirective() {
var directive = {
templateUrl: 'myTemplate.html',
restrict: 'E',
require: ['^form', 'ngModel'],
link: linkFunc
};
return directive;
/////////
function linkFunc(scope, element, attrs, ctrls) {
scope.form = ctrls[0];
scope.ageRange = {};
scope.checkAndValidateAgeRange = checkAndValidateAgeRange;
var ngModel = ctrls[1];
ngModel.$render = getAgeRange;
function checkAndValidateAgeRange() {
// fired when the model changes
};
// $render function
function getAgeRange() {
scope.ageRange.ageMin = ngModel.$viewValue.ageMin;
scope.ageRange.ageMax = ngModel.$viewValue.ageMax;
};
};
};
In some cases, both of the ngModel object's properties passed to the directive - ageMin and ageMax - could be undefined.
And we all know what happens when we have an input with restrictions such as type="[whatever]", min="18" or max="80" and the data entered in that input does not follow those requirements: it is set to undefined in the model.
So, if the above properties were initially passed to the directive set to undefined and you entered a value in the <input type="number ...> that, for example, was not numeric... the binded model's value would still be undefined, so there wouldn't be any changes in the model making the ng-change not trigger.
What I finally did to solve this, was to initialize both ageRange.ageMin and ageRange.ageMax to null if they are passed as undefined, at my $render function:
ngModel.$render = getAgeRange;
// $render function
function getAgeRange() {
scope.ageRange.ageMin = ngModel.$viewValue.ageMin || null;
scope.ageRange.ageMax = ngModel.$viewValue.ageMax || null;
};
This way, when entering an invalid input the model's property value will change from null to undefined causing the ng-change to trigger.
checkout this fiddle
$scope.checkAndValidateAgeRange = function(name, model) {
if (name === 'ageMin') {
if (angular.isNumber(model)) {
if (model < $scope.age.min) {
$scope.minAgeMessage = 'You are under age';
} else if (model > $scope.age.max) {
$scope.minAgeMessage = 'You are too old';
} else {
$scope.minAgeMessage = '';
}
} else {
$scope.minAgeMessage = 'Enter Only Numbers';
$scope.ageRange.ageMin = null;
}
}
if (name === 'ageMax') {
if (angular.isNumber(model)) {
if (model <= $scope.ageRange.ageMin) {
$scope.maxAgeMessage = 'You are under age';
} else if (model > $scope.age.max) {
$scope.maxAgeMessage = 'You are too old';
} else {
$scope.maxAgeMessage = '';
}
} else {
$scope.maxAgeMessage = 'Enter Only Numbers';
$scope.ageRange.ageMax = null;
}
}
}
you can't use allowInvalid on type='number' as given here. You can set type='text' and then handle validation inside the ng-change handler if your intent if using type='number' is showing validation messages.
To set validity of form inside a controller refer to this link.
I'm having two input text box.
I need to combine the values entered in two text boxes and display it in the third.
I'm able to display it if I use only the value in the third text box.
Box 1:
<input type="text" ng-model="entity.name">
Box 2:
<input type="text" ng-model="entity.code">
Box 3:Box1+Box 2
<input type="text" value="{{entity.name+ ' + ' + entity.code}}">
However if I use a model name in the third box, the logic doesn't seem to be working:
<input type="text" value="{{entity.name+ ' + ' + entity.code}}"
ng-model="entity.fullCode">
Can anyone suggest a fix ??
This is a good question as it illustrates how incorrect "thinking in Angular" can lead to issues.
With Angular you start with model first. Then the View is bound to the model and reflects it - not the other way around. What I mean by that is that ng-value would not set the model, although it would alter the view. You (or rather, the controller) is responsible for setting the model.
So, if you need entity.fullCode to equal the concatenation of entity.name and entity.code, then you should set it in the controller.
For example, if you wanted to set it any time entity.name or entity.code change, then you could do so with $watch:
$scope.$watch("entity.name + entity.code", function(newVal){
$scope.entity.fullCode = $scope.entity.name + "+" + $scope.entity.code;
})
Note, though, that since you are binding entity.fullCode to another input, changing that input would change entity.fullCode and would not make it equal to the + of the first two.
<div ng-app>
<div>
<label>Name:</label>
<input type="text" ng-model="entity.name">
<label>Code:</label>
<input type="text" ng-model="entity.code">
<label>Full Code:</label>
<input type="text" ng-model="entity.fullCode" value="{{entity.fullCode=entity.name + ' + ' + entity.code}}">
</div>
</div>
You must assign something to your ng-model attribute, so that it can bind.
your code seems to be work. but just display purpose we do this.
cheers
You need to use $watch with true
function MyCtrl($scope) {
$scope.entity={name:'',code:'',fullCode:''};
$scope.$watch('entity',function(n,o){
$scope.entity.fullCode = $scope.entity.name + $scope.entity.code;
},true);
}
Fiddle:- http://jsfiddle.net/405qc0xg/
$scope.entity = [];
$scope.entity.name = "";
$scope.entity.code = "";
$scope.$watch("entity.name + entity.code", function(newVal){
if($scope.entity.name != "" && $scope.entity.code != ""){
$scope.entity.fullCode = $scope.entity.name + "+" + $scope.entity.code;
}
else {
$scope.entity.fullCode = "";
}
})
you need to make use of $watch.
It keeps watch on mentioned obeject as soon as value of object change the function of $watch will be called and it will refresh $scope
for your code your need to write this:
$scope.$watch('entity.name',function(){
$scope.entity.fullCode=$scope.entity.name+' + '+$scope.entity.code;
});
$scope.$watch('entity.code',function(){
$scope.entity.fullCode=$scope.entity.name+' + '+$scope.entity.code;
});
I assume you're using controllerAs syntax and would suggest you do something like this in your controller:
entity.fullCode = entity.name + ' - ' + entity.code;
Then you can drop the value attribute and simply bind to the element via data-ng-model/ng-model.
Hope this helps you, please have a look into the plunker
http://plnkr.co/edit/oMUABphr6JcNEhCnCDKq?p=preview
$scope.obj = {first : '',second : ''};
$scope.$watch('obj', function(newval, oldval){
$scope.obj.third = $scope.obj.first + $scope.obj.second;
},true)
The above code says, when ever the object 'obj' changes, then the code inside the $watch will execute.
Your code should actually work. See this JSFiddle for a working demo.
<div ng-app>
<div>
<label>Name:</label>
<input type="text" ng-model="entity.name">
<label>Code:</label>
<input type="text" ng-model="entity.code">
<label>Full Code:</label>
<input type="text" value="{{entity.name + ' + ' + entity.code}}">
</div>
</div>
I'm still fairly new to angular.js. This seems like it should be very simple, but I'm stumped.
I have an input field:
<input type="text" placeholder="Search" ng-model="search.txt">
And I have a button that calls this function in my controller on ng-click:
$scope.clearSearch = function() {
$scope.search = {txt:"qqqqq"};
}
Clicking the button behaves as expected - the input value on the page becomes "qqqqq". So the data binding seems correct.
However, if I type anything into the field first and then press the button, the input value does not change on the page - the input field keeps the value I typed. Why is that?
What I'm really trying to do is clear the field, I'm just using "qqqqq" for illustration - setting the value to null has the same behavior.
It works:
Script:
angular.module('myapp',[])
.controller('myctrl',function($scope){
$scope.search = {text:'some input'};
$scope.clearSearch = function () {
$scope.search={text:null};
}
});
Markup:
<div ng-app="myapp" ng-controller="myctrl">
<input type="text" ng-model="search.text"/>
<button ng-click="clearSearch()">clear</button>
</div>
In plunker
I am using jQuery to send Ajax request to the server to save the values being input in the form. Below the section where I am stuck. The HTML is as
<span class="no-margin multiple Date_Off" style="margin-left: 104px;">
<input type="text" value="" /><input type="text" />
<input type="text" value="-" /><input type="text" />
<input type="text" /><input type="text" value="-" />
<input type="text" /><input type="text" /><input type="text" />
<input type="text" />
</span>
I have tried using jQuery to send the request. What I want to do is something like this
I want to save the values from the form, to the same Column_Name that the input fields have. In the multiple input fields I am not using input names. Instead I am using a classname which is identical to the Column_Name in the database.
For that, I am using $(this).parent().attr('class');. If I use this in an alert, it gives me the result without error. But if I use it in the code, it gives me undefined.
I want to append each input's value to the string to save it as a single string.
Here is what I tried so far
var input = $('input');
input.change(function () {
// Input click function...
if ($(this).parent().attr('class')
.replace(' multiple ', '')
.replace('no-margins', '') == 'Date_Off') {
// Date Time for the office work!
var value = '';
value = $(this).parent().find('input').each(function (index, ele) {
value += ele.val();
});
send_request('Date_Off', value);
// Below is the else condition, to execute only when the input is single
// Like a single string input and not like the one in image
// That's why I am using attr('name') for that.
} else {
send_request($(this).attr('name'), $(this).val());
}
});
But what it returns is always a undefined in the Query structure. Here is the function for that
function send_request(input_name, value) {
$.ajax({
url: '/ajax_requests/save_form',
data: 'input_name=' + input_name + '&form_id=' +
$('input[type=hidden]').val() + '&value=' + value,
error: function () {
$('.main-content').append(
'There was an error in request.
Please contact your website Developer to fix it.'
);
},
success: function () {
}
});
}
Image for the code execution
The input in focus was 1. Date. And the console shows the Internal Server Error. Because jQuery sent the request with input_name=undefined which is not a Column_Name.
I have created a (Mini) fiddle for that: http://jsfiddle.net/afzaal_ahmad_zeeshan/EHWqB/
Any help here?
For the fiddle that you posted, there were two errors. The first was you were calling ele.val(), but ele in this context is not a jQuery object - so you need to get the value property off of it. The second is that the jQuery each function operates on an array of objects and it's return value is that array of objects. You don't want your value, which should be a string, to be accepting that return value. Here is an updated, working fiddle
input.change(function () {
// Input click function...
var value = '';
$(this).parent().find('input').each(function (index, ele) {
value += ele.value;
});
send_request('Date_Off', value);
});
In this line you're trying to get the name of the input
send_request($(this).attr('name'), $(this).val());
I don't see a "name" attribute anywhere in your code, I think what you want is to get the class of the parent instead?
send_request($(this).parent().attr('class'), $(this).val());