Dynamic models using ng-if - AngularJS form - angularjs

Here is my code:
As you can see, this will only get displayed if q.answer == 'Fail' - that is the value of a select box further up in the page.
If "Fail" has been selected, then the user can select a defect type which will be saved into question.failure.type.
My question is, if a user selects "Fail" and then selects a defect type - and then changes "Fail" to something else. Then question.failure.type is still retained, even though the ng-if is false now. How can I make it so that question.failure.type is no longer in the model if the ng-if is false?
<div class="panel panel-danger" ng-if="q.answer == 'Fail'">
<div class="panel-heading">
<h3 class="panel-title">Comments</h3>
</div>
<div class="panel-body">
<form novalidate name="failureForm">
<div class="row">
<div class="col-xs-12">
<select name='defect' class='form-control' ng-model='question.failure.type' ng-options='item for item in defectTypes' required>
<option value=''>Select a defect type...</option>
</select>
...
Edit: added new code as requested
<div ng-repeat="q in questions" ng-show="standard.serviceType">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">{{ $index + 1 }}. <span ng-bind="q.questionText"></span></h3>
</div>
<div class="panel-body">
<answer-field question="q"></answer-field>
</div>
</div>
... then the code in the example above appears

Assuming that the value of q.answer is assigned in an <input> element in your HTML, you can clear the value of question.failure.type based on any conditional expression using ng-change.
For example:
<input ng-bind='q.answer'
ng-change='question.failure.type =
(q.answer == 'Fail' ? question.failure.type : undefined)'
>
This is only a trivial example, but it is essentially setting the question.failure.type to either the value it already has or undefined, depending on if q.answer == 'Fail' or not.

Here is the code for your question, assuming some predefined values for your scope variable.
<html ng-app="myNoteApp">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
angular.module('myNoteApp', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.q = {
answer : 'Fail'
};
$scope.defectTypes = ['Item1','Item2','Item3'];
}]);
</script>
<div ng-controller="ExampleController">
<form name="myForm">
<label>Value1:
<input type="checkbox" ng-model="q.answer" ng-true-value="'Pass'" ng-false-value="'Fail'">
</label><br/>
<tt>Checkbox value is {{q.answer}}</tt><br/>
</form>
<div class="panel panel-danger" ng-if="q.answer === 'Fail'">
<div class="panel-heading">
<h3 class="panel-title">Comments</h3>
</div>
<div class="panel-body">
<form novalidate name="failureForm">
<div class="row">
<div class="col-xs-12">
<select name='defect' class='form-control' ng-model='question.failure.type' ng-options='item for item in defectTypes' required>
<option value=''>Select a defect type...</option>
</select>
</div>
</div>
</form>
</div>
</div>
</div>
</html>

you should put in your controller
$scope.$watch('q.answer', function(newVal, oldVal){
if(newVal!='Fail') question.failure.type.length = 0;
})
or, put into ng-change method
<input type="text" ng-model="q.answer" ng-change="changing()"/>
in controller
$scope.chaging = function(){
if($scope.q.answer!='Fail') question.failure.type.length = 0;
}

Related

Common ng-model value in ng-repeat

