Why do we need to use ng-model to make sure that validation works. For instance, in this code if I remove ng-model attribute then validation breaks but it works as long as there is ng-model attribute no matter what is the value of attribute is. So what's the significance of ng-model in this case? Why do I have to use though it's value does not make much difference?
The value of ng-model makes all the difference. Not the initial value however, which you are correctly asserting seems to be irrelevant. As soon as you type something into that input box Angular magically assigns the value to the variable assigned to ng-model.
Subsequently, the value of ng-model is what Angular's validation code is validating! The data has to get from your fingers to the code somehow and that's the ng-model.
Let's say you have typed into an input box with ng-model on it: "I am so cool."
<form ng-controller="SuperController">
<input ng-model="somethingAwesome" />
<button ng-click="someAction()">Click me!</button>
</form
Inside your controller you can access that value on the $scope.
function SuperController ($scope) {
$scope.someAction = function () {
console.log($scope.somethingAwesome)
// "I am so cool."
}
}
If you set the value inside your controller.. your input box will display that value.
function SuperController ($scope) {
$scope.somethingAwesome = 'You are so cool!'
}
Angular's validation functions read the value of the stuff on your $scope, which contains the values of items in your view that have the directive ng-model.
https://docs.angularjs.org/api/ng/directive/ngModel
Related
I have a text input bound to a model value, but I can't figure out how to change the input value programmatically and have the change propagate to the model.
I understand that because I'm updating the value external to the angular scope that I need to explicitly call $scope.$apply(), but it's not working.
HTML:
<input id="test_input" ng-model="test_value">
Controller:
$scope.test_value = 'abc'; // starting value
Console:
$('#test_input').val('xyz');
$('#test_input').scope().$apply();
$('#test_input').scope().test_value;
-> 'abc';
ngModel listens for "input" event, so you need to trigger that event after setting the value:
$('#test_input').val('xyz');
$('#test_input').trigger('input');
$('#test_input').scope().test_value;
Plunkr
I made a autofill dropdown using angular custom directive.All is working fine.
But I want to make this directive reusable!!!!
Currently my directive is tightly depended on Id and Name property of selected item.
I want to assign text property(Which I want to bind the text into list items html) and value property(which will be available in my app controller) like textfield="Name" and value-field="Id".
Imagine If my data object does not contain Name or Id property , my
directive would not work.
HTML:
<autofill-dropdown items="searchCurrencies"
textfield="Name" valuefield="Id" selected-data="Id" urllink="/api/SetupCurrency/Autofill?filter=">
</autofill-dropdown>
Template :
<div class="pos_Rel">
<input placeholder="Search Currency e.g. doller,pound,rupee"
type="text" ng-change="SearchTextChange()" ng-model="searchtext"
class="form-control width_full" />
<ul class="currencySearchList" ng-show="IsFocused && items.length">
<li class="autofill" ng-repeat="item in items" ng-click="autoFill(item)">
{{item.Name}}
</li>
</ul>
</div>
So,finally what I want to accomplish , I'm going to bind Name property(or other,depends on what value I set to "text-field" attribute onto my html) to listitems and whenever user select an item, it will give me the selected Id(or other property ,depends on what value I set to "value-field" attribute onto my html).
Plunkr Here
Update:
I think my question not so clear.
I have written same directive 2 times to accomplish and also 2 times same template :(
Please look through my updated plunkr.
Updated Plunkr
I want to say that I am not quit sure if I understood your question in the right way so I try to repeat it.
textfield="Name" valuefield="Id" selected-data="Id"
You want to store the Value of the Property of the selected Item of your custom directive.
The Value should be stored in the Variable provided in the attribute "textfield"
The attribute "valuefield" should define the name of the property of the selected Object
If this is the case you have to get rid of the two-way databinding for your valuefield. Because you only want to provide a String (like "Id" or "Name").
I altered your plunkr again. First of all I made the new scope variables:
scope: {
'items': '=',
'urllink':'#',
'valuefield':'#',
'textfield':'=',
'Id':'=selectedData'
}
Valuefield is now only a text binding. So if you want to change it in the angular way you have to provide a scope variable outside of the directive and a '=' twoway binding inside :D
$scope.autoFill = function (item) {
$scope.IsFocused = false;
$scope.searchtext = item.Name;
$scope.Id = item.Id;
$scope.textfield = item[$scope.valuefield];
}
Also I added the last expression to your autofill function. The name of the property (valuefield) will be written into the textfield variable which is linked with your outside scope (in this case "Name"):
textfield="Name"
If this is not what you asked I am sorry but I am new to stackoverflow and I still can not comment :P
https://plnkr.co/edit/zE1Co4nmIF3ef6d6RSaW?p=preview
JSfiddle code at the bottom
My problem: If an <input> field has whitespace in it and you "clear" the value with angular by setting its scope value to an empty string, it leaves the whitespace in the input field.
The reason: I understand why it is doing it, as the angular digest doesn't see a change, since it already has the scope variable empty due to trimmed whitespace via ng-trim.
My question: Is there a proper way to make sure the input field gets blanked out? I know of multiple solutions, but all of them are hacks or wouldn't work.
Set the scope value to null, and then to blank after a $timeout. But this could cause problems due to the code expecting only strings in the scope value.
Set the element to ng-trim, but I like having the value automatically trimmed
Empty the input field with jquery (or directly setting the element's value). This is probably the solution I am going to end up going with (a function that clears the input and blanks the scope variable at the same time), but I'm hoping there is something not quite so hacky.
jsfiddle: https://jsfiddle.net/0kf84g5o/3/
HTML
<div ng-app=MyApp>
<div ng-controller="TestCtl">
Press "tabs and spaces", add spaces and/or tabs, and then press "blank out'<br>
<input ng-model=TestInput id=TestInput>
<input type=button value="abc" ng-click="ChangeTestValue('abc')">
<input type=button value="Tabs and spaces"ng-click="ChangeTestValue('\t \t')">
<input type=button value="Blank out" ng-click="ChangeTestValue('')">
<input type=button value="Null out" ng-click="ChangeTestValue(null);">
<pre>
Angular Value: --{{TestInput}}--
JSONified Angular Value: --{{TestInputJSON}}--
Actual input value JSONified: --{{TestInputActualJSON}}--
</pre>
</div>
</div>
Javascript
var MyApp=angular.module('MyApp', []);
MyApp.controller('TestCtl', function($scope, $timeout) {
//Update the value programatically
$scope.TestInput='Start text';
$scope.ChangeTestValue=function(Str) {
$scope.TestInput=Str;
};
//Update TestInputJSON
$scope.$watch('TestInput', function(NewVal) { //When angular values changes
scope.TestInputJSON=JSON.stringify(NewVal);
});
//Update TestInputActualJSON
$scope.$watch('TestInput', function(NewVal) { //When angular value changes
$timeout(UpdateTestInputActualJSON, 1); //Wait for 1ms to update so the new value is alread set
});
$('#TestInput').on('keyup paste', UpdateTestInputActualJSON); //On a jquery event
function UpdateTestInputActualJSON(e) //Do the actual update of TestInputActualJSON
{
$scope.TestInputActualJSON=JSON.stringify($('#TestInput').val());
if(e) //Call angular digest if coming from jQuery
$scope.$apply();
}
});
I am wanting to know: how does one get a DEFAULT value for the ng-model inside a CHECKBOX to be true? The code i have will check the box but whenever i evaluate the model it keeps saying UNDEFINED...why is that?
<input ng-change="docModel.check()"
type="checkbox"
ng-model="amountSelected"
ng-checked="true" />
To define the default value when using AngularJS, simply give a value to the model variable in your controller:
$scope.amountSelected = true;
According the officiel AngularJS documentation ngChecked directive:
Note that this directive should not be used together with ngModel, as this can lead to unexpected behavior
link to the doc
I have made a simple example using angularjs. This example contains three radio inputs, each of which have to call a function on change (ng-change => console.log). Unfortunately, the function its only triggered the first time any radio input is selected.
HTML:
<div ng-app="myApp" ng-controller="radioGroupController">
<div ng-repeat="value in values">{{value}}
<input type="radio" name="name" ng-model="val" value="{{value}}" ng-change="logChange(val)" />
<hr/>
</div>
</div>
JS:
angular.module('myApp', [])
.controller('radioGroupController', ['$scope', function ($scope) {
$scope.values = ['Option1', 'Option2', 'Option3'];
$scope.logChange = function (newValue) {
console.log('Changed to ' + newValue);
};
}]);
Am I doing something wrong or is this the expected beheaviour?
EDIT: fiddle
Couple of issues/changes:-
1- Change value={{value}} to ng-value="value" because ng-value - Binds the given expression to the value of input[select] or input[radio], so that when the element is selected, the ngModel of that element is set to the bound value.
2- You need to set the selected value on the property on parent scope, you have ng-repeat and you really are setting value of the child scope, so each radio has its own child scope and its value never changes so ng-change is not triggered.
3- You do not need to pass the model value though logChange scope will already have it.
Try:-
In your controller add:-
$scope.selected = {};
and view set the model as a property on selected property of controller scope instead of ng-repeated child scope's val property:-
<input type="radio" name="name" ng-model="selected.val"
ng-value="value" ng-change="logChange()" />
Plnkr
You can change ng-change to ng-click, then it fires every time you actually click on the button.
Here is a JSFiddle.
Depending on what you want to achieve, consider $watch or ng-model for your purpose.
If you bind ng-model to "values" or whatever, you can check which
value it has and work with that. Angulars advantage is exactly this
two-way-databinding without doing anything. No need to call a
function to pass an argument.