AngularJS ng-repeat 'No Results' div visibility flickering on second button click - angularjs

The following form shows a list of data on submit. I am trying to show no results found when there is no data on submit. It works okay. But when there is data available to list, "no results" shows up for a second when i click. I tried using display:none; but it did not work. How to stop it from showing.
HTML
<form class="form-inline" name="myForm" >
<div class="form-group" >
<label class="radio-inline">
<input name="sampleinlineradio" value="3" type="radio" ng-model="radioption"
ng-required="!radioption"> MAIN 1</label>
<label class="radio-inline">
<input name="sampleinlineradio" value="1" type="radio" ng-model="radioption" >
Main 2</label>
<div ng-show="!radioption && buttonClicked">Please select one.</div>
</div>
<div class="form-group">
<label ng-repeat="branch in branches">
<input type="checkbox" name="selectedBranches[]" value="{{branch.value}}"
ng-model="branch.selected" ng-required="isOptionsRequired()" >
{{branch.name}}</label>
<div ng-show="isOptionsRequired() && buttonClicked">Please select one.</div>
</div>
<div>
<label class="searchlabel">
<input type="radio" name="searchradio1" value="showComponentSearch" ng-model="value"
ng-required="value == 'showComponentSearch'" >
Search By Component</label>
<input type="text" name="comptext" ng-model="search" id="tags"
ng-required = "value == 'showComponentSearch' && search == 'comptext'" >
<div ng-show="value == 'showComponentSearch' && !search && buttonClicked">Please enter text before submit.</div>
<div>
<label class="searchlabel">
<input name="searchradio2" value="showDateRangeSearch" type="radio" ng-model="value"
ng-required="value == 'showDateRangeSearch'" >
Search By Time</label>
</div> </div>
<div ng-show="!value && buttonClicked">Please select one search option.</div>
<input type="button" ng-click="fetchresults()" value="submit" >
</form>
<div ng-show="buttonClicked">
<table> <thead>.....</thead>
<tbody>
<tr ng-show="results.length!=0" ng-repeat="r in results">
<td></td></tbody></table>
</div>
<div ng-show="buttonClickedAgain">
<span ng-show="results.length==0 ">No results.</span>
</div>
In Controller
$scope.fetchresults = function(){
if($scope.searchSelectionValue == 'showComponentSearch') {
$scope.results = Result.query({main: $scope.radioption, branch: $scope.selection[0],
component:$scope.search });
if($scope.search) {
$scope.buttonClickedAgain = true;
}
}
$scope.buttonClicked = true;
};