I am listing div using ng-repeat to in following manner and include form-template which is assigned. I have several form-template and want to include in following manner. They can have nested ng-repeat to include same template. So i am using "trackerWidgetData" variable in my template. its working fine but inner ng-repeat have different variable(dependWidgetData).
How to use common model value for form-template. If we are including it in nested ng-repeat.
<div class="listview-trckr-new clearfix" ng-repeat="trackerWidgetData in optionsList.inlineTemplates | filter:options.trackerSearchClient track by $index">
<div class="listview-trckr-new-top">
<div class="listview-trckr-new-left clearfix">
<h3>{{trackerWidgetData.trackerName}}</h3>
</div>
<div class="listview-trckr-new-right">
<div ng-if="trackerWidgetData.template" ng-include src="'/public/views/tracker-templates/'+trackerWidgetData.template"></div>
</div>
</div>
<div class="listview-trckr-new-btm" ng-if="trackerWidgetData.dependendTrackers && trackerWidgetData.dependendTrackers.length">
<div class="listview-trckr-new-top" ng-repeat="dependWidgetData in trackerWidgetData.dependendTrackers">
<div class="listview-trckr-new-left clearfix">
<h3>{{dependWidgetData.trackerName}}</h3>
</div>
<div class="listview-trckr-new-right">
<div ng-if="dependWidgetData.template" ng-include src="'/public/views/tracker-templates/'+dependWidgetData.template"></div>
</div>
</div>
</div>
</div>
I have many different type template like this.
<script type="text/ng-template" id="addManualContent.tpl">
<ng-form name="stepAddForm" novalidate >
<div class="new-weight-tracker">
<div class="weight-auto-fil-input">
<input type="text" name="value" ng-model="form[trackerWidgetData.uniqueFormId].trackerValue.values[0].value" />
<div class="new-trkr-select">
<select class="weight-selectbox" name="foodUnit" ng-model="form[trackerWidgetData.uniqueFormId].trackerValue.values[0].unitId" ng-options="opt.id as opt.unitName for opt in trackerWidgetData.unitType.units">
</select>
</div>
</div>
<div class="new-tracker-cale">
<adm-dtp ng-model='form[trackerWidgetData.uniqueFormId].trackerValue.dateTime' maxdate="{{optionsList.maxTimeStamp}}" options='{format: toUpperString(dateFormat) + "hh:mm", default: todayTimestamp, freezeInput:false}'>
<input name="date" ng-model="form[trackerWidgetData.uniqueFormId].trackerValue.dateTime" ng-click="initDTP(form[trackerWidgetData.uniqueFormId].trackerValue.dateTime)" type="text" ng-required="true" dtp-input>
<i aria-hidden="true" class="fa fa-calendar" ng-click="initDTP(form[trackerWidgetData.uniqueFormId].trackerValue.dateTime)" dtp-toggle></i>
</adm-dtp>
</div>
<div class="new-logit-btn">
<a ng-href="" ng-class="{'disable-anchor-btn': optionsList.inAddProcess}" ng-click="optionsList.inAddProcess ? null : addTrackerValue(stepAddForm, trackerWidgetData)" class="fill_button">Log It</a>
</div>
</div>
</ng-form>
</script>
The Question is How to pass model value to ng-template when including it?

ngif markup error while displaying ngMessages error in angularjs

i am using ngMessages to validate a form , which is dynamically generated using ngRepeat.ngMessages is working fine but i want to display validation error messages only submit button is clicked.I am using ng-if for checking
submit button clicked and current form field is invalid . but i am getting angular compiler error , i think it is something to do with constructing the control name dynamically.
can any one suggest what is wrong with following markup.
<div ng-repeat="item in Data" class="container-fluid">
<ng-form name="fm">
<div class="row">
<div class="col-md-10">
<h2>{{ item.headerName}}</h2>
</div>
</div>
<div class="row" ng-repeat="it in item.items">
<div class="col-md-8">
<div class="form-group">
<label for="''{{ it.name}}''" class="col-xs-4 control-label"> {{ it.name}}</label>
<div class="col-xs-2">
<select name='{{"yOrNo" + $parent.$index + $index}}'
id='{{"yOrNo" + $parent.$index + $index}}'
class="form-control"
data-ng-disabled="false"
ng-model="it.yesorNo"
ng-options="yno.id as yno.value for yno in lookups.yno"
ng-required="true"></select>
<div class="messages" ng-messages="fm.yOrNo{{$parent.$index}}{{$index}}.$error" ng-if="fm.yOrNo{{$parent.$index}}{{$index}}.$error && submitClicked" >
<div class="error-message" ng-message="required">* required.</div>
</div>
</div>
</div>
</div>
</div>
</ng-form>
</div>
Your ng-form needs a unique name per iteration, so instead of:
<ng-form name="fm"> try something like:
<ng-form name="fm{{$index}}">
note that all references to that name=fm{{$index}} will now needs to be adjusted accordingly, E.G: this: fm.yOrNo{{$parent.$index}}{{$index}}.$error will need to become this: fm{{$parent.$index}}.yOrNo{{$parent.$index}}{{$index}}.$error

Cannot read property '$valid' of undefined

