Reputation: 1962
I am updating a form to have two sets of radio buttons that turns on or off panels. The first says "Yes" to contact the customer or "No". If we are to contact, then present choice of which method is used, phone or email. (Previously there was just the question to contact or not.)
While I can get the show function to work properly, I do not understand why I cannot get the radio button to show as selected. (It could be that I am fairly green to AngularJS.)
<div class="radio styled-radio" id="callTheCustomerDiv">
<input class="form-control" id="callTheCustomerRadio1"
name="callTheCustomer" type="radio" value="Yes"
ng-required="issueType=='IncidentDiv'"
ng-model="$parent.callTheCustomer"
ng-click="contactSelection('none')"/>
<label for="callTheCustomerRadio1"> Yes</label> - Please indicate how the customer wants to be contacted.<br/>
<div class="form-group" id="howToContactDiv" ng-show=state class="row fullWidth">
<div id="contactOptions" class="form-group">
<label for="phoneRadio">Phone</label>
<!-- radio indicator is not working correctly -->
<input id="phoneRadio" class="form-control" type="radio"
ng-click="contactSelection('phone')"
name="phoneSelect" ng-model="$parent.phoneSelect"
value="{{$parent.phoneSelect}}" />
<label for="emailRadio">Email</label>
<input id="emailRadio" class="form-control" type="radio"
ng-click="contactSelection('email')" name="emailSelect"
ng-model="$parent.emailSelect"
value="{{$parent.emailSelect}}" />
<br/> <!-- phoneSelect : {{phoneSelect}} -->
</div>
<div id="phoneContact" ng-show="contactType=='phone'">
<span>Phone
<input class="form-control input-sm" type="text"
name="callTheCustomerPhone"
id="callTheCustomerPhone"
ng-model="$parent.callTheCustomerPhone"
ng-required="$parent.contactType=='phone' && accForm.phoneNumber.$viewValue === ''"
maxlength="20"/>
</span>
</div>
<br/>
<div id="emailContact" ng-show="contactType=='email'">
<span>Email
<input class="form-control input-sm" type="text"
name="emailTheCustomer" id="emailTheCustomer"
ng-model="$parent.emailTheCustomer"
ng-required="$parent.contactType=='email' && accForm.emailTheCustomer.$viewValue === ''"
maxlength="150"/></span>
</div>
</div>
<input class="form-control" id="callTheCustomerRadio2"
name="callTheCustomer" type="radio" value="No"
ng-required="issueType=='IncidentDiv'"
ng-model="$parent.callTheCustomer"
ng-click="contactSelection('no')"/>
<label for="callTheCustomerRadio2">No</label>
</div>
$scope.contactSelection = (function (contact) {
if (contact=='none'
||contact=='email'
||contact=='phone'){
$scope.state = true;
$scope.contactType = contact;
if (contact=='phone'){$scope.phoneSelect = true;$scope.emailSelect = false;}
if (contact=='email'){$scope.emailSelect = true;$scope.phoneSelect = false;}
}else{
$scope.state = false;
$scope.contactType = 'no';
$scope.emailTheCustomer = '';
$scope.callTheCustomerPhone = '';
$scope.phoneSelect = false;
$scope.emailSelect = false;
}
});
Upvotes: 1
Views: 102
Reputation: 1962
Couple things were in play here
I had to change the label-input tag order.
<div class="radio styled-radio" id="callTheCustomerDiv">
<input class="form-control" id="callTheCustomerRadio1" name="callTheCustomer" type="radio" value="Yes"
ng-required="issueType=='IncidentDiv'"
ng-model="callTheCustomer"
ng-click="contactSelection(null)" />
<label for="callTheCustomerRadio1"> Yes</label> - Please indicate how the customer wants to be contacted.<br/>
<div class="form-group" id="howToContactDiv"
ng-if="customerContact.contactOptionShow" class="row fullWidth">
<div id="contactOptionsDiv" >
<div id="contactOptionsSelectDiv" >
<input class="form-control" id="phoneRadio" type="radio" name="contactSelection"
ng-model="customerContact.contactSelection" value="phone" />
<label for="phoneRadio">Phone</label>
<input class="form-control" id="emailRadio" type="radio" name="contactSelection"
ng-model="customerContact.contactSelection" value="email" />
<label for="emailRadio">Email</label>
<br/>
</div>
<div id="phoneContactDiv" ng-show="customerContact.contactSelection=='phone'">
<span>Phone
<input class="form-control input-sm" type="text" name="callTheCustomerPhone" id="callTheCustomerPhone"
ng-model="callTheCustomerPhone"
ng-required="customerContact.contactSelection=='phone' && accForm.phoneNumber.$viewValue === ''"
maxlength="20"/></span>
</div>
<br/>
<div id="emailContactDiv" ng-show="customerContact.contactSelection=='email'">
<span>Email
<input class="form-control input-sm" type="text" name="emailTheCustomer" id="emailTheCustomer"
ng-model="emailTheCustomer"
ng-required="customerContact.contactSelection=='email' && accForm.emailTheCustomer.$viewValue === ''" maxlength="150"/></span>
</div>
</div>
</div>
<input class="form-control" id="callTheCustomerRadio2" name="callTheCustomer" type="radio" value="No"
ng-required="issueType=='IncidentDiv'" ng-model="callTheCustomer"
ng-click="contactSelection('clear')" />
<label for="callTheCustomerRadio2">No</label>
</div>
I completely removed the $parent references and simplified the function by using the properties of the variable.
modified the mainController method and variable to look like:
$scope.customerContact ={
contactOptionShow : false,
contactSelection : null
};
$scope.contactSelection = (function (contact) {
if (contact != null
&& contact=='clear' ){
$scope.customerContact.contactOptionShow = false;
$scope.customerContact.contactSelection = '';
$scope.emailTheCustomer = '';
$scope.callTheCustomerPhone = '';
}else{
$scope.customerContact.contactOptionShow = true;
}
});
I think it reads better now as well.
Upvotes: 0
Reputation: 48968
$parent
Using $parent
is problematic. If the template nests more than one directive which instantiates a child scope, the two-way binding will have a data hiding problem. It is better to bind ng-models to a property of an object in the controller scope.
If $parent
binds the ng-model
to $rootScope
, the controller $scope will not be able to set the model value.
The model value is getting set, just the display does not change.
The model is getting set because the ng-click
handler is setting it manually. If the binding is correct, the ng-model
controller should set it automatically and there would be no need to set it manually. The ngModelController
needs the proper binding to render to the HTML.
Avoid using $parent
. Define objects in the $scope for your controller, then reference a property of that object. See Nuances of scope inheritance in AngularJS.
The below example binds correctly even though the ng-if
directive adds a child scope:
angular.module("app",[])
.controller("ctrl",function($scope) {
$scope.fd1={
sel1: null,
yes1: false
};
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="ctrl">
<form name="form1">
<input ng-model="fd1.yes1" type="checkbox" />
OK to Contact?<br>
<div ng-if="fd1.yes1">
<input ng-model="fd1.sel1" type="radio" name="sel1" value="email" />
email
<input ng-model="fd1.sel1" type="radio" name="sel1" value="phone" />
phone
<br>{{fd1.sel1}}
<div ng-show="fd1.sel1">
<input ng-model="fd1.info1">
<br>
<button ng-click="fd1.sel1=null">Reset choice</button>
</div>
</div>
</form>
</body>
Upvotes: 1
Reputation: 8650
Radio buttons normally come in groups and the name
attribute is used to group them.
There are two radio groups in your code, the Yes/No and Phone/Email.
The Yes/No radio buttons have the same name callTheCustomer
while the Phone/Email radio buttons have different names. Change the name
attributes for the phone and email radio buttons to something more meaningful to that group like phoneOrEmail
.
Upvotes: 2