Angular make input valid manually - javascript

I am using a bootstrap datepicker. when i click on the icon date& time automatically enters into the input. but the input remained as invalid since i did not interacted with it directly. has any one faced this problem.
here is the plnkr for that: http://plnkr.co/edit/yBmwZCCPvTOQWE6q3BW5
view
<body data-ng-controller="ReservationController as resvnCtrl">
<div class="container">
<div class="col-lg-6 col-lg-offset-3 col-md-8 col-md-offset-2 col-sm-12 col-xs-12 ">
<div>
<h2 class="text-center page-heading">Make a reservation</h2>
</div>
<div>
<form role="form" name="resvnCtrl.form" data-ng-submit="resvnCtrl.submitForm(resvnCtrl.form.$valid)" novalidate>
<div class="form-group" data-ng-class="{'has-error':resvnCtrl.form.time.$invalid && (resvnCtrl.form.time.$dirty || resvnCtrl.form.$submitted) }">
<label class="control-label">Date-Time</label>
<div class='input-group date' id='datetimepicker'>
<input type="text" name="time" id="time" data-ng-model="resvnCtrl.reservation.time"
placeholder="Enter Desired Time" class="form-control" required>
<span class="input-group-addon pointer" data-date-picker>
<i class="fa fa-calendar"></i>
</span>
</div>
<div data-ng-messages="resvnCtrl.form.time.$error" data-ng-if="resvnCtrl.form.time.$dirty || resvnCtrl.form.$submitted">
<p class="help-block" data-ng-message="required">Date and Time required</p>
</div>
</div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<input type="submit" name="submit" id="submit" value="Make Reservation" class="btn btn-primary btn-block " >
</div>
</div>
</form>
</div>
</div>
</div>
</body>
controller
var app = angular.module('plunker', []);
angular.module('plunker')
.controller('ReservationController',ReservationController);
ReservationController.$inject=['$scope'];
function ReservationController($scope) {
var resvnCtrl=this;
resvnCtrl.reservation={};
resvnCtrl.confirmation={};
$('#datetimepicker').datetimepicker();
resvnCtrl.submitForm=function(isValid){
alert("valid:"+resvnCtrl.form.time.$valid);
}
}

I think you can refer to angular-strap:http://mgcrea.github.io/angular-strap/#/datepickers. when you import angular-strap.min.js, angular-strap.tpl.min.js and libs.min.css to your index.html. your app.js should be like this:
var app = angular.module('plunker', ['mgcrea.ngStrap.datepicker']);

That's the curse of usage jQuery within angular. Your models controller updates only $viewValue when plugin initialized and that does not trigger digest. Digest triggered my another action - focus in or out that is run digest.
Solution for this is watcher that will manually set $modelValue by $setViewValue() method so angular will know something happened and update validation.
And please, create separate directive for datepicker that will initialize it on element you used directive on.

Related

Unable to get value from html to controller

