AngularJS fire ng-change when changing a model - javascript

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();
});

Related

How to control the disability state of HTML inputs using Javascript

I have been trying to cycle between the disability states of two inputs on my website by using a button attached to some JavaScript. My current code has two buttons in use which both disable one input and enable the other, however this is not very practical. I wanted to know how I can use one button and one script to cycle between the disability states of my inputs, this is my current code:
<script>
function switch_monthlyexpense()
{
document.getElementById("monthlyexpenses").disabled=false;
document.getElementById("monthlypexpenses").disabled=true;
}
</script>
<script>
function switch_monthlypexpense()
{
document.getElementById("monthlyexpenses").disabled=true;
document.getElementById("monthlypexpenses").disabled=false;
}
</script>
<button class="btn btn-primary" onclick="switch_monthlyexpense()" id="monthlyexpensestoggle">Expenses</button>
<button class="btn btn-primary" onclick="switch_monthlypexpense()" id="monthlypexpensestoggle">P Expenses</button>
<form id="expenses_form" style="visibility:visible;">
<div class="form-group">
<div class="form-group col-md-1">
<label for="monthlyexpenses" id="monthlyexpenseslabel">Monthly Expenses</label>
<input type="number" class="form-control" id="monthlyexpenses" placeholder="0" disabled>
</div>
<span class="input-group-text" id="dsign5">$</span>
</form>
<form id="pexpenses_form" style="visibility:visible;">
<div class="form-group">
<div class="form-group col-md-1">
<label for="monthlypexpenses" id="monthlypexpenseslabel">Monthly P Expenses</label>
<input type="number" class="form-control" id="monthlypexpenses" placeholder="0">
</div>
<span class="input-group-text" id="psign4">%</span>
</form>
<script>
// use a variable to note which one is disabled
let selected = "monthlyexpenses"
function switchDisabled () {
// toggle the from "monthlyexpenses" to "monthlypexpenses" or vice versa
selected = selected === "monthlyexpenses" ? "monthlypexpenses" : "monthlyexpenses"
// check if the DOM disabled state is the same as the selected
document.getElementById("monthlyexpenses").disabled = selected === "monthlyexpenses";
document.getElementById("monthlypexpenses").disabled = selected === "monthlypexpenses";
}
</script>
<button class="btn btn-primary" onclick="switchDisabled()" id="switch-button">Switch</button>
<form id="expenses_form" style="visibility:visible;">
<div class="form-group">
<div class="form-group col-md-1">
<label for="monthlyexpenses" id="monthlyexpenseslabel">Monthly Expenses</label>
<input type="number" class="form-control" id="monthlyexpenses" placeholder="0" disabled>
</div>
<span class="input-group-text" id="dsign5">$</span>
</form>
<form id="pexpenses_form" style="visibility:visible;">
<div class="form-group">
<div class="form-group col-md-1">
<label for="monthlypexpenses" id="monthlypexpenseslabel">Monthly P Expenses</label>
<input type="number" class="form-control" id="monthlypexpenses" placeholder="0">
</div>
<span class="input-group-text" id="psign4">%</span>
</form>
disabled is an attribute so you can set it by:
document.getElementById("myId").setAttribute('disabled', '');
And to enable the element:
document.getElementById("myId").removeAttribute('disabled');
Your first function will look like:
function switch_monthlyexpense()
{
document.getElementById("monthlyexpenses").removeAttribute('disabled');
document.getElementById("monthlypexpenses").setAttribute('disabled', '');
}

angular 4 submit form by pressing enter with login button