You can try adding the line $scope.buttonClickedAgain = false; before the if statement as below.
$scope.fetchresults = function(){
$scope.buttonClickedAgain = false;
if($scope.searchSelectionValue == 'showComponentSearch') {
Result.query({main: $scope.radioption, branch: $scope.selection[0], component: $scope.search }, function(results){
$scope.results = results;
$scope.buttonClickedAgain = true;
});
//if($scope.search) {
//$scope.buttonClickedAgain = true;
//}
}
$scope.buttonClicked = true;
};
You can check the below snippet where result will come after 5 seconds. But when you click the button, no results div hides immediately. You can try this with multiple clicks. If it does not work properly to you then its because of other code issue which throws error and check your browser console.
var app = angular.module('app', []);
app.controller('TestController', function($scope, $timeout){
$scope.fetchresults = function(){
$scope.buttonClickedAgain = false;
if($scope.value == 'showComponentSearch') {
//$scope.results = Result.query({main: $scope.radioption, branch: $scope.selection[0],
// $scope.search });
$scope.results = [];
$timeout(function() {
var rnd = Math.random();
if(rnd >= 0.5) {
$scope.results = [{id: 1}, {id: 2}];
}
//if($scope.search) {
$scope.buttonClickedAgain = true;
// }
}, 5000);
}
$scope.buttonClicked = true;
};
});
angular.bootstrap(document, ['app']);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="TestController" >
<form class="form-inline" name="myForm">
<div class="form-group" >
<label class="radio-inline">
<input name="sampleinlineradio" value="3" type="radio" ng-model="radioption"
ng-required="!radioption"> MAIN 1</label>
<label class="radio-inline">
<input name="sampleinlineradio" value="1" type="radio" ng-model="radioption" >
Main 2</label>
<div ng-show="!radioption && buttonClicked">Please select one.</div>
</div>
<div class="form-group">
<label ng-repeat="branch in branches">
<input type="checkbox" name="selectedBranches[]" value="{{branch.value}}"
ng-model="branch.selected" ng-required="isOptionsRequired()" >
{{branch.name}}</label>
<div ng-show="isOptionsRequired() && buttonClicked">Please select one.</div>
</div>
<div>
<label class="searchlabel">
<input type="radio" name="searchradio1" value="showComponentSearch" ng-model="value"
ng-required="value == 'showComponentSearch'" >
Search By Component</label>
<input type="text" name="comptext" ng-model="search" id="tags"
ng-required = "value == 'showComponentSearch' && search == 'comptext'" >
<div ng-show="value == 'showComponentSearch' && !search && buttonClicked">Please enter text before submit.</div>
<div>
<label class="searchlabel">
<input name="searchradio2" value="showDateRangeSearch" type="radio" ng-model="value"
ng-required="value == 'showDateRangeSearch'" >
Search By Time</label>
</div> </div>
<div ng-show="!value && buttonClicked">Please select one search option.</div>
<input type="button" ng-click="fetchresults()" value="submit" >
</form>
<div ng-show="buttonClicked">
Records:
<table> <thead></thead>
<tbody>
<tr ng-show="results.length!=0" ng-repeat="r in results">
<td>{{r.id}}</td></tbody></table>
</div>
<div ng-show="buttonClickedAgain">
<span ng-show="results.length==0 ">No results.</span>
</div>
</div>

Use ng-if instead of ng-show on the div . ng-if prevents the div from being rendered
<div ng-show="buttonClickedAgain">
<span ng-show="results.length==0 ">No results.</span>
</div>

Related

How pass dynamic values to ProgressBar and below message based number forms completed?