Here I am sending data of mail id and its visibility to server for two different users for one I have included mail and its visibility and for another hiding visibility.
To hide visibility I am using <div ng-if="atom.type === 'person'">.
Hiding and showing is working properly but problem is that on both case
it is showing visibility undefined.
If I am not using <div ng-if="atom.type === 'person'">. then it is properly sending visibility.
How to resolve this?
My Code is bolow
var myApp = angular.module('myApp', ['ngMessages']);
myApp.controller('profileInfo', function($scope, $http) {
$scope.authorized = false;
$scope.visibility = ["Private", "Friends", "Public"];
$scope.id = 0;
$atom.type = 'person';
$scope.addMailId = function(data) {
console.log(data);
$scope.mailidDetaillD = {
'mailidDetaillList[0].email': data.mailid,
'mailidDetaillList[0].visibility': data.visibility,
'pageId': $scope.id,
};
console.log($scope.mailidDetaillD);
}
});
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.9/angular-messages.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.9/angular.min.js"></script>
<dd class="col-sm-7 col-md-7 col-lg-7">
<div class="pull-right" ng-if="authorized">
<a ng-click="showAddMailIdDiv()" ng-model="addMailIdLink">add MailId Details</a>
<div class="add-school" ng-show="showAddMailId">
<form action="AddMailId" id="AddMailId" name="addmail" cssClass="form-horizontal">
<div class="form-group">
<div class="col-lg-2">
<label>Mail Id</label>
</div>
<div class="col-lg-6">
<input type="text" ng-model="mail.mailid" name="mailid" placeholder="Enter mail id" required class="form-control" />
<div ng-messages="addmail.mailid.$error" ng-if="addmail.mailid.$touched">
<p class="field-err" ng-message="required">MailId Required</p>
</div>
</div>
</div>
<div ng-if="atom.type === 'person'">
<div class="form-group">
<div class="col-lg-2">
<label>Visibility</label>
</div>
<div class="col-lg-6">
<select ng-model="mail.visibility"
ng-init=" mail.visibility = visibility[1]"
ng-options="x for x in visibility"
class="form-control"
name="mailvisibility" required>
</select>
<div ng-messages="addmail.mailvisibility.$error" ng-if="addmail.mailvisibility.$touched">
<p class="field-err" ng-message="required">Select Mail visibility</p>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="col-lg-2">
<label class="sr-only">Submit</label>
</div>
<div class="col-lg-6 pull-right">
<input type="button" value="add" ng-click="addMailId(mail)" ng-disabled="addmail.$invalid" cssClass="btn btn-sm btn-primary" />
<input type="button" ng-click="hideAddMailIdDiv()" value="cancle" class="btn btn-sm btn-secondary" />
</div>
</div>
</form>
</div>
</div>
</dd>
last console.log is showing following result
mailidDetaillList[0].email: "W#w.com"
mailidDetaillList[0].visibility: undefined
pageId: 2337
after removing <div ng-if="atom.type === 'person'">
mailidDetaillList[0].email: "ss#s.com"
mailidDetaillList[0].visibility: "Public"
pageId: 2337
Delete the ng-init:
<select ng-model="mail.visibility"
̶n̶g̶-̶i̶n̶i̶t̶=̶"̶ ̶m̶a̶i̶l̶.̶v̶i̶s̶i̶b̶i̶l̶i̶t̶y̶ ̶=̶ ̶v̶i̶s̶i̶b̶i̶l̶i̶t̶y̶[̶1̶]̶"̶
ng-options="x for x in visibility"
class="form-control"
name="mailvisibility" required>
</select>
And set visibility from the controller:
$scope.mail = { visibility: $scope.visibility[1] };
AngularJS is an MVC - Model-View-Controller framework. The framework renders the View from the Model. The Controller creates the Model. Using ng-init to create the Model is going the wrong way. It makes an App that is difficult to understand, test, debug, and maintain.
The ng-init directive can be abused to add unnecessary amounts of logic into your templates. There are only a few appropriate uses of ngInit. See AngularJS ng-init Directive API Reference.

AngularJS fire ng-change when changing a model

I have a form that looks like this:
<div class="col-xs-12 col-lg-4">
<form name="deliveryForm" ng-class="{ 'has-error': deliveryForm.$invalid && !deliveryForm.contact.$pristine }">
<div class="form-group">
<div class="btn-group">
<label class="btn btn-default" ng-model="controller.order.lines[0].forDelivery" btn-radio="true" ng-change="controller.setDeliveryDetails()">For delivery</label>
<label class="btn btn-default" ng-model="controller.order.lines[0].forDelivery" btn-radio="false" ng-change="controller.findCollectionPoints()">For collection</label>
</div>
</div>
<div class="form-group" ng-if="!controller.order.lines[0].forDelivery">
<label class="control-label">Contact</label>
<input class="form-control" type="text" name="contact" ng-model="controller.model.contact" ng-change="controller.setDeliveryDetails()" autocomplete="off" required />
<input type="hidden" name="collectionPoint" ng-model="controller.model.collectionPoint" ng-change="controller.setDeliveryDetails()" required />
</div>
<div class="form-group">
<label class="control-label">Instructions</label>
<input class="form-control" type="text" name="instructions" ng-model="controller.model.instructions" ng-change="controller.setDeliveryDetails()" autocomplete="off" />
</div>
<div class="form-group">
<button class="btn btn-default" type="button" ui-sref="saveOrder.lines">Back</button>
<a class="btn btn-primary pull-right" ng-if="deliveryForm.$valid" ui-sref="saveOrder.confirm">Continue</a>
</div>
</form>
</div>
As you can see, if my first line is not for delivery, then I show the contact input and the hidden collectionPoint input.
A bit further down I have a link that changes the collectionPoint:
What I was hoping would happen is that the hidden input would detect the change and fire the controller.setDeliveryDetails() method, but it doesn't seem to work.
Is there a way I can do this?
ng-change is triggered when changes are made on an input not on the model.
What you can do is either run controller.setDeliveryDetails() on ng-click :
Or set up a watch in your controller on controller.model.collectionPoint
$scope.$watch(angular.bind(this, function () {
return this.model.collectionPoint;
}), function (newVal) {
controller.setDeliveryDetails();
});