Is it possible to submit a form that have a submit button (by pressing enter)
I have two text fields by clicking the login button I am able to process the outcome but I am unable to do it by hitting enter.
Here is the HTML code(updated with full code)
this is signin.component.html
<div class="modal-content" style="padding: 10px;" id="login" *ngIf="show">
<div class="modal-body text-left">
<div class="login">
<h2>Login</h2>
<hr>
<div class="row socialButtons">
<div class="col-xs-12 col-sm-12 col-md-4">
<a class="btn btn-lg btn-block btn-facebook" (click)="signInFacebook()">
<i class="fa fa-facebook visible-xs"></i>
<span class="hidden-xs">Facebook</span>
</a>
</div>
<div class="col-xs-12 col-sm-12 col-md-4">
<a class="btn btn-lg btn-block btn-linked-in" (click)="signInLinkedin()">
<i class="fa fa-linkedin visible-xs"></i>
<span class="hidden-xs">Linkedin</span>
</a>
</div>
<div class="col-xs-12 col-sm-12 col-md-4">
<a class="btn btn-lg btn-block btn-google-plus" (click)="signInGoogle()">
<i class="fa fa-google-plus visible-xs"></i>
<span class="hidden-xs">Google</span>
</a>
</div>
</div>
<br>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12">
<form class="loginForm" #loginForm="ngForm" action="" autocomplete="off" method="POST">
<div class="form-group">
<label class="control-label" for="signupName">Email</label>
<input type="email" class="form-control" name="username" placeholder="Email" [(ngModel)]="username" required>
</div>
<div class="form-group">
<label class="control-label" for="signinPassword">Password</label>
<input type="password" class="form-control" name="password" placeholder="Password" [(ngModel)]="password" required>
</div>
</form>
<div class = "error"> {{ errMsg }} </div>
<button class="btn btn-lg btn-info btn-block btnlog" type="button" [disabled]="loginForm.invalid" (click)="login()">Login</button>
<hr>
</div>
</div>
<div class="row row-sm-offset-3">
<div class="col-xs-12 col-sm-12 col-md-6">
<p class="forgotPwd">
Forgot password? Reset
</p>
<p class="forgotPwd">
New User? Register now
</p>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="showSignUp">
<app-sign-up></app-sign-up>
</div>
<div *ngIf="showForgotPassword">
<app-forgot-password></app-forgot-password>
</div>
this signin.component.ts file
import { Component, OnInit } from '#angular/core';
import {NgbModal, NgbActiveModal} from '#ng-bootstrap/ng-bootstrap';
import { Router } from '#angular/router';
import { AuthService } from '../services/auth/auth.service';
#Component({
selector: 'app-sign-in',
templateUrl: './sign-in.component.html',
styleUrls: ['./sign-in.component.css']
})
export class SignInComponent implements OnInit {
username:string;
password:string;
show = true;
showSignUp = false;
showForgotPassword = false;
errMsg = "";
constructor(
private authService: AuthService,
public activeModal: NgbActiveModal,
) { }
ngOnInit() {
this.authService.getEmitter().subscribe(res => {
if(res){
this.activeModal.dismiss('success');
}
else{
this.username = "";
this.password = "";
this.errMsg = "Invalid Username/Password";
}
})
}
signInGoogle(){
this.authService.loginWithGoogle();
}
signInFacebook(){
this.authService.loginWithFacebook();
}
signInLinkedin(){
this.authService.loginWithLinkedin();
}
logOut(){
this.authService.logOut();
}
login(){
this.authService.login(this.username,this.password);
}
reset(){
this.show = false;
this.showSignUp = false;
this.showForgotPassword = true;
}
signup(){
this.show = false;
this.showSignUp = true;
this.showForgotPassword = false;
}
}
Use (keyup.enter)="focusableSubmit.click()" to input Password and call #focusableSubmit to Button login, this would perform the task and same for button as shown in code below.
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12">
<form class="loginForm" #loginForm="ngForm" action="" autocomplete="off" method="POST">
<div class="form-group">
<label class="control-label" for="signupName">Email</label>
<input type="email" class="form-control" name="username" placeholder="Email" [(ngModel)]="username" required>
</div>
<div class="form-group">
<label class="control-label" for="signinPassword">Password</label>
<input type="password" class="form-control" name="password" placeholder="Password" [(ngModel)]="password" required (keyup.enter)="focusableSubmit.click()">
</div>
</form>
<div class = "error"> {{ errMsg }} </div>
<button #focusableSubmit class="btn btn-lg btn-info btn-block btnlog" type="button" [disabled]="loginForm.invalid" (click)="login()">Login</button>
<hr>
</div>
</div>
Your button should be inside the form but you have closed it inside the two input fields.
Update your code like this
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12">
<form class="loginForm" #loginForm="ngForm" action="" (submit)="login()" autocomplete="off" method="POST">
<div class="form-group">
<label class="control-label" for="signupName">Email</label>
<input type="email" class="form-control" name="username" placeholder="Email" [(ngModel)]="username" required>
</div>
<div class="form-group">
<label class="control-label" for="signinPassword">Password</label>
<input type="password" class="form-control" name="password" placeholder="Password" [(ngModel)]="password" required>
</div>
<div class = "error"> {{ errMsg }} </div>
<button type="submit" class="btn btn-lg btn-info btn-block btnlog" [disabled]="loginForm.invalid" (click)="login()">Login</button>
</form>
<hr>
</div>
</div>
Yes you can.
Usually, you need to put your code in action="". But this isn't old HTML, this is Angular, and it works with Javascript.
So, in order to do that, you need to add the novalidate tag, and tell the form what to do when you validate it.
You also need to declare a submit input instead of your button.
This would look like
<form class="loginForm" novalidate (ngSubmit)="login()" autocomplete="off">
<input type="submit" value="Login" class="btn btn-lg btn-info btn-block btnlog" [disabled]="loginForm.invalid" (click)="login()"/>
Yes it is possible and quite easy!
First you have to replace
(button)="button()"
with
(ngSubmit)="login()"
and remove the click handler from the button and change the type to submit.
Both lines changed look like this:
<form class="loginForm" #loginForm="ngForm" action="" autocomplete="off" (ngSubmit)="login()" method="POST">
and:
<button type="submit" class="btn btn-lg btn-info btn-block btnlog" [disabled]="loginForm.invalid">Login</button
Dont forget that this way, that button() does not get called.
Angular documentation is really helpful on most of the generel topics, maybe you should take a look there.
Additionally you should consider reading up on some basic information about forms. I personally suggest: forms on MDN and buttons on MDN.
Here's a strapped version of my form for sending comments.
As you see, I prevented the ENTER event on textarea and that will cause pressing ENTER while focused on textarea to not make a new line (but you can use SHIFT + ENTER).
Pressing enter sends a form.
<form #addCommentForm="ngForm" (keydown.enter)="addComment(addCommentForm.value)">
<textarea (keydown.enter)="$event.preventDefault()" type="text" placeholder="Leave a comment..." name="description" #description="ngModel" [(ngModel)]="comment.description"></textarea>
</form>
Give a try to
<button type="submit" class="btn btn-lg btn-info btn-block btnlog" [disabled]="loginForm.invalid" (click)="login()">Login</button>