I am displaying progress bar, progress bar status message bellow by passing static values, how can pass dynamic values to progress bar and bellow progress bar i need show progress bar status message dynamically. bellow I written code for static. please help me for passing dynamic values to progress bar, and progress bar status message.
html
----
<div ng-app="app" ng-controller="main">
<div>
<form ng-hide="form_1" name="form1" novalidate>
<span>
<input name="group1" type="radio" value="Yes" ng-model ="user.ans1" ng-required="true" />Yes
<input name="group1" type="radio" value="NO" ng-model ="user.ans1" ng-required="true" />No
</span><br/>
<span>
<input name="group2" type="radio" value="Yes" ng-model ="user.ans2" ng-required="true" />Yes
<input name="group2" type="radio" value="NO" ng-model ="user.ans2" ng-required="true" />No
</span><br/>
<span>
<button type="button" ng-disabled="form1.$invalid" ng-click="start();">start</button>
</span>
</form>
<form ng-show="form_2" name="form2" novalidate>
<div>
<p progressbar prog="form2.$valid ? '33':'0'" ></p>
<p>{{form2.$valid ? 'Set 1 of 3 completed':''}}</p>
</div>
<span>
<input name="group3" type="radio" value="Male" ng-model ="gender" ng-required="true" /> Male
<input name="group3" type="radio" value="Female" ng-model ="gender" ng-required="true" /> Female
</span><br/>
<button type="button" ng-disabled="form2.$invalid" ng-click="form2Next();" >Next</button>
</form>
<form ng-show="form_3" name="form3" novalidate>
<div>
<p progressbar prog="form3.$valid ? '66':'33'" ></p>
<p>{{form3.$valid ? 'Set 1 of 3 completed':''}}</p>
</div>
<span>
<input name="group4" type="radio" value="btech" ng-model ="course" ng-required="true" /> Btech
<input name="group4" type="radio" value="mtech" ng-model ="course" ng-required="true" /> Mtech
</span><br/>
<button type="button" ng-disabled="form3.$invalid" ng-click="form3Next();" >Next</button>
</form>
<form ng-show="form_4" name="form4" novalidate>
<div>
<p progressbar prog="form4.$valid ? '100':'66'" ></p>
<p>{{form4.$valid ? 'Set 1 of 3 completed':''}}</p>
</div>
<span>
<input name="group5" type="radio" value="software" ng-model ="emp" ng-required="true" /> software
<input name="group5" type="radio" value="hardware" ng-model ="emp" ng-required="true" /> hordeware
</span><br/>
<button type="button" ng-disabled="form4.$invalid" ng-click="form4Next();" >Next</button>
</form>
</div>
</div>
script
------
angular.module("app", [])
.controller("main", ['$scope', function($scope) {
$scope.start = function(){
if((($scope.user.ans1 == "Yes")&&($scope.user.ans2 == "Yes"))||(($scope.user.ans1 == "No")&&($scope.user.ans2 == "Yes"))){
$scope.form1Next();
}
else{
$scope.form2Next();
}
}// startasignment function End
$scope.form1Next = function(){debugger;
$scope.form_1 = true;
$scope.form_2 = true;
}
$scope.form2Next = function(){debugger;
$scope.form_1 = true;
$scope.form_2 = false;
$scope.form_3 = true;
}
$scope.form3Next = function(){debugger;
$scope.form_2 = false;
$scope.form_3 = false;
$scope.form_4 = true;
}
$scope.form4Next = function(){debugger;
alert("successfully submited")
$scope.form_4 = false;
}
}])
.directive('progressbar', [function() {
return {
restrict: 'A',
scope: {
'progress': '=prog'
},
template: '<div class="stripe" style="background-color: #C7D2D2; height:30px; width:100%;"> <div ng-style="style" style="background-color:#FFFF00; height:100%"></div> </div>',
controller: function($scope, $element, $attrs) {
$scope.$watch(function() {
$scope.style = {"width": $scope.progress + "%"}
})
}
}
}]);
if you'r using an angularjs progress bar directive
then you can assign a variable to the prog attribute and manipulate it as you want like
<p progressbar prog="Progress" ></p>
call it like :
<input type="button" value="add 10" ng-click="AddProgress(10)">
and in controller
$scope.Progress ='0';
$scope.AddProgress = function (percentige) {
$scope.Progress = parseInt($scope.Progress)+percentige;
}
now you can put the progressbar in a shared div (without hiding and showing) and maybe animate it ..
first thing i found when searched angularJs progress bar was this cool looking thing
here is a jsFiddle

How to reset Bootstrap Form

Here im using Bootstrap validations with AngularJs when my form is submitted the columns is reset but its shows all validation..But my aim is its should not display validations
Bootstrap
<div class="modal" id="modal1">
<div class="modal-dialog">
<div class="modal-content">
<form name="f1" novalidate ng-submit="Save(Auth.emp)">
<div class="modal-body">
<div class="form-horizontal">
<div class="form-group">
<div class="row">
<div class="col-sm-4">
Email
</div>
<div class="col-sm-8">
<input type="text" name="email" class="form-control" ng-model="Auth.Email" ng-class="Submitted?'ng-dirty':''" required />
<span class="Error" ng-show="(f1.email.$dirty ||Submitted) && f1.email.$error.required">Email REq</span>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-4">
Password
</div>
<div class="col-sm-8">
<input type="text" name="psw" class="form-control" ng-model="Auth.Password" ng-class="Submitted?'ng-dirty':''" required />
<span class="Error" ng-show="(f1.psw.$dirty ||Submitted) && f1.psw.$error.required">Password REq</span>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="submit" value="{{LoginAction}}" />
</div>
</form>
</div>
</div>
</div>
AngularCode.Js
$scope.Save = function (emp) {
if ($scope.LoginAction = "Login") {
$scope.Submitted = true;
if ($scope.isFormValid == true) {
var ss = {
Email: $scope.Auth.Email,
Password: $scope.Auth.Password,
}
var xxer = myServices.GetLogin(ss);
xxer.then(function (msg) {
$scope.msg = msg.data;
$('#modal2').modal('show')
Reset();
})
}
}
}
Reset
function Reset() {
$scope.Email = '';
$scope.Password = '';
}
I think you looking for this:
function Reset() {
$scope.Auth.Email = ''
$scope.Auth.Password = '';
}
You can set a model at the same level as the form tag and make all other inputs sub properties. Then set form model at the root level to an empty object when you click on reset. Here's a codepen.
function exampleController($scope) {
$scope.reset = function() {
$scope.form = {};
};
}
angular
.module('app', [])
.controller('exampleController', exampleController);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<div class="row" ng-app="app" ng-controller="exampleController">
<form novalidate ng-model="form">
<input ng-model="form.email" type="email" />
<input ng-model="form.password" type="password" />
</form>
<button ng-click="reset()">Reset</button>
<pre>{{form}}</pre>
</div>

