AngularJS - Running a funcion on false of ng-pattern - angularjs

I know that this issue has been mentioned before. Although I believe that this issue is slightly different.
Link
Link
I have the following code
<textarea name="Text2" cols="40" rows="2" ng-model="pageModel.storeText" ng-pattern="/^(?:\d+(?:, *|))*\d+$/" class="form-control"></textarea>
<span ng-show="itemStoreForm.Text2.$error.pattern">ERROR</span>
I need the ng-show in the span to initiate a function I have based in a controller:
$scope.storeError = function(){
messageService.setMessage("messageContainer", "Please enter store numbers in correct format", "danger");
};
How can I call the function storeError()?

If you can access the scope-object from your controller, try
$scope.$watch('itemStoreForm.Text2.$error', function(error) {
if (error && error.pattern) {
$scope.storeError();
}
});
Since the FormController is published on $scope via name, it should be accessible for a watch-function.

Related

Get value from input type email with Angular

How can I pass the value of an <input type='email'> using angularjs. I need to validate the email address on the input of my form and need to generate a key with this. The only thing I need to know is how should I get the value from the input.
angular.module('myApp', [])
.controller('EmailController', function($scope) {
$scope.hash = "";
$scope.generateKey = function () {
var resultKey = $scope.email;
// TODO: generate key
// Assing value to hash
$scope.hash = resultKey;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="EmailController">
<form>
<p>Email: <input type="email" ng-model="email" ng-keyup="generateKey()"></p>
<p><b>Hash: </b>{{hash}}</p>
</form>
</div>
Edit 1
I could use <input type='text'> and validate with a regex but I want to use type='email' as in the cellphone display more options on the keyboard. Does exist a way to get the input value using angular even if it isn't a valid email?
Use ng-model-options="{ allowInvalid: true }" if you want invalid email addresses to be bound to your controller:
<input type="email" ng-model="email" ng-keyup="generateKey()" ng-model-options="{ allowInvalid: true }">
Edit: You usually shouldn't data-bind to a primitive because prototypal inheritance can sometimes lead to binding to the wrong scope. Try binding to an object instead, like data.email.
Edit: Live example
The way angular handles input values and validations is via $parsers. you can intercept the default parsers and therefore get the value before it get to the email validation. Created this little snippet to further illustrate my point. Notice that I am not using .push to add my parser but instead I am using .unshift. I use unshift rather than push because I want to make sure my parser is the first on the list. or at least, the first at the moment i added to the list. This will guarantee that it runs before the default parsers which are already in the list by the time my code runs.
var app = angular.module('myApp', []);
app.controller('EmailController', function($scope) {
$scope.hash = "";
});
app.directive('generateKey', function(){
return {
require: ['ngModel'],
link: function(scope, element, attr, ctrls){
var ngModel = ctrls[0];
ngModel.$parsers.unshift(function(text){
scope.hash = text;
return text;
});
}
};
});
for a complete snippet, please visit: https://jsbin.com/vabofapigo/edit?html,js,output

How do i access a dynamically generated ng-model value of an input field using $scope.$watch in angularjs

I want to access a dynamically generated angular-ngmodel
value of an input field using $scope.$watch.
This is my code snippet below:
<body ng-app="myApp" ng-controller="myCtrl">
<form>
<input type="text" ng-model="<?php echo $product->id ?>" name="prid" />
<input type="submit" value="Add to Cart" ng-click="yea()"/>
</form>
</body>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.yea = function() {
$scope.$watch('xxx', function(){
var test = angular.copy($scope.xxx);
alert(test);
})
};
});
</script>
What I want to do actually: i want to get the dynamic generated value of
the text field above, then pass it through angularJS to a php variable.
So, I thought of the code above but got stucked (do not know what the xxx
wud be). Please, am I doing it the wrong way or is there any solution to
the code above?
Thanks
You could create your own directive:
<my-input my-input-id="{{'<?php echo $product->id ?>'}}"></my-input>
This way php should replace its code with the id, which you will then be able to use in your directive:
app.directive('myInput', function() {
return {
restrict: 'E',
scope: {
myInputId: '#'
},
template: '<input ng-model="myInputId" />'
};
});
Note that I haven't tested if this code really works. If you would create a plunkr or jsfiddle, I will be more than happy to take a look.
But I would personally never print out php in a way like this. Whenever I worked with PHP and Angular, I did HTTP calls from Angular to a PHP API. This way you have a clear separation between your Angular and PHP code.
You can use ngInit to initialize your model, like
<input type="text" ng-init="initPrid(<?php echo $product->id ?>)" ng-model="prId" name="prid" />
And then inside your controller add
$scope.initPrid = function(id) {
$scope.prId = id;
};

Angular directive making required field readonly

I'm trying to make a input field required and readonly.
The html standard does not allow this, so I tried to make my own directive for it, but the keydown/keypress bind is never made. Is there a way around this and why this does not work?
ngApp.directive('required', function() {
return {
require: '?input',
restrict: 'A',
link: function($scope,$element,$attr) {
if ($attr.hasOwnProperty('readonly')) {
$element.removeAttr('readonly');
$element.bind('keydown keypress', function(e){
e.preventDefault();
});
}
}
};
});
plnkr.co/edit/XhTxPpqnKwSFKJflSHZW?p=preview .... second text field, required is never validated by the system!
cheers
c_bb
EDIT: I just re-read your question and thought about it again, and my original answer is crap. You really do want novalidate on your form, and then you show errors in an angular type way rather than trying to use html form validation, which isn't going to work for you for the reasons you mention in the comments.
You want your form to looks something like this:
<form name="testForm" ng-submit="submitForm(testForm.$valid)" novalidate >
<input type="text" name="value" ng-model="test1" required><br>
<input type="text" name="value2" ng-model="test2" required readonly><br>
<p ng-show="testForm.value2.$error.required" class="help-block">Please select a whatever</p>
<input type="submit" ng-click='testForm.$valid && mySubmitFunction()'>
</form>
This will give you an error message based on the stock angular validation for required.
and you need some kind of a submit handler in your controller, like this:
$scope.submitForm = function(isValid) {
// check to make sure the form is completely valid
if (isValid) {
alert('our form is amazing');
} else {
console.log('fail')
}
};
Do whatever sensible things you need in the submit function.
//OLD, TERRIBLE ANSWER BELOW
If the readonly attribute does indeed override the required attribute the 'proper' solution would probably to write some custom validation (see article at http://ng-learn.org/2014/02/Writing_Custom_Validitions/).
However, if you just want a cheap way out, you could put a ng-minlength=1 requirement on the input. If the user can't put anything in the field manually, and there has to be something in the field for it to be valid, I think you've basically got what you want.

Why I cannot access form angular's properites in JS such as $error?

I cannot access angular's Form members. I don't have a clue why. I'm using angular 1.4. The full code is at: http://jsbin.com/lujojiduru/edit?html,js,console,output
angular.module('test',[]).controller('testController', function($scope){
$scope.sendInvitations = function(){
var error = myForm.NewInvitations.$error;
console.log('sent');
console.log('value: ' + error );
};
});
the value of $error is always undefined. Any idea?
var error = myForm.NewInvitations.$error;
should be:
var error = $scope.myForm.NewInvitations.$error;
Notice the $scope
This is assuming you have the name="myForm" on your <form> tag
So something like:
<div ng-controller="testController">
<form name="myForm" novalidate>
...
</form>
</div>
you can also, if you prefer, send in the validity of your form, to your method on the controller.
So:
<button class="btn btn-success" ng-click="sendInvitations(myForm.$valid)">Send Invitations</button>
And in your controller:
$scope.sendInvitations = function(isValid){
if(!isValid)
return;
};
Update
You also don't have any errors.
Add required to your input.
So your controller is now:
angular.module('test',[]).controller('testController', function($scope){
$scope.sendInvitations = function(){
debugger;//
var error = $scope.myForm.NewInvitations.$error;
console.log('sent');
console.log(error );
};
});
and your input
<input style="width: 95%" name="NewInvitations" type="email" ng-model="newInvitations" required />
This is an update to your bin
http://jsbin.com/hebikucanu/1/edit?html,js,console,output
myForm is not accessible in the global scope. You can pass it in as an argument to sendInvitations.
ng-click="sendInvitations(myForm)
$scope.sendInvitations = function(myForm){
It's unlikely that you'd need to do this, though. You can do use the myForm properties in the view.
In angular, you should never touch the DOM. Meaning, you should never invoke HTML elements directly as you would in traditional HTML/JS settings. (read more)
Angular encourages the use of ng-model to employ two-way binding as a means to communicate between the controller and the view. (angular two-way data binding tutorial)
Thus, the first change you should attempt is to replace
var error = myForm.NewInvitations.$error;
with:
var error = $scope.NewInvitations;
This will cause the code to run.
But it appears that you want to retrieve the email input validation error and display it through angular.
Here is an excellent explanation with a tutorial that I think achieves what you're trying to do. If you just want to see the code in action, try this link. (Be sure to hit the Run button.)
Hope this helps!

pre-populated form data is undefined in service

jQuery:
$("#inputParentName").val(response.name);
HTML/Angular Form:
<form role="form" ng-submit="addParentService.addParent()">
<div class="form-group">
<label for="inputParentName">Name</label><input class="form-control" id="inputParentName" value="" type="text" ng-model="addParentService.inputParentName" />
</div>
...
<button class="btn btn-default" type="submit">Submit</button>
</form>
The following code when run diplays my name correctly in the input box.
However in my service when I try to see what the value is for inputParentName I get an undefined error. But, when I type something in to the textbox for inputParentName the typed in value displays.
Controller Code:
myapp.controller('AddParentController', function ($scope, addParentService) {
$scope.addParentService = addParentService;
});
Service Code:
myapp.service('addParentService', function () {
var vm = this;
vm.parent = [];
vm.addParent = function () {
alert(vm.inputParentName);
};
});
What can I do differently so I can get the pre-loaded data to register so that my service recognizes the data?
This is just basic code that I'm trying to get working. I realize it isn't pure AngularJS. I am just trying to see how I can get this to work. I will refactor with directives after everything works as I think it should.
If you want the initial value to be "something" when the view displays, you can (technically) use ng-init, though the docs tell us expressly NOT to do this.
The only appropriate use of ngInit is for aliasing special properties
of ngRepeat, as seen in the demo below. Besides this case, you should
use controllers rather than ngInit to initialize values on a scope.
But if you're just trying to test something, ng-init would look like:
<input ng-model="test.val" ng-init="test.val='something'" />
The preferred way though would be to add the value to the controller $scope.
<input ng-model="test.val" />
Then in your controller:
myapp.controller('MyCtrl', function ($scope) {
$scope.test = {
val: 'something'
}
});
#jme11 and This Answer gave me the insight to the following way I figured out how to get this to work:
jQuery code for Facebook logic:
$("#inputParentName").val(response.name);
$("#inputParentEmail").val(response.email);
$("#inputParentBirthday").val(response.birthday);
angular.element(document.getElementById('inputParentName')).scope().$apply();
angular.element($('#inputParentName')).scope().setName(response.name);
angular.element($('#inputParentEmail')).scope().setEmail(response.email);
angular.element($('#inputParentBirthday')).scope().setBirthday(response.birthday);
My Controller code:
$scope.setName = function (val) {
addParentService.inputParentName = val;
}
$scope.setEmail = function (val) {
addParentService.inputParentEmail = val;
}
$scope.setBirthday = function (val) {
addParentService.inputParentBirthday = val;
}
Service Code:
vm.addParent = function () {
alert(vm.inputParentName);
alert(vm.inputParentBirthday);
alert(vm.inputParentEmail);
alert(vm.inputParentCellPhone);
alert(vm.inputParentCarrier);
};
Now when I'm adding my Parent the values pre-populated from Facebook are usable in my service code.
Again - Thanks to jme11 for helping me solve this.

Resources