My angular form validation doesn't work

I use bootstrap with angular, and I disabled bootstrap's validation, angular still doesn't work. It seems that I already set everything.
My code likes below, every input's validation didn't.
<form novalidate name="new_people" ng-if="is_editting_newpeople" class="form-horizontal" role="form" ng-submit="save_new_people()">
<div class="input-group">
<div class="input-group-addon">True Name</div>
<input class="form-control" name="realname" type="text" ng-model="editting_people.realname" autofocus required>
</div>
<div class="input-group">
<div class="input-group-addon">Nickname</div>
<input type="text" name="nickname" class="form-control" id="nickname" ng-model="editting_people.nickname" required>
</div>
<div class="input-group">
<div class="input-group-addon">Mobilenumber</div>
<input type="text" class="form-control" id="mobile" name="mobilenumber" ng-model="editting_people.mobilenumber" required ng-minlength=11>
</div>
<div class="input-group">
<div class="input-group-btn">
<button type="button" class="btn btn-default
dropdown-toggle" data-toggle="dropdown">{{ editting_people.idclass.name }}
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li ng-repeat="id_class in IDCLASSES">
<a ng-click="set_id_class(id_class)">{{ id_class.name }}</a>
</li>
</ul>
</div>
<!-- /btn-group -->
<input type="text" class="form-control" ng-model="editting_people.idnumber" required name="idnumber">
</div>
<!-- /input-group -->
<br>
<input class="btn btn-primary" type="submit" value="Submit" />
<input class="btn btn-default" value="取消" type="button" ng-click="cancel_new_people()" />
</form>
What do you mean by input doesn't work?
Post your code of related controller please, because it is not clear what validation are you doing. If you have novalidate you should organize validation in your angular controller or HTML, e.g.:
<div ng-show="editting_people.realname.length<4">
Any error message here.
</div>

