ng-model doesn't change value when field contains user input - javascript

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

Related

How to get data from input field inside a Jquery function in angular?

I want to take the input field value each time a letter is added/changed/deleted
so I'm using the jquery to trigger it.
but I don't know how to save this value.
in the html:
<form [formGroup]="searchForm">
<input id='myTextbox1' type='text'/>
</form>
in the ts file:
searchString:string;
searchForm: FormGroup;
ngOnInit(){
this.searchForm = new FormGroup({
'str':new FormControl(null)
})
/
$('#myTextbox1').on('input', function() {
// i tried this:
this.searchString = this.searchFrom.controls['str'].value
});
}
but controls weren't read from the form.
I just want to save the value of the input field in the searchstring variable and change it each time it changes.
please help me.
Rather than using jquery you could update your code as below:
<form [formGroup]="searchForm">
<input id='myTextbox1' type='text' formControlName="str"/>
</form>
and instead of the jquery code you could use the power of Observables:
this.searchForm.str.valueChanges.subscribe((value) => {
this.searchString = value;
});

How to detect input field value change in ng-repeat

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>

Why binding to null not work when value of number input illegal in AngularJs

See example here: https://jsfiddle.net/codefalling/u2mn764x/1/
<div ng-app>
<div ng-controller="TodoCtrl">
<input type="number" ng-model="value" size="30" >
<input type="button" ng-click="change()" class="btn-primary" value="TEST" >
</div>
</div>
function TodoCtrl($scope) {
$scope.change = function() {
$scope.value = null
}
}
When I type 10 into number input, click button, it turn to be empty.
However when I type a standalone e or . into number input, then click button, nothing happend. But $scope.value = 123 stills works.
So, Why view didn't get update(empty) in this situation?
Additional, is there any other way to empty it?
To clear out the HTML 5 number controls, you can check the state of the control and if it is invalid then override its value to blank. I have updated your fiddle with the below code https://jsfiddle.net/u2mn764x/3/
<div ng-app>
<div ng-controller="TodoCtrl">
<input type="number" ng-model="value" size="30" id='mynumber'>
<input type="button" ng-click="change()" class="btn-primary" value="TEST" >
</div>
</div>
function TodoCtrl($scope) {
$scope.change = function() {
if (!document.getElementById('mynumber').validity.valid)
{
$scope.value = null
document.getElementById('mynumber').value='';
}
}
}
For short, because e and . is not the complete legal numeric value. According to Foalting point number in W3 spec:
if the value started by ., it must be followed by one or more "0—9";
if the value started by e, it must be followed by an optional + or -, and one or more "0-9"
As the HTML check is not passed, it will not trigger the JS, as I imagine. If you continue to input .1 or e45, it works.
As soon as you type 10 inside Number Input,Angular will bind 10 and it will be like $scope.value = 10, but when you fire click event,you are changing the value to null like $scope.value = null,so send the value of model through the event and bind it to your variable.
<div ng-app>
<div ng-controller="TodoCtrl">
<input type="number" ng-model="value" size="30" >
<input type="button" ng-click="change($event,value)" class="btn-primary" value="TEST" >
</div>
</div>
And the javascript code :
function TodoCtrl($scope) {
$scope.change = function($event,val) {
$scope.value = val;
}
}
Thanks to comment of #zeroflagL.I found the answer.
Model did not have a value when input is illegal. So $scope.value = null or $scope.value = '' won't work because they are illegal value,too.
Model value and view value are both undefined, so angular did not update view.
We can use DOM API to empty illegal input manually. Or set modal to a value, force dirty check then set it to null again:
$scope.value = 0
$scope.$apply();
$scope.value = null
See https://jsfiddle.net/codefalling/xhcz3Lbj/

ng-repeat not updating information after $scope was updated