Radio button event not getting fired second time

I have two radio buttons 1. employee 2 customer when i have to select employee employee id textbox should get open n wen i click on customer it should get disappear. when i am clicking it for first tym its working fine second time its not working .
HTML FILE
<div class="row control-group">
<label >
<input name="cssPre" id="css1" value="geEmp" class="input-xlarge" type="radio" data-ng-model="addUser.Emp" ng-change="ge()">{{::'label.addUser.employee'|translate}}
</label>
<label >
<input name="cssPre" id="css2" value="customer" type="radio" data-ng-model="addUser.customer" ng-change="customer()">{{::'label.addUser.Customer'|translate}}
</label>
Textbox which i wanna show
<div ng-show="ge == true">
<div class="row control-group" ng-show="addUser.geEmp" ng-class="{error:addUserForm.phone.$dirty && !addUserForm.phone.$valid && !addUserForm.phone.$error.pattern, success:addUserForm.phone.$valid}">
<label class="col-xs-4 col-sm-4 col-md-3 col-lg-3 control-label">{{::'label.addUser.SSO'|translate}}</label>
<div class="col-xs-7 col-sm-7 col-md-9 col-lg-9 controls">
<input type="text"
class="input-xlarge"
id="sso"
name="phone"
ng-model="addUser.user.phone"
ng-pattern="ph_numbr"
placeholder="{{::'placeholder.addUser.phone'|translate}}"
ng-change="addUserForm.phone.$setValidity('duplicateName', true);"
required="true"
ng-maxlength=8
ng-minlength=8
ge-auto-focus
/>
<span class="help-block" ng-show="addUserForm.phone.$dirty && addUserForm.phone.$error.required">{{::'error.required'|translate}}</span>
<span class="help-block" ng-show="addUserForm.phone.$dirty && addUserForm.phone.$error.pattern">{{::'error.number'|translate}}</span>
<span class="help-block" ng-show="addUserForm.phone.$dirty && addUserForm.phone.$error.maxlength">{{::'error.max.length'|translate}}</span>
<span class="help-block" ng-show="addUserForm.phone.$dirty && addUserForm.phone.$error.duplicateName">{{::'error.editOrganization.duplicateName'|translate}}</span>
</div>
</div>
JS file
$scope.ge = function() {
$scope.ge = true;
}
$scope.customer = function() {
$scope.ge = false;
}
You have defined variable as well as a function as ge rename either of these one.
You are refining the $scope.ge variable as per your code
$scope.ge = function () {
$scope.ge = true;
}
So change to
$scope.someProperFunctionName = function () {
$scope.ge = true;
}
HTML
<input name="cssPre" id="css1" value="geEmp" class="input-xlarge" type="radio" data-ng-model="addUser.Emp" ng-change="someProperFunctionName ()">

Can't get option value when using Angularjs

