optimizing the code by passing the targeted element in AngularJS - javascript

I tried to implement the below functionality. There are 2 text boxes. When we type on box 1 the box 2 will also have the value of box 1 and vice versa.
using the same ng-model will do this, but I need to learn how to use elements(references) and identify them in a controller to do this
<body ng-app="myApp" ng-controller="myControl">
Name 1 : <input type="text" ng-model="name1" ng-change="change1()" />
Name 2 : <input type="text" ng-model="name2" ng-change="change2()" >
</body>
var app = angular.module('myApp', []);
app.controller('myControl',function($scope,$http){
$scope.change1 = function(){
$scope.name2= $scope.name1;
}
$scope.change2 = function(){
$scope.name1= $scope.name2;
}
});
Fiddle of the code
How can I use one function instead of using the two functions change1 and change2( I think if I pass a reference it can be done. But i could not find a way to do that) ?

Just have a look at this code you call same function on ng-change and it works fine
<body ng-app="myApp" data-ng-controller="MainCtrl" id="div1">
Name 1 : <input type="text" ng-model="name1" ng-change="change1(name1)" />
Name 2 : <input type="text" ng-model="name2" ng-change="change1(name2)" />
<script>
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope){
$scope.change1 = function(val){
$scope.name2= val;
$scope.name1=val;
}
});
</script>
</body>

By making the the ng-model value structure like object, then Javascript prototypal will do the trick, While you are assigning name1 object to name2 they both will follow the same object, as update in any of the value array will update other. Thats the reason why we don't want such feature then we uses cloning of object, In jQuery its .clone() & in angular its known as angular.copy which creates a new deep copy of the object which will not follow this rule.
Markup
Name 1 : <input type="text" ng-model="name1.value"/>
Name 2 : <input type="text" ng-model="name2.value"/>
Code
var app = angular.module('myApp', []);
app.controller('myControl',function($scope,$http){
$scope.name1= {};
$scope.name2= {};
$scope.name1= $scope.name2; //will update two object according no need of ng-change
});
Forked Fiddle

Related

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/

How do I reset a form in angularjs?