I have an ng-repeat which creates a form with some starting data. Then the user is free to modify said data and the changes should appear in the form. Before that, the user submitted data are sanitized by another function, which is called by an ng-click on a button.
Everything works well under the hood (I checked my $scope.some_array, from which ng-repeat takes the data and the new data is in the right place) but nothing happens on the page.
The element:
<li ng-repeat="field in some_array" id="field-{{$index}}">
<div class="{{field.field_color}}">
<button type="button" ng-click="save_field($index)">done</button>
{{field.nice_name}}
</div>
<div id="field-input-{{$index}}">
<input type="text" id="{{field.tag}}" value="{{field.content}}">
<label for="{{field.tag}}">{{field.nice_name}}</label>
</div>
</li>
save_field code:
$scope.save_field = function (index) {
console.log($scope.some_array[index]["content"])
var value = $("#field-" + index).children("div").children("input").val()
var name = $scope.some_array[index]["name"]
var clean_value = my_clean(value)
if (norm_value === "") {
return
}
$scope.some_array[index]["content"] = clean_value
console.log($scope.some_array[index]["content"])
}
On the console I see:
10.03.16
10/03/16
Which is right, but in the form I only see 10.03.16. I already tried putting $timeout(function(){$scope.$apply()}) as the last line of my function, but the output is still the same.
You shouldn't use input like this if you want to bind a variable to it. Digest loop will refresh the value but it will not be updated visibly because this is not html native behavior.
Use ng-model instead, it will update view value of the input as expected:
<input type="text" id="{{field.tag}}" ng-model="field.content">
Also using ng-model your variable will be updated when user modify the input, so you can retrieve it to do some treatments much more easily in save_field function, without jQuery:
$scope.save_field = function (index) {
if (norm_value === "") {
return;
}
$scope.some_array[index]["content"] = my_clean($scope.some_array[index]["content"]);
};
More infos: https://docs.angularjs.org/api/ng/directive/ngModel

Model update is not propagated dynamically

I want to sum up 2 values and display the result in the 3rd input:
HTML
<div ng-app="myApp">
<div ng-controller="MainCtrl as mainCtrl">
Main {{mainCtrl.foo}} <br/>
<input type="text" ng-model="mainCtrl.foo"/>
<input type="text" ng-model="mainCtrl.foo2"/>
<input type="text" ng-model="mainCtrl.foo3"/>
<br/>
</div>
</div>
JS
var myApp = angular.module('myApp', []);
var my = {};
my.MainCtrl = function() {
this.foo = '1';
this.foo2 = '2'
this.foo3 = this.sumUp();
}
my.MainCtrl.prototype.sumUp = function() {
return this.foo + this.foo2;
}
// register all controllers
myApp.controller('MainCtrl', my.MainCtrl);
My problem is that the 3rd input is set only when the document is loaded but it is not dynamically changing while typing values in first two inputs.
Fiddle:
http://jsfiddle.net/K64wb/
Use parameter ng-change for input-fields 1 and 2.
Solution for U ;) ng-change="mainCtrl.foo3=mainCtrl.sumUp()"
Example:
<div ng-controller="MainCtrl as mainCtrl">
Main {{mainCtrl.foo}} <br/>
<input type="text" ng-change="mainCtrl.foo3=mainCtrl.sumUp()" ng-model="mainCtrl.foo"/>
<input type="text" ng-change="mainCtrl.foo3=mainCtrl.sumUp()" ng-model="mainCtrl.foo2"/>
<input type="text" ng-model="mainCtrl.foo3"/>
<br/>
</div>
When your view loads, it only fires the controller function once. So it assigns foo and foo2, and then computes foo3, and then it's done. this.sumUp is never called again.
You can add ng-change="mainCtrl.foo3=mainCtrl.sumUp()" to the input boxes like Mularski suggests. This causes the sumUp function to run and be assigned to foo3 every time the input value changes. I think that looks kind of messy, though. And if you decided to add more input boxes to add up, you have to remember to put ng-change on all of them.
Another way to do it is to assign the sumUp function itself to foo3 like this
this.foo3 = this.sumUp;
instead of assigning the result of sumUp like you are doing (this.foo3 = this.sumUp();). Then in your view, assign foo3() to the ng-value of the textbox:
<input type="text" ng-value="mainCtrl.foo3()"/>
(you can't assign it to ng-model because the function isn't writeable).
Now you're telling the textbox to always show the result of that function, and it will fire whenever any of its dependencies change (i.e. foo and foo2).
Here's a Fiddle.

Categories

Resources