Dynamic form addition/subtraction with angularjs

I am trying to get my dynamic form additions/subtractions to work correctly. The situation is that I am able to get the form block to add or remove, however, when I click the remove button it removes the most recently added block rather than the one I click on.
For example, if I add two new form blocks for a total of 3 blocks (block1, block2, block3) and I click remove on block2, instead of removing block 2 it removes block3.
I have created a plunker that demonstrates this, but it ONLY works when you launch the preview side in a separate window (otherwise the add button is inactive for some reason).
Working Example (must open in popup preview in plunker to function): plunker
<form class="form-horizontal" name="cpdForm" novalidate="" ng-submit="processForm()" ng-show="!message">
<h2>Subcontractor Performance</h2>
<hr />
<div ng-repeat="subcontractor in subcontractors">
<div class="well well-sm">Subcontractor #{{subcontractor.id}} <span id="subCounter"></span>
<button type="button" ng-click="removeSub()" class="close" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="form-group">
<div class="col-md-6">
<label for="subName">Subcontractor Name</label>
<input type="text" class="form-control" id="subName" name="subName" placeholder="Subcontractor" ng-model="formData.subName['subName'+($index+1)]" />
</div>
<div class="col-md-3">
<label for="mwbeCert">Disadvantaged Certification</label>
<select class="form-control" name="mwbeCert" ng-model="formData.mwbeCert" required="">
<option value="">Select MWBE Certification...</option>
<option ng-repeat="item in dropdownpoll['mwbecert']" value="{{item.mwbeid}}">{{item.mwbe}}</option>
</select>
</div>
<div class="col-md-3">
<label for="subAmount">Contracted Amount</label>
<div class="inner-addon left-addon">
<i class="glyphicon glyphicon-usd"></i>
<input type="text" class="form-control" id="subAmount" name="subAmount" placeholder="Contracted Amount" ng-model="formData.subAmount" />
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-4">
<label for="subContactName">Contact Name</label>
<input type="text" class="form-control" id="subContactName" name="subContactName" placeholder="Contact Name" ng-model="formData.subContactName" />
</div>
<div class="col-md-4">
<label for="subContactPhone">Contact Phone</label>
<input type="text" class="form-control" id="subContactPhone" name="subContactPhone" placeholder="Contact Phone" ng-model="formData.subContactPhone" />
</div>
<div class="col-md-4">
<label for="subContactEmail">Contact Email</label>
<input type="text" class="form-control" id="subContactEmail" name="subContactEmail" placeholder="Contact Email" ng-model="formData.subContactEmail" />
</div>
</div>
<div class="form-group">
<div class="col-md-3">
<label for="subRating">Subcontractor Rating</label>
<select class="form-control" name="subRating" ng-model="formData.subRating" required="">
<option value="">Select Subcontractor Rating...</option>
<option ng-repeat="item in dropdownpoll['subrating']" value="{{item.subratingid}}">{{item.rating}}</option>
</select>
</div>
<div class="col-md-9">
<label for="subComment">Comments</label>
<input type="text" class="form-control" id="subComment" name="subComment" placeholder="Comments" ng-model="formData.subComment" />
</div>
</div>
<hr />
<button type="button" class="btn btn-info btn-sm pull-right" ng-show="showAddSub(subcontractor)" ng-click="addNewSub()">[+] Add New Sub</button>
</div>
<input type="hidden" style="display:none;" ng-model="formData.subCount" value="{{subcontractor.id}}" />
<div class="form-group">
<div class="col-sm-12">
<button class="btn btn-primary" id="submit" ng-click="submitting()" ng-disabled="buttonDisabled">{{submit}}</button>
</div>
</div>
</form>
<pre>{{formData}}</pre>
you are splicing $scope.subcontractors-1 which only behaves like it does, ie, removes the last one.
try using $event.currentTarget as a general rule, it will indicate the clicked item exactly, and don't forget to pass $event as a parameter for the remove function.
I hope this helps you
You need to pass an index to the function removeSub
I modified your fn to accept an index
$scope.removeSub = function(ind) {
var newItemNo = $scope.subcontractors.length-1;
$scope.subcontractors.splice(ind-1, 1);
};
and in your HTML you just pass the currently iterated $index
<button type="button" ng-click="removeSub($index)" class="close" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
Hope this works. But be careful your formdata and subcontrators array are not in sync after this, thats a programming logic I guess you have to fix.
Happy coding
Cheers.
Joy
Not a full answer but your not telling the function in your script.js which one to remove your just telling it to chop one off the end. Try setting it up so that you pass the current subContractor id like ng-click="removeSub({{subcontractor.subContractorId}})" (not sure what your data model is) you could also reference the index but I believe that would be harder.