I have the following AngularJS code:
angular.module('loggedInApp', ['ui.bootstrap']);
var myapp = angular.module('loggedInApp', ['ui.bootstrap'])
myapp.controller('AddParentController', function ($scope, addParentService) {
var vm = this;
$scope.addParentService = addParentService;
$scope.setName = function (val) {
addParentService.inputParentName = val;
}
$scope.setEmail = function (val) {
addParentService.inputParentEmail = val;
}
$scope.setCarrier = function (val) {
addParentService.inputParentCarrier = val;
}
$scope.setBirthday = function (val) {
addParentService.inputParentBirthday = val;
}
});
myapp.service('addParentService', function () {
var vm = this;
vm.eventObjs = [];
vm.parent = [];
vm.addParent = function () {
alert(vm.inputParentName);
alert(vm.inputParentBirthday);
alert(vm.inputParentEmail);
alert(vm.inputParentCellPhone);
alert(vm.inputParentCarrier);
vm.parent.push({
name: vm.inputParentName, dob: vm.inputParentBirthday,
cell: vm.inputParentCellPhone, carrier: vm.inputParentCarrier,
email: vm.inputParentEmail, active: true, personId: vm.parent.length + 1
});
vm.inputParentName = '';
vm.inputParentDOB = '';
vm.inputParentCellPhone = '';
vm.inputParentCarrier = 0;
vm.inputParentEmail = '';
vm.active = true;
};
vm.buildEventObject = function (titleValue, startValue, personId, choreIdValue) {
vm.eventObjs.push({ title: titleValue, start: startValue, familymemberpersonid: personId, choreId: choreIdValue });
return vm.eventObjs;
}
vm.returnEventObject = function () {
return vm.eventObjs;
}
});
My HTML looks like this:
<div class="row clearfix" ng-controller="AddParentController as parent">
<div class="col-md-6 column">
<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>
<div class="form-group">
<label for="inputParentBirthday">Birthday</label><input class="form-control" id="inputParentBirthday" value="" type="text" ng-model="addParentService.inputParentBirthday" />
</div>
<div class="form-group">
<label for="inputParentCellPhone">Cell Phone</label><input class="form-control" id="inputParentCellPhone" value="" type="text" ng-model="addParentService.inputParentCellPhone" />
</div>
<div class="form-group">
<label for="inputParentCarrier">Phone Carrier</label><br />
<select class="form-control" id="inputParentCarrier">
<option>ATT</option>
<option>Cricket</option>
<option>Sprint</option>
<option>T-Mobile</option>
<option>Verizon</option>
</select>
</div>
<div class="form-group">
<label for="inputParentEmail">E-Mail Address</label><input class="form-control" id="inputParentEmail" value="" type="email" ng-model="addParentService.inputParentEmail" />
</div>
<button class="btn btn-default" type="submit">Submit</button>
</form>
</div>
<br /><br />
<div class="col-md-6 column">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
Parent:
</h3>
</div>
<div class="panel-body">
<table class="table table-striped">
<tr>
<th>Name</th>
<th>Cell #</th>
<th>E-Mail</th>
<th>DOB</th>
</tr>
<tr ng-repeat="parent in addParentService.parent">
<td>{{parent.name}}</td>
<td>{{parent.cell}}</td>
<td>{{parent.email}}</td>
<td>{{parent.dob}}</td>
</tr>
</table>
</div>
<div class="panel-footer">
<button class="btn btn-default" type="submit">Save your Family!</button>
</div>
</div>
</div>
</div>
My issue is when I click the submit button I am calling my service that alerts out all the different values I entered. Everything works except the inputParentCarrier value. When it alerts out it says 'undefined'
Seems like this should be an easy fix, but right now I can't see what is wrong.
You are missing ng-model on your select
<select class="form-control" id="inputParentCarrier" ng-model="addParentService.inputParentCarrier">
<option>ATT</option>
<option>Cricket</option>
<option>Sprint</option>
<option>T-Mobile</option>
<option>Verizon</option>
</select>
You need to add ng-model="addParentService.inputParentCarrier" to your select tag
you need to add model for select element as well, like:
<select ng-model="addParentService.inputParentCarrier" class="form-control" id="inputParentCarrier">
<option>ATT</option>
<option>Cricket</option>
<option>Sprint</option>
<option>T-Mobile</option>
<option>Verizon</option>
</select>
You should bind your ng-model to the select, not the label.
<select class="form-control" id="inputParentCarrier" ng-model="addParentService.inputParentCarrier">
<option>ATT</option>
<option>Cricket</option>
<option>Sprint</option>
<option>T-Mobile</option>
<option>Verizon</option>
</select>
change your select tag to this:
<select class="form-control" id="inputCarrier" ng-model="myService.inputParentCarrier">
<option value="att">ATT</option>
....
<select>

Angularjs Form Validation of a group of input