I have a form with a name field and two validations - required and max-length.
When I enter correct value, the form in controller is showing valid and returning true. But on entering wrong data, $valid is not throwing false and simply says -
Cannot read property '$valid' of undefined
Why is the form getting undefined in this case?
Jsfiddle here
Thanks in advance
Add ng-submit attribute to the form:
<form name="myForm" ng-submit="SaveAndNext()" novalidate>
Change controller to:
function myCtrl($scope, $log){
$scope.data = {};
$scope.SaveAndNext = function(){
if($scope.myForm.$valid){
$log.info('Form is valid');
$log.info($scope.data);
} else {
$log.error('Form is not valid');
}
}
}
Remove ng-click event handler from your submit button
Updated fiddle: http://jsfiddle.net/9cgopo7d/1/
I included the $log service because it's a useful default service and you might not know about it.
See demo below pass your form to controller with the submit click
ng-click="SaveAndNext(myForm)"
and now you can easy access all your form properties
function myCtrl($scope) {
$scope.SaveAndNext = function(form) {
console.log(form);
if (form.$valid) {
alert(form.$valid);
} else {
alert("!" + form.$valid)
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="registrationdetails" ng-app="" ng-controller="myCtrl">
<form name="myForm" novalidate>
<div class="list">
<div class="item list-item">
<div class="row row-center">
<div class="col-50"> <span class="form-field-name">Name</span>
</div>
<div class="col-50">
<textarea type="text" rows="5" ng-model="data.Name" name="Name" ng-maxlength=45 required></textarea> <span ng-show="myForm.Name.$dirty && myForm.Name.$invalid">
<span class="form-error" ng-show="myForm.Name.$error.required">Name is required</span>
<span class="form-error" ng-show="myForm.Name.$error.maxlength">Name should be max 45 characters</span>
</span>
</div>
</div>
</div>
<div class="item list-item">
<div class="row row-center">
<div class="col-50"> <span class="form-field-name">Type</span>
</div>
<div class="col-50">
<select ng-class="{defaultoption: !data.Type}" ng-model="data.Type" name="Type" required>
<option value="" disabled selected class="defaultoption">Type</option>
<option value="1" class="actualoption">Type 1</option>
<option value="2" class="actualoption">Type 2</option>
</select>
<span ng-show="myForm.Type.$dirty && myForm.Type.$invalid">
<span class="form-error" ng-show="myForm.Type.$error.required">Type is required</span>
</span>
</div>
</div>
</div>
<div class="item list-item">
<div class="row">
<div class="col">
<input type="submit" class="button" ng-click="SaveAndNext(myForm)" value="Next">
</div>
</div>
</div>
</div>
</form>
</div>
Place $scope.data={}; at the top of controller:-)
This is happening becuase you are directly submit the form which doesn't yet initialized the data object and therefore name data.Name is not recognized.
And if you place $scope.data={} in that case we have empty data object initialized.So in second case we have atleast reference of empty object whereas in first case it doesn't have any reference.
Fiddle
HTML:
<form name="form" id='form' novalidate>
<input type="text"required name="Title" ng-model="Title">
<div ng-messages="form.Title.$error">
<div ng-message="required">Field Required</div>
</div>
</form>
JS:
$scope.save= function(){
if (!scope.createMessage.$valid) {
scope.form.$submitted = true;
return;
}
The format for using $valid should be like this. If you don't get again then visit the official site of AngularJs.
I had similar problem, but in my case I was a ng-if creating a child scope that did not have the form defined.
Just changed the ng-if to ng-show and the form stop be undefined.

Show/Hide divs depend on dropdown select in AngularJS

I am trying to show a div depending on what is selected from the drop down list. For example, if a user selects 'Cash' from the list show Cash div or if the user select 'Check' from the list show Check div
I have put together sample but its incomplete and needs to wire-up
http://jsfiddle.net/abuhamzah/nq1eyj1v/
Also when the user change the selection I would also like to clear the previous selection so when the user goes back to the previous selection they should not see.
<div ng-controller="MyCtrl">
<div class="col-xs-12">
<label class="col-xs-6 control-label">Type:</label>
<div class="col-xs-6">
<select name="type" ng-model="payment.type" ng-dropdown required ng-change="changeme()" >
<option ng-option value="Cash">Cash</option>
<option ng-option value="Check">Check</option>
<option ng-option value="Money Order">Money Order</option>
</select>
</div>
</div>
<div class="col-xs-12" id="cash">
<div >
<label class="col-xs-6 control-label">Cash :</label>
<div class="col-xs-6">
<input type="number" class="form-control" ng-model="payment.cash" />
</div>
</div>
</div>
<div class="col-xs-12" id="check">
<div >
<label class="col-xs-6 control-label">check :</label>
<div class="col-xs-6">
<input type="number" class="form-control" ng-model="payment.check" />
</div>
</div>
</div>
<div class="col-xs-12" id="money_order">
<div >
<label class="col-xs-6 control-label">money_order :</label>
<div class="col-xs-6">
<input type="number" class="form-control" ng-model="payment.money_order" />
</div>
</div>
</div>
</div>
//controller:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.changeme = function() {
alert('here');
}
}
you didnt initialize as the angular app coz u missed the ng-app directive first
and this is the solution using ng-if
DEMO
<div ng-app="myApp" ng-controller="MyCtrl"> // initialize as a angular app
<div class="col-xs-12" id="cash" ng-if="payment.type == 'Cash'"> // this div will show if the value of `payment.type` model equals to `cash`. and so on.

Clear the previous input once the selection is selected

How would I clear the input box once the user select from dropdown using angularjs.
every time clear the input box once the selection is made.
here is what I put together the sample:
http://jsfiddle.net/abuhamzah/jb1j3w7x/
<div ng-app="myApp" ng-controller="MyCtrl">
<div class="col-xs-12">
<label class="col-xs-6 control-label">Type:</label>
<div class="col-xs-6">
<select name="type" ng-model="payment.type" ng-dropdown required ng-change="changeme(payment.type)" >
<option ng-option value="Cash">Cash</option>
<option ng-option value="Check">Check</option>
<option ng-option value="Money Order">Money Order</option>
</select>
</div>
</div>
{{ payment.cash }}
<div class="col-xs-12" id="cash" ng-if="payment.type == 'Cash'">
<div >
<label class="col-xs-6 control-label">Cash :</label>
<div class="col-xs-6">
</div>
</div>
</div>
<div class="col-xs-12" id="check" ng-if="payment.type == 'Check'">
<div >
<label class="col-xs-6 control-label">check :</label>
<div class="col-xs-6">
</div>
</div>
</div>
<div class="col-xs-12" id="money_order" ng-if="payment.type == 'Money Order'">
<div >
<label class="col-xs-6 control-label">money_order :</label>
<div class="col-xs-6">
</div>
</div>
</div>
<div class="col-xs-12" ng-if="payment.type == 'Check' || payment.type == 'Money Order' || payment.type == 'Cash'">
<div >
<div class="col-xs-6"><input type="number" class="form-control" ng-model="payment_input"/>{{payment.type}}</div>
</div>
</div>
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.changeme = function() {
alert(payment.type);
payment_input='';
}
}
You can do this more easily with $watch, which is designed for this purpose.
In your controller:
$scope.$watch('payment.type', function (newVal, oldVal) {
$scope.payment_input = 0;
// anything else you want to do when the payment type is changed
})
Now whenever payment.type is changed, these lines will be executed.
Here are more docs: https://docs.angularjs.org/api/ng/type/$rootScope.Scope
EDIT
Here is a working fiddle with your code: http://jsfiddle.net/jb1j3w7x/5/
You need to use ng-show instead of ng-if for input element container because the following reason
The ngIf directive removes or recreates a portion of the DOM tree
based on an {expression}. If the expression assigned to ngIf evaluates
to a false value then the element is removed from the DOM, otherwise a
clone of the element is reinserted into the DOM.
Approach 1: (using controller)
Working demo: http://jsfiddle.net/jb1j3w7x/2/
Approach 2: (you can update the model without controller)
Working demo: http://jsfiddle.net/jb1j3w7x/4/
Also,
You have missed to add $scope for updating the number field
Number field should be updated as number. we cant update as empty
text

Resources