Form gets submitted even if the required fields are left empty in angular JS

I am newbie to angular JS and i have created a form which is
HTML
<div data-ng-controller="ReservationController"
<form class="form-horizontal" role="form">
<div class="form-group">
<div class="col-sm-10">
<label>Guest Name</label>
<input type="text" class="form-control" placeholder="" ng-model="res_guest_name" required>
</div>
</div>
<div class="form-group">
<div class="col-sm-10">
<label>Phone</label>
<input type="phone" class="form-control" ng-model="res_member_phone">
</div>
</div>
<div class="form-group">
<div class="col-sm-10">
<label>FAX</label>
<input type="phone" class="form-control" ng-model="res_member_fax">
</div>
</div>
<div class="form-group">
<div class="col-sm-10">
<label>Email</label>
<input type="email" class="form-control" ng-model="res_member_email" required>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-8 col-sm-10">
<button type="submit" class="btn btn-success" ng-click="res_save()">Save Changes</button>
</div>
</div>
</form>
</div>
CONTROLLER
function ReservationController($scope, $http, $cookieStore,$location,$filter) {
$scope.res_save = function()
{
var save_res ="https://pbg.com/save_form.html?contactid="+conId+"&token="+token+"&id="+$scope.resId+"&page=edit&guest_name="+$scope.res_guest_name+"&phone="+$scope.res_member_phone+"&fax="+$scope.res_member_fax+"&email="+$scope.res_member_email;
$http.get(save_res).success(function(response) {
alert('success');
});
}
}
My form gets submitted even after the required fields are left empty. it shows the error, then it gets submitted.
Obviously it will submit the form you didn't handled the submission of form.You just managed the errors :-)
Use ng-disabled="myForm.$invalid"
where myForm is the name field on form
<form class="form-horizontal" name="myForm" role="form">
<button type="submit" class="btn btn-success" ng-disable="myForm.$invalid" ng-click="res_save()">Save Changes</button>
If you don't want the button to be disable till then you can use
<button type="submit" class="btn btn-success" ng-click="res_save(myForm.$valid)">Save Changes</button>
And in controller
$scope.res_save = function(valid)
{
if(valid){
var save_res ="https://pbg.com/save_form.html?contactid="+conId+"&token="+token+"&id="+$scope.resId+"&page=edit&guest_name="+$scope.res_guest_name+"&phone="+$scope.res_member_phone+"&fax="+$scope.res_member_fax+"&email="+$scope.res_member_email;
$http.get(save_res).success(function(response) {
alert('success');
});
}
}
You are not checking for Form valid state before saving it , don't expect angular to magically stop saving when form is invalid.
You should look into the documentation for ng-submit. If you move the res_save function into an ng-submit on the form (and removed the ng-click on the submit input) it will validate against required fields, prevent execution of the function until they are valid.

Categories

Resources