Binding data from view to controller in AngularJS

Hello I am building an angular application and I have a problem inside my stripe form. Basically I send data such as card number, expiry date and CVC code from the view to the controller's stripe callback, but I would like to add also the amount of money to pay. So I added this into my form:
<form stripe-form="handleStripe" name="myForm">
<!-- input added for the price -->
<div class="row" ng-if="!unregistered_user">
<div class="input-field col col-xs-12">
<label for="name">Amount </label>
<input name='price' type="number" id="amount" ng-model="price">
</div>
</div>
<!-- credit/debit card form -->
<div class="row">
<div class="input-field col col-xs-12">
<label for="cardn">Card number</label>
<input type="text" name="number" id="cardn" ng-model="number" payments-validate="card" payments-format="card" payments-type-model="type" ng-class="myForm.number.$card.type"/>
</div>
</div>
<div class="row">
<div class="input-field col-xs-6">
<label for="exp">Expiry</label>
<input type="text" id="exp" ng-model="expiry" payments-validate="expiry" payments-format="expiry" />
</div>
<div class="input-field col-xs-6">
<label for="cvc">CVC</label>
<input type="text" id="cvc" ng-model="cvc" payments-validate="cvc" payments-format="cvc" payments-type-model="type"/>
</div>
</div>
<div class="row">
<div class="input-field col-xs-12">
<button type="submit" class="btn btn-primary btn-large">Pay {{ price }}</button>
</div>
</div>
</form>
In the controller I have this variable:
▸   $scope.price = 0;
When I first load the page I can see that the price input has exactly the same amount that I put in the variable $scope.price. But when I changed it in the page and submit the form, $scope.price is always 0.
It's like the data is being passed from the controller to the view, but not the way back from the view to the controller.
How can I solve this?
I think your issue is with ng-if that wraps your input with price model. ng-if creates its own scope and in your case the price is connected with the scope inside ng-if and not with you controller.
You could use ng-show instead, or set the model like this: ng-model = "$parent.price" or use controllerAs syntax and you don't have to worry about this issue anymore.

Button Click event in Angular JS

I am trying to fire a button click event in angular Js but its not happening at all. Neither i am getting any kind of event related error in developer console of Chrome.
Here is the Markup..
<!-- Login Form Here !-->
<div id="login" ng-controller="LoginformController" style="display: none;" class="col-sm-5 form-box">
<div class="form-top">
<div class="form-top-left">
<h3>Login now</h3>
<p>Fill in the form below to get instant access:</p>
</div>
<div class="form-top-right">
<i class="fa fa-pencil"></i>
</div>
<div class="form-top-divider"></div>
</div>
<div class="form-bottom">
<form role="form" action="" method="post" class="registration-form">
<div class="form-group">
<label class="sr-only" for="UserID">User ID</label>
<input type="text" name="UserID" placeholder="User ID..." class="form-first-name form-control" id="UserID">
</div>
<div class="form-group">
<label class="sr-only" for="Password">Password</label>
<input type="text" name="Password" placeholder="Password..." class="form-last-name form-control" id="Password">
</div>
<button type="submit" class="btn">Login!</button>
<br/>
<button type="button" class="btn-sm btn-link" ng-click="PasswordRecovery()">Forgot Password</button>
</form>
</div>
</div>
and here is the anguar JS code..
var app = angular.module('LoginApp', []);
app.controller('LoginformController', function ($scope) {
$scope.PasswordRecovery = function () {
alert("Clicked 2");
}
});
Please help me to resolve this ..
If I would add
<div ng-controller="UnexistingController"></div>
to your HTML then I would get:
"Error: [ng:areq] Argument 'UnexistingController' is not a function,
got undefined
http://errors.angularjs.org/1.4.3/ng/areq?p0=UnexistingController&p1=not%20a%20function%2C%20got%20undefined
Which makes sense, since I did not add a controller to the module yet. I suspect you made the same mistake.
Argument 'SignupformController' is not a f‌​unction, got undefined
Description
AngularJS often asserts that certain values will be present and truthy
using a helper function. If the assertion fails, this error is thrown.
To fix this problem, make sure that the value the assertion expects is
defined and truthy
.
Works for me, I don't understand why you added style="display: none;, but it's not the problem.
See Plunker.

