I have an html form that takes a name and a location and Posts it to a mobile service table.
<form name="userform" ng-submit="addName(user)">
<p>name: <input type="text" id="name" ng-model="user.name" /></p>
<p>location: <input type="text" id="location" ng-model="user.location"/></p>
<button id="btn-add-evangelist">Add to list</button>
</form>
and this is how I retrieve data from the form in Angular
$scope.people = [];
$scope._name = "Default Name";
$scope._location = "Default Location";
$scope.user = {
name: function (theName) {
if (angular.isDefined(theName)) {
$scope._name = theName;
}
return $scope._name;
},
location: function (theLocation) {
if (angular.isDefined(theLocation)) {
$scope._location = theLocation;
}
return $scope._location;
}};
however, when I run the html, the location textbox has the function code instead of the "Default Location" string, and the name textbox is blank instead of "Default Name".
I wonder what can be wrong here. Any help is appreciated.
AngularJS works correct. It basically takes the string representation of the function, and sets it as the value of the textbox.
If you need the evaluated value instead, you need to call the function by putting a parentheses after the function name, like this:
angular.module('myapp', [])
.controller('myctrl', function($scope) {
$scope.people = [];
$scope._name = "Default Name";
$scope._location = "Default Location";
$scope.user = {
name: function(theName) {
if (angular.isDefined(theName)) {
$scope._name = theName;
}
return $scope._name;
}(),
location: function(theLocation) {
if (angular.isDefined(theLocation)) {
$scope._location = theLocation;
}
return $scope._location;
}()
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp" ng-controller="myctrl">
<form name="userform" ng-submit="addName(user)">
<p>name: <input type="text" id="name" ng-model="user.name" /></p>
<p>location: <input type="text" id="location" ng-model="user.location" /></p>
<button id="btn-add-evangelist">Add to list</button>
</form>
</div>
You can set directly the default value to the model like this:
$scope.people = [];
$scope._name = "Default Name";
$scope._location = "Default Location";
$scope.user = { //set default value to the inputs
name:$scope._name,
location:$scope._location
}
If you are using latest version of angular js. Try ng-model-options="{ getterSetter: true }".
Sometimes it's helpful to bind ngModel to a getter/setter function. A
getter/setter is a function that returns a representation of the model
when called with zero arguments, and sets the internal state of a
model when called with an argument. It's sometimes useful to use this
for models that have an internal representation that's different from
what the model exposes to the view.
Best Practice: It's best to keep getters fast because AngularJS is
likely to call them more frequently than other parts of your code. You
use this behavior by adding ng-model-options="{ getterSetter: true }"
to an element that has ng-model attached to it. You can also add
ng-model-options="{ getterSetter: true }" to a , which will
enable this behavior for all s within it. See ngModelOptions
for more.
angular.module('myapp', [])
.controller('myctrl', function($scope) {
$scope.people = [];
$scope._name = "Default Name";
$scope._location = "Default Location";
$scope.user = {
name: function(theName) {
if (angular.isDefined(theName)) {
$scope._name = theName;
}
return $scope._name;
},
location: function(theLocation) {
if (angular.isDefined(theLocation)) {
$scope._location = theLocation;
}
return $scope._location;
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.3/angular.min.js"></script>
<div ng-app="myapp" ng-controller="myctrl">
<form name="userform" ng-submit="addName(user)">
<p>name: <input type="text" id="name" ng-model="user.name" ng-model-options="{ getterSetter: true }"/></p>
<p>location: <input type="text" id="location" ng-model="user.location" ng-model-options="{ getterSetter: true }"/></p>
<button id="btn-add-evangelist">Add to list</button>
</form>
</div>
Related
I'm new to Angular JS and I want to bind the input value to $scope object, just like we use ng-bind and ng-model for input fields to bind their values to DOM (the value changes as we type something in the input).
Can't I do the same? I mean just like displaying live text entered into input should be stored to $scope.foo.bar and hence it is printed in the console?
Here's what I'm trying:
<script type="text/javascript">
var app = angular.module("testApp", []);
app.service("stringService", function(){
this.myFunction = function(word){
return word.toUpperCase();
};
});
app.controller("control", function($scope, $location, stringService, $http){
$scope.age=24;
$scope.foo = {bar: "hello"};
console.log($scope.foo.bar);
$scope.isNumber = angular.isNumber($scope.foo.bar);
});
</script>
<div ng-app="testApp">
<div ng-controller="control" ng-init="obj=[{name:'vikas'}, {name: 'vijay'}, {name: 'vinay'}]; mySwitch=true">
<form name="testForm">
<input type="text" name="bar" ng-model="foo.bar" required>
</form>
<div>{{isNumber}}</div>
</div>
</div>
I can see the initial value (hello) in the console and false in DOM. But it doesn't update.
this line $scope.isNumber = angular.isNumber($scope.foo.bar); will only run once which is at angular initialize the page.
you can change isNumber to function in order to call multiple times.
$scope.isNumber = function() {
return angular.isNumber($scope.foo.bar);
}
call it at template:
<div>{{isNumber()}}</div>
var app = angular.module("testApp", []);
app.service("stringService", function() {
this.myFunction = function(word) {
return word.toUpperCase();
};
});
app.controller("control", function($scope, $location, stringService, $http) {
$scope.age = 24;
$scope.foo = {
bar: 1
};
console.log($scope.foo.bar);
$scope.isNumber = function() {
console.log(Number.isFinite($scope.foo.bar));
console.log(typeof($scope.foo.bar));
return angular.isNumber($scope.foo.bar);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="testApp">
<div ng-controller="control" ng-init="obj=[{name:'vikas'}, {name: 'vijay'}, {name: 'vinay'}]; mySwitch=true">
<form name="testForm">
<input type="text" name="bar" ng-model="foo.bar" required>
</form>
<div>{{isNumber()}}</div>
</div>
</div>
while #Pengyy's is quite correct in saying that you need to databind to a function, that is only part of the problem...
The problem is NaN, a perplexing numeric value that is not a number, but has type 'number' and some quicks having to do with bindings to string valued attributes like <input>'s value in html.
// the constant NaN
console.info(NaN);
// the type of the constant NaN
console.info(typeof NaN);
// NaN is not equal to NaN
console.info(NaN === NaN);
// Number.isNaN checks for NaN
console.info(Number.isNaN(NaN));
// Number.isNaN returns false for any value unless typeof value === 'number'
console.info(Number.isNaN({
a: []
}));
surprisingly, Angular's angular.isNumber function does not help us deal with these oddities. As stated in the documentation it
Determines if a reference is a Number.
This includes the "special" numbers NaN, +Infinity and -Infinity.
If you wish to exclude these then you can use the native `isFinite' method.
Ref: https://docs.angularjs.org/api/ng/function/angular.isNumber
To make matters worse, it also ignores all values for which typeof value !== 'number'
Finally, the last hurdle to overcome is that an HTML input's value is always a string! This means we need to convert it to number.
Therefore, the function needs to look like
$scope.isNumber = function(n) {
// must convert to number because `Number.isNaN` does not coerce
return isFinite(n) && !Number.isNaN(Number(n));
}
And the binding like
<div>{{isNumber(foo.bar)}}</div>
Here is an example
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script type="text/javascript">
(function() {
"use strict";
var app = angular
.module("testApp", [])
.controller({
MyController
});
MyController.$inject = ['$scope'];
function MyController($scope) {
$scope.foo = {
bar: "hello"
};
console.log($scope.foo.bar);
$scope.isNumber = function(n) {
console.info(typeof n);
return isFinite(n) && angular.isNumber(Number(n));
}
}
}());
</script>
<div ng-app="testApp">
<div ng-controller="MyController">
<form name="testForm">
<input type="type" name="bar" ng-model="foo.bar" required>
</form>
<div>{{isNumber(foo.bar)}}</div>
</div>
</div>
Notice how the raw type of the input is always 'string'
Value must be updating but you do not have anything to communicate, You need a watcher or a function that fires the console log and checks for number.
Change your controller to :-
app.controller("control", function($scope, $location, stringService, $http){
$scope.age=24;
$scope.foo = {bar: "hello"};
console.log($scope.foo.bar);
$scope.isNumber = angular.isNumber($scope.foo.bar);
$scope.check = function() {
$scope.isNumber = angular.isNumber($scope.foo.bar);
console.log($scope.foo.bar);
console.log($scope.isNumber);
}
});
And in Html
<input type="type" name="bar" ng-model="foo.bar" ng-change="check()" required>
I have a text field , <input type="text" placeholder="" class="form-control" ng-model="firstName"> in that text field first character must be alphabet only , when user try to enter first character not a alphabet not accepting.
Generic regex check of first string character.
var testString= "This is testString"
console.log(testString+" - "+alphabeticalFirstChar(testString));
testString= "1This is testString"
console.log(testString+" - "+alphabeticalFirstChar(testString));
testString= "This is testString0"
console.log(testString+" - "+alphabeticalFirstChar(testString));
testString= ""
console.log(testString+" - "+alphabeticalFirstChar(testString));
function alphabeticalFirstChar(str){
if(/^[A-z]+$/.test(str[0]) && !str.length<1)//added check for str not being empty - returns true otherwise
return true;
else
return false;
}
Try the following code:
var myApp = angular.module('myApp', []);
myApp.controller('myController', ['$scope', function($scope){
$scope.firstName = "";
var regex = /^[A-z]+$/;
$scope.$watch('firstName', function(newValue, oldValue){
if($scope.firstName.length > 0){
if(regex.test(newValue)){
$scope.firstName = oldValue;
}
}
});
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<input type="text" placeholder="" class="form-control" ng-model="firstName">
</div>
var myApp = angular.module('myApp', []);
myApp.controller('controller', function($scope) {
$scope.password;
$scope.check = function () {
if($scope.password != null){
var charArray = $scope.password.split('');
console.log(charArray);
if(/[a-zA-Z\_]$/.test(charArray[0]) && charArray[0] != null) {
return true;
}
else {
return false;
}
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="controller">
<input type="password" ng-model="password" placeholder="Enter Password"/>
<img src="http://icons.iconarchive.com/icons/custom-icon-design/pretty-office-2/256/success-icon.png" ng-show="check()" width="25" height="25"/>
<img src="https://dialectline.files.wordpress.com/2013/06/sign-error-icon.png" ng-show="!check()" width="25" height="25"/>
</div>
I hope it helps.
In Html
<input type="text" placeholder="" class="form-control" ng-model="firstName" ng-change="checkAlphabet()">
In Controller
$scope.checkAlphabet = function() {
if($scope.firstName.substr(0, 1).match(/[A-Za-z]/) == null)
$scope.firstName = $scope.firstName.substr(1);
}
Working example using $watch using regex as pointed by #Adam
Follow: https://jsfiddle.net/nirus/3Lytwybr/2/
Javascript:
function LoginController($scope) {
$scope.user = {
firstName: ""
};
$scope.$watch('user.firstName', function(){
console.log("changed");
var cache = $scope.user.firstName;
if (!(/^[a-zA-Z]+$/.test($scope.user.firstName[0]))){
$scope.user.firstName = cache.slice(1,cache.length);
console.log("here: "+ cache)
}
})
}
Html:
<div ng-app ng-controller="LoginController">
<div>Hello {{ user.firstName }}</div>
<input ng-model="user.firstName" />
</div>
Note : Avoid using too many watchers as it hampers the performance of the app.
I modified Adam K`s code and translated it into angular.
if(/^[A-z]+$/.test($scope.firstname[0]) == false) {
$scope.firstname = ""; }
Hope it helped.
Having three input fields
<input type="text" name="foo1" ng-model="data.input1"/>
<ng-messages for="forms.myForm.foo1" role="alert">
<ng-message when="oneRequired"> Please set foo1 (or foo2 or foo3) </ng-message>
<ng-messages>
<input type="text" name="foo2" ng-model="data.input2"/>
<ng-messages for="forms.myForm.foo2" role="alert">
<ng-message when="oneRequired"> Please set foo2 (or foo1 or foo3) </ng-message>
<ng-messages>
<input type="text" name="foo3" ng-model="data.input3"/>
<ng-messages for="forms.myForm.foo3" role="alert">
<ng-message when="oneRequired"> Please set foo3 (or foo1 or foo2) </ng-message>
<ng-messages>
I want to guarantee that at least one input fields value is set. In this case, not only the current validation fields $error should evaluate to 'false' but also all others. All messages should disappear.
My first idea was to use a directive and a unique id to link the fields together:
<input type="text" name="foo1" ng-model="data.input1" one-required="i1_i2_i3_link_identifier/>
Probably I could use a (singleton) service for the registration of the controller and the current values. But I don't have an idea to ensure that all linked controllers (used in the directives) are updated on validation errors.
I highly recommend using the https://github.com/turinggroup/angular-validator directive. It is very flexible and will easily allow to to set your custom validators. I was able to get rid of ng-messages and clean up my html code greatly with this directive.
You can set a custom validator in your controller or service to use throughout your site.
<input type = "text"
name = "firstName"
class = "form-control"
ng-model = "form.firstName"
validator = "myCustomValidator(form.firstName)"
validate-on="dirty"
required></div>
Here is a plunker and code for you: http://plnkr.co/edit/X5XdYYekT4YZH6xVBftz?p=preview As you can see this is very clunky and there is a lot of code. With angular validator you can reduce your code to be inline within your inputs and add a controller function.
<form name="myForm">
<input type="text" name="foo1" ng-model="data.input1" required/>
<div ng-if="myForm.foo1.$error.required && myForm.foo2.$error.required && myForm.foo3.$error.required" class="error">
<ng-messages for="myForm.foo1" role="alert">
<ng-message="required"> Please set foo1 (or foo2 or foo3) </ng-message>
</ng-messages>
</div>
<br/>
<input type="text" name="foo2" ng-model="data.input2" required/>
<div ng-if="myForm.foo1.$error.required && myForm.foo2.$error.required && myForm.foo3.$error.required" class="error">
<ng-messages for="myForm.foo2" role="alert">
<ng-message="required"> Please set foo2 (or foo2 or foo3) </ng-message>
</ng-messages>
</div>
<br/>
<input type="text" name="foo3" ng-model="data.input3" required/>
<div ng-if="myForm.foo1.$error.required && myForm.foo2.$error.required && myForm.foo3.$error.required" class="error">
<ng-messages for="myForm.foo3" role="alert">
<ng-message="required"> Please set foo3 (or foo2 or foo3) </ng-message>
</ng-messages>
</div>
<br/>
</form>
I solved the problem using a central Service holding the values and a callback registry. The callbacks are called all the time, when the input changes (using a watcher):
angular.module('myApp', []);
angular.module('myApp').controller('myFormController', function($scope) {
$scope.data = {
i1: "remove",
i2: "all",
i3: "values"
};
});
angular.module('myApp').factory('oneRequiredService', function() {
var service = {};
var container = {};
var observerCallbacks = {};
var isValid = function(groupId) {
var valid = false;
var modelStates = container[groupId];
angular.forEach(modelStates, function(modelValid) {
valid = valid || (modelValid ? true : false);
});
return valid;
};
var isRegistered = function(groupId) {
return container.hasOwnProperty(groupId);
};
var notifyAll = function(key) {
var valid = isValid(key);
if (isRegistered(key)) {
angular.forEach(observerCallbacks[key], function(callback, index) {
callback(valid);
});
};
};
service.register = function(groupId, scopeId, callback) {
this.updateValue(groupId, scopeId, undefined);
if (callback) {
this.registerCallback(groupId, callback);
}
};
service.registerCallback = function(groupId, callback) {
if (callback) {
observerCallbacks[groupId] = observerCallbacks[groupId] || [];
observerCallbacks[groupId].push(callback);
};
};
service.updateValue = function(groupId, scopeId, value) {
container[groupId] = container[groupId] || {};
container[groupId][scopeId] = value;
notifyAll(groupId);
};
return service;
});
angular.module('myApp').directive('oneRequired', function(oneRequiredService) {
return {
restrict: "A",
require: 'ngModel',
scope: true,
link: function(scope, element, attrs, ctrl) {
var modelAttr = attrs["ngModel"];
var linkIdentifier = attrs["oneRequired"];
var updateCurrentState = function(isValid) {
scope._valid = isValid;
};
scope.$watch(modelAttr, function(newVal, oldVal) {
oneRequiredService.updateValue(linkIdentifier, scope.$id, newVal);
});
scope.$watch('_valid', function(newVal, oldVal) {
ctrl.$setValidity('oneRequired', newVal);
});
oneRequiredService.register(linkIdentifier, scope.$id, updateCurrentState);
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<body ng-app="myApp">
<form ng-controller="myFormController" name="forms.myForm">
<label for="i_1">i_1</label>
<input id="i_1" name="i1" type="text" one-required="foo-bar" ng-model="data.i1" />
<span> i1-err-one-required: {{forms.myForm.i1.$error.oneRequired}} </span> <br>
<label for="i_2">i_2</label>
<input id="i_2" name="i2" type="text" one-required="foo-bar" ng-model="data.i2"/>
<span> i2 err-one-required: {{forms.myForm.i2.$error.oneRequired}} </span> <br>
<label for="i_3">i_3</label>
<input id="i_3" name="i3" type="text" one-required="foo-bar" ng-model="data.i3"/>
<span> i3-err-one-required: {{forms.myForm.i3.$error.oneRequired}} </span> <br>
</form>
</body>
I have a form with 2 input fields and requirement is that once user enters valid data into these
fields, I need to pass the input data to the factory function and get the data from server.To achieve this I thought of using $watch function but stuck at how to know if form is valid in $wathc function and then call the factory function to get data from the server.Here is the code.
Any help would be highly appreciated.
//html
<html>
<body ng-app="myModule">
<div ng-controller="myCtrl">
Product Id: <input type="text" ng-model="myModel.id" /><br/>
Product Name: <input type="text" ng-model="myModel.productname" /><br/>
</div>
</body>
</html>
//js
var myModule = angular.module('myModule',[]);
myModule.controller('myCtrl',['$scope', function($scope){
$scope.myModel = {};
var getdata = function(newVal, oldVal) {
};
$scope.$watch('myModel.id', getdata)
$scope.$watch('myModel.productname', getdata)
}]);
Wouldn't you just watch myModel, since the same function is called in both cases?
You could do this with ng-change just as easily.
<html>
<body ng-app="myModule">
<form name="productForm" ng-controller="myCtrl">
<div>
Product Id: <input type="text" name="idModel" ng-model="myModel.id" ng-change="validateID()" /><br/>
Product Name: <input type="text" ng-model="myModel.productname" ng-change="validateProduct()" /><br/>
</div>
</form>
</body>
And your JS would look like this:
var myModule = angular.module('myModule',[]);
myModule.controller('myCtrl',['$scope', 'myFactory',
function($scope, myFactory){
$scope.myModel = {};
$scope.validateID = function(){
//things that validate the data go here
if(your data is valid){
myFactory.get(yourParams).then(function(data){
//whatever you need to do with the data goes here
});
}
};
$scope.validateProduct = function(){
//things that validate the data go here
if(your data is valid){
myFactory.get(yourParams).then(function(data){
//whatever you need to do with the data goes here
});
}
};
}
]);
Using ng-change saves you from having to add a $watch to your scope (they are expensive) and will fire when the user leaves the input box. If you need to catch each keystroke, I would recommend that you use UI-Keypress and run the same functions.
To know if form is valid you have to add a form tag and inside your controller check $valid, on your example the form is always valid becaus you do not have any required field.
See the below example on codepen
The HTML
<div ng-app="myModule">
<div ng-controller="myCtrl">
<form name="myform" novalidate>
Product Id:
<input type="text" ng-model="myModel.id" />
<br/>
Product Name:
<input type="text" ng-model="myModel.productname" />
<br/>
</form>
<br/>
<div>{{result}}</div>
<div>Form is valid: {{myform.$valid}}</div>
</div>
</div>
The JS
var myModule = angular.module('myModule', []);
myModule.controller('myCtrl', ['$scope', function ($scope) {
$scope.myModel = {};
$scope.result = "(null)";
var getdata = function (newVal, oldVal) {
var valid = null;
if ($scope.myform.$valid) {
valid = "is valid";
} else {
valid = "is INVALID";
}
$scope.result = "Changed value " + newVal + " form " + valid;
};
$scope.$watch('myModel.id', getdata);
$scope.$watch('myModel.productname', getdata);
}]);
In Angularjs, I'm trying to pass a value from a textbox to method written in controller as below
#Try 1
<input type="text" ng-blur="isExists(this.value)">
and within my controller I have
$scope.isExists = function (theValue) {
alert(theValue);
};
It is not working.
#Try 2
<input type="text" ng-model="username" ng-blur="isExists()">
and within controller
$scope.isExists = function () {
alert($scope.username); // returns undefined
};
How to pass value from ng-blur to a method within a Controller?
Updates:
Any reason why the valueis not seen in the textbox?
<input type="text" ng-model="username" ng-blur="isExists()">
Fiddle
Try2 should not return undefined if the <input type="text"
is filled with at least one character.
You can append {{ username }} on the html page just for debug purporses to make sure it was well binded.
<input type="text" name="userId" id="txtid" />
<script type="text/javascript">
$(document).ready(function () {
$('#txtid').blur(function () {
debugger;
var id = $('#txtid').val();
window.location = "/Home/CreateSupplier/?userid=" + id;
});
});
</script>
In controller
public ActionResult CreateSupplier(string userid)
{
if (userid != null)
{
return Content("Received Username:" + userid);
}
return View(thesupplierList);
}