With Angular I use specific directive for validate single input field. (i.e. email, username etc.)
In this project I have this scenario:
I need to set an Advance Payment field, this Advance must be between min/max value.
To set the Advance I have three input text:
Cash
Old Car Value
Financed Advance
the sum of those three input is my Advance value.
So I need to validate Advance but I have no a single input with ng-model setted on.
What is the best way to check and validate the Advance Payment value?
I need to add a directive to all those three input fields? or is better a directive for the form?
Any suggestion will be appreciated.
jsfiddle example
(function () {
var app = angular.module("myApp", ['ngMessages']);
app.controller('myFormCtrl', function($scope) {
$scope.plan = {};
$scope.plan.advance = 0;
$scope.plan.min_advance = 3000;
$scope.plan.max_advance = 6000;
$scope.updateAdvance = function(){
var advance = 0;
if ($scope.quotationAdvanceType && !isNaN($scope.plan.quotation))
advance += $scope.plan.quotation;
if ($scope.cashAdvanceType && !isNaN($scope.plan.cash))
advance += $scope.plan.cash;
if ($scope.financedAdvanceType && !isNaN($scope.plan.financed))
advance += $scope.plan.financed;
$scope.plan.advance = advance;
}
});
})();
Just to give you (and perhaps others) another option.
To simplify, you can use a number input with its ng-model set to plan.advance. This will allow you to use the min/max attributes. You can set the input to hidden if you prefer not to display it.
<input type="number" name="advance" ng-model="plan.advance" min="{{plan.min_advance}}" max="{{plan.max_advance}}" hidden />
Then you can use the built in validation for min and max such as:
<span ng-messages="myForm.advance.$error" role="alert">
<span ng-message="min">Minimum not reached.</span>
<span ng-message="max">Maximum exceeded.</span>
</span>
Run the code snippet below to see it in action:
(function () {
var app = angular.module("myApp", ['ngMessages']);
app.controller('myFormCtrl', function ($scope) {
var advance = [];
$scope.plan = {};
$scope.plan.advance = 0;
$scope.plan.min_advance = 3000;
$scope.plan.max_advance = 6000;
$scope.reset = function(val) {
$scope.plan[val] = undefined;
$scope.updateAdvance();
};
$scope.updateAdvance = function () {
advance = [$scope.plan.quotation, $scope.plan.cash, $scope.plan.financed];
$scope.plan.advance = advance.reduce(function (a, b) {
a = a ? a : 0;
b = b ? b : 0;
return a + b;
}, 0);
}
});
})();
#import url("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css");
<script src="https://code.angularjs.org/1.3.15/angular.min.js"></script>
<script src="https://code.angularjs.org/1.3.15/angular-messages.min.js"></script>
<div ng-app="myApp" class="container">
<form name="myForm" ng-controller="myFormCtrl" class="form-horizontal">
<div class="form-group" ng-class="{ 'has-error' : myForm.plan.min_advance.$invalid && myForm.plan.min_advance.$touched}">
<label for="plan.min_advance" class="control-label col-xs-4 col-sm-2">Min Advance</label>
<div class="col-xs-8 col-sm-10">
<input type="number" ng-model="plan.min_advance" class="form-control" />
</div>
</div>
<div class="form-group" ng-class="{ 'has-error' : myForm.plan.max_advance.$invalid && myForm.plan.max_advance.$touched}">
<label for="plan.max_advance" class="control-label col-xs-4 col-sm-2">Min Advance</label>
<div class="col-xs-8 col-sm-10">
<input type="number" ng-model="plan.max_advance" class="form-control" />
</div>
</div>
<div class="form-group" ng-class="{ 'has-error' : myForm.surname.$invalid && myForm.surname.$touched}">
<div class="col-xs-12">
<label for="surname" class="control-label">Surname</label>
<input type="text" value="" name="surname" id="surname" ng-model="surname" ng-minlength="3" ng-mAXlength="20" required="required" class="form-control" />
<span ng-messages="myForm.surname.$error" class="help-block" role="alert" ng-show="myForm.surname.$touched">
<span ng-message="required">You forgot to enter your surname</span>
<span ng-message="minlength">Surname is too short</span>
<span ng-message="maxlength">Surname is too long</span>
</span>
</div>
</div>
<p>Set the Advance between minimun <strong>{{plan.min_advance | currency}}</strong> and maximum <strong>{{plan.max_advance | currency}}</strong>
</p>
<div class="form-group">
<label for="quotation" class="col-xs-4 col-sm-2 control-label">
<input type="checkbox" name="quotationAdvanceType" ng-model="quotationAdvanceType" ng-change="reset('quotation')"/> Quotation:
</label>
<div class="col-xs-8 col-sm-10">
<input type="number" name="quotation" ng-value="plan.quotation" ng-model="plan.quotation" ng-change="updateAdvance()" class="form-control" ng-disabled="!quotationAdvanceType" placeholder="{{'max '+ (plan.max_advance-plan.advance)}}" />
</div>
</div>
<div class="form-group">
<label for="cash" class="col-xs-4 col-sm-2 control-label">
<input type="checkbox" name="cashAdvanceType" ng-model="cashAdvanceType" ng-change="reset('cash')" /> Cash:
</label>
<div class="col-xs-8 col-sm-10">
<input type="number" name="cash" ng-value="plan.cash" ng-model="plan.cash" ng-change="updateAdvance()" class="form-control" ng-disabled="!cashAdvanceType" placeholder="{{'max '+ (plan.max_advance-plan.advance)}}" />
</div>
</div>
<div class="form-group">
<label for="financed" class="col-xs-4 col-sm-2 control-label">
<input type="checkbox" name="financedAdvanceType" ng-model="financedAdvanceType" ng-change="reset('financed')" /> Financed:
</label>
<div class="col-xs-8 col-sm-10">
<input type="number" name="financed" ng-value="0" ng-model="plan.financed" ng-change="updateAdvance()" class="form-control" ng-disabled="!financedAdvanceType" placeholder="{{'max '+ (plan.max_advance-plan.advance)}}" />
</div>
</div>
<div ng-class="{'has-error' : myForm.advance.$invalid && (quotationAdvanceType || cashAdvanceType || financedAdvanceType) && (myForm.quotation.$dirty || myForm.cash.$dirty || myForm.financed.$dirty)}">
<input type="number" name="advance" ng-model="plan.advance" min="{{plan.min_advance}}" max="{{plan.max_advance}}" hidden />
<p class="help-block">Total Advance: <strong>{{plan.advance ? (plan.advance | currency) : 'none'}}</strong>
<span ng-messages="myForm.advance.$error" role="alert" ng-show="myForm.quotation.$dirty || myForm.cash.$dirty || myForm.financed.$dirty">
<span ng-message="min">Minimum not reached.</span>
<span ng-message="max">Maximum exceeded.</span>
</span>
</p>
</div>
<button type="submit" class="btn btn-primary" ng-disabled="myForm.$invalid">Send</button>
</form>
</div>
Is there an advantage over your custom directive approach? I would say yes and here's why:
Your directive is tightly coupled to your controller scope, so you can't reuse it elsewhere in your application and it will require you to separately update it if you change one of your scope variables in the future.
You are essentially duplicating code for functionality that already exists in the framework. That results in more upfront cost of development and maintenance effort down the line.
I solve my question with a brand new directive.
I don't know if this is the right way to do that, but it works fine and the behaviour is correct.
app.directive('totalAdvance', function() {
return {
restrict: 'E',
require: '^form',
link: function(scope, element, attrs, formCtrl) {
var advanceValue = 0;
var advanceValidator = function() {
if (advanceValue >= attrs.min && advanceValue <= attrs.max){
formCtrl.$setValidity('minAdvance', true);
formCtrl.$setValidity('maxAdvance', true);
return advanceValue;
}else if (advanceValue < attrs.min) {
formCtrl.$setValidity('minAdvance', false);
formCtrl.$setValidity('maxAdvance', true);
return null;
}else if (advanceValue > attrs.max){
formCtrl.$setValidity('minAdvance', true);
formCtrl.$setValidity('maxAdvance', false);
return null;
}
};
scope.$watch('plan.advance', function(value) {
advanceValue = value;
return advanceValidator();
});
scope.$watch('plan.min_advance', function() {
return advanceValidator();
});
scope.$watch('plan.max_advance', function() {
return advanceValidator();
});
}
};
});
jsfiddle example

Resources