scope function inside controller not updating the values according to ng-models in the view

Hi i got this function in the controller that is called from the ng-view:
productApp.controller('ModalInstanceCtrl', function ($scope, $modalInstance, productFactory, prodId) {
$scope.ok = function () {
console.log($scope.model_productDescription);
$scope.$watch(['model_productBrand,model_productName,model_productDescription,model_productPrice, model_productStock'], function() {
var stock = '';
if($scope.model_productStock) {
stock = 'AVAILABLE';
}else{
stock = 'NO STOCK';
}
var productObject = {
id : prodId,
prodBrand : $scope.model_productBrand,
prodName : $scope.model_productName,
description : $scope.model_productDescription,
price : $scope.model_productPrice,
prodStock : stock
}
productFactory.updateProductById(productObject, function successCallback(data) {
// do something here in data
}, function errorCallback(data, status) {
alert(data + ' Failed with error ' + status);
});
})
};
});
This is the modal.htm body:
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" ng-click="cancel()">×</button>
<h4 class="modal-title">Modify a Product</h4>
</div>
<div class="modal-body">
<form class="form-horizontal">
<fieldset>
<!-- Row 1 -->
<div class="col-md-12 col-centered">
<div class="control-group">
<label class="control-label" for="prod_brand">Product Brand</label>
<input type="text" id="prod_brand" class="form-control"
ng-model="model_productBrand" required="required" value="prod.prodBrand">
</div>
<div class="control-group">
<label class="control-label" for="prod_name">Product Type</label> <input
type="text" id="prod_name" class="form-control"
ng-model="model_productName" required="required" value="prod.prodName">
</div>
<div class="control-group">
<label class="control-label" for="prod_price">Price</label>
<div class="input-group">
<span class="input-group-addon">$</span> <input type="text"
class="form-control" ng-model="model_productPrice" value="prod.price"> <span
class="input-group-addon">.00</span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="prod_description">Description</label>
<textarea id="prod_description" class="form-control" ng-model="model_productDescription" cols="70" rows="3">{{prod.description}}</textarea>
</div>
<div class="control-group" style="margin-top: 10px">
<div class="input-group">
<span class="input-group-addon"> <input type="checkbox" ng-model="model_productStock">
</span>
<span class="form-control no-cursor">Stock</span>
</div>
</div>
</div>
</fieldset>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="cancel()">Close</button>
<button type="button" class="btn btn-primary" ng-click="ok()">Edit product</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
Now, if i type in the textarea (for example), and press the ok button, it will get into this function. Now, since the textarea value has changed, shouldn't be reflected in the $scope.productDescription value? looks like it's not. I thought that whenever you make a change in the model, it would override the $scope.model_name value, should i use ng-change or any other directive for this?
Tried adding a $watch but it's not working either, any suggestion?
P.S: console.log($scope.model_productDescription); // shows the old description despite the fact i change it
Thanks.
The most probable cause of this is that your model.html is creating child scope. The changes that you do to the model property are local to child and cannot be seen in the parent due to prototypal inheritance.
What you can try is to create an object on the controller and do binding on object property.
$scope.productObject={};
Do the textarea binding to
<textarea id="prod_description" class="form-control" ng-model="productObject.productDescription" cols="70" rows="3">{{prod.description}}</textarea>
Now the changes would be reflected in productObject.productDescription property.
Also go through this wiki to understand how does scope inheritance works https://github.com/angular/angular.js/wiki/Understanding-Scopes
God... i'm going to fix it as of now by doing this:
From the view:
<button type="button" class="btn btn-primary" ng-click="ok(model_productBrand, model_productName, model_productPrice, model_productDescription, model_productStock)">Edit product</button>
From the controller passing the vars to the ok() function:
$scope.ok = function (model_productBrand, model_productName, model_productDescription, model_productPrice, model_productStock) {
Yeah... i know it looks UGLY as hell, but bleh...
Thank you, anyway i'm going to tick your answer as correct since the solution you gave me is really convenient, the only problem was that my project was kinda bad design for the solution you provided :P but is good!

Categories

Resources