See Fiddle: http://jsfiddle.net/hejado/7bqjqc2w/
I'm trying to form.reset() my form using angular.
HTML:
<div ng-controller="formCtrl">
<form name="resetme" id="resetme">
<input ng-model="text" type="text" />
<input file-model="file" type="file" />
<button type="button" ng-click="resetForm()">reset</button>
</form>
</div>
JS:
.controller('formCtrl', function($scope) {
$scope.resetForm = function() {
//$scope.resetme.reset();
document.getElementById('resetme').reset();
};
});
Please note: I'm using this kind of form to ajax-upload a file. The page is not refreshing and I don't want to use any reset-buttons. (I'm using one in the fiddle for simplicity.) I want to call the reset-function after the fileupload is finished (via http success).
I'm using
<input type="file" />
so I can't reassign empty values to all my inputs, because file inputs are readonly.
Calling the reset() function on the DOM element works, but I was told talking to the DOM in angular would be evil, so...
I'd like to know, how this would be done the angular way. I tried naming the form and referencing it via $scope.formname but I'm not able to call Web API functions... (commented line)
How can I achieve this?
UPDATE
After reading some of the answers, I should make clear, that I am using ngModel and a custom directive fileModel to get a hold of the file-object.
Some of the solutions worked in resetting the value of the input field, but the model is not cleared (neither file, nor text). Custom directives are the answer to that, but this kinda exceeds the scope of this question.
I wrote about this topic a couple years ago. I don't know if the Angular team has yet implemented a native form reset directive but you can do so yourself. There are a couple caveats to this implementation: it only works for one model (if you need to support more see the followup post) and the issue of when to initialize the original values. Also, I never tested this with file inputs so I am not sure it would work with those.
There was an issue for this but it was closed due to inactivity. :/
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', ['$scope',
function($scope) {
$scope.myModel = {
foo: 'Boop',
bar: 'Beep'
};
$scope.myModelCopy = angular.copy($scope.myModel);
}
]);
myApp.directive('resetDirective', ['$parse',
function($parse) {
return function(scope, element, attr) {
var fn = $parse(attr.resetDirective);
var masterModel = angular.copy(fn(scope));
// Error check to see if expression returned a model
if (!fn.assign) {
throw Error('Expression is required to be a model: ' + attr.resetDirective);
}
element.bind('reset', function(event) {
scope.$apply(function() {
fn.assign(scope, angular.copy(masterModel));
scope.form.$setPristine();
});
// TODO: memoize prevention method
if (event.preventDefault) {
return event.preventDefault();
} else {
return false;
}
});
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="MyCtrl">
<form reset-directive="myModel" name="form">
<input type="text" ng-model="myModel.foo" />
<input type="text" ng-model="myModel.bar" />
<input type="reset" value="Reset" />
<pre>myModel: {{ myModel | json }}</pre>
<pre>myModelCopy: {{ myModelCopy | json }}</pre>
<pre>form pristine: {{ form.$pristine }}</pre>
</form>
</div>
</body>
You can try :
reset
$scope.resetForm = function(form) {
//Even when you use form = {} it does not work
form.fieldA = null;
form.fieldB = null;
///more fields
}
Or
$scope.resetForm = function(form) {
//Even when you use form = {} it does not work
angular.copy({},form);
}
See Demo
You'd want to attach ng-model to each of your input fields then null them out via $scope. Either that or make a custom directive
I've just had a similar problem with forms not resetting. Here's what I would do:
In your resetform() function, I would include statements that set both of your ng-models in your input to "". For example:
**HTML**
<input ng-model="text" type="text" />
<input file-model="file" type="file" />
**JS**
.controller('formCtrl', function($scope) {
$scope.resetForm = function() {
$scope.text = "";
$scope.file = null;
};
});
Not certain if this will work for file-models but I'm certain it will remove the text. Best of luck!
If you don't want to use ng-model and proper reset type of button you can use this code, however this is not proper angular way to reset the form but it will work
$scope.reset = function(){
$('form').children('*').each(function(){
$(this).val('');
});
}
Here's the Plunker
To reset the form data use following code :
$scope.resetEmployeeData = function() {
$scope.employeeCred.userName = '';
$scope.employeeCred.employeeNo = '';
$scope.employeeCred.sapNo = '';
$scope.employeeCred.emailD = '';
$scope.employeeCred.mobileNo = '';
**this**.createEmployee.$setPristine();
**this**.createEmployee.$setUntouched();
};
use this rather than $scope.

how to know if a radio button is checked or not in controller in angularjs

I am using radio buttons and I want to know if they are checked or not in the controller. Is there any other way to find that out in angular except ( document.getElementById( "radio_button" ).checked ) ?
You can trigger the function on click like this :
In HTML :
<div ng-click='newValue(value)'>
<input type="radio" ng-model="value" value="firstValue">
<input type="radio" ng-model="value" value="secondValue" > </div>
You can also observe the model change by using ng-change as follows :
In Javascript :
$scope.newValue = function (value) {
alert(value);
}
You can even watch the value by using $watch like this :
$scope.$watch('value', function(value) {
alert(value);
});
However, using ng-change is better and efficient than $watch and is easier to test.
There is no need of $watch
You can do it in more simpler way.
<body ng-controller="testCtrl">
<label>Check me to check both:
<input type="checkbox" ng-model="master" ng-checked="checkTest(master)"></label><br/>
</body>
JS :
$scope.checkTest = function(boolChecked){
console.log(boolChecked)
}
Here is Plunker
You can do this in a few different ways:
with Radio Buttons
In your HTML
<input type="radio" ng-value="isButtonChecked">
In your controller
$scope.isButtonChecked = true;
with another element tag
In your HTML
<div ng-click="isButtonChecked = !isButtonChecked"></div>
In your controller
$scope.isButtonChecked = true;

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.

How to achieve Functional binding with ng-model (With plnkr)

I have a dob column and values comes in this is in yyyy-mm-dd format say 2013-01-01 and I need to show it in input box as 1 Jan. I can achieve this by writing a function and then return exact value from that function. But function could not be called from input box using ng-model where as it can be called using ng-bind in spans. I can understand that function calling in input box will break two way binding. But what other approach I can use for this.
http://plnkr.co/edit/pZDpypsxM1OA2JwFhjjp?p=preview
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script type="text/javascript" >
var app = angular.module('app', []);
app.controller('AppCtrl', function ($scope) {
$scope.dob = "2013-01-01";
$scope.getDateOfBirth = function(dob){
var months = ["Jan","Feb","Mar","Apr","May","June","July","Aug","Sep","Oct","Nov","Dec"]
var split = dob.split("-");
return parseInt(split[2])+" "+months[parseInt(split[2])-1];
}
});
</script>
<span ng-app="app" ng-controller="AppCtrl" ng-bind="getDateOfBirth(dob)"></span>
<input type="text" ng-model="getDateOfBirth(dob)"/>
You can use ng-init to assign the value returned by the function and assign it to a model:
<input ng-init="myDOB = getDateOfBirth(dob);" type="text" ng-model="myDOB">
DEMO
You can use ng-init to set the value and ng-change to keep the value updated
http://plnkr.co/edit/q1hg0R?p=preview
For dates, phone numbers, etc., you can use ui-mask. Hope this helps someone!

Categories

Resources