iowatiger08
iowatiger08

Reputation: 1962

AngularJS 1.x not showing radio as checked

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}}" />
         &nbsp; &nbsp; &nbsp; &nbsp;
        <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>

Looks like this when Phone is selected:

enter image description here

and like this when email is selected:

enter image description here

I added this method to the Main controller:

$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

Answers (3)

iowatiger08
iowatiger08

Reputation: 1962

Couple things were in play here

  1. 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>
              &nbsp; &nbsp; &nbsp; &nbsp;
              <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>
    
  2. 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

georgeawg
georgeawg

Reputation: 48968

Avoid using $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

nash11
nash11

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

Related Questions