angularjsangularjs-directiveradio-buttonangularjs-ng-value

In Angular, unable to bind to a radio button in a directive on page load


CURRENT SITUATION: I have form fields that are dynamically created via a directive. One of the types includes radio buttons.

GOAL: On page load, I need to bind the values of these elements to a predefined scope. This works correctly with other field types but not with the radio buttons despite the $parent.model matching the option exactly.As you can see in the JSFiddle, "your_name_0" and "description_1" bind correctly but not the radio buttons.

CONSTRAINTS: Due to code restrictions, the directive's ng-model and ng-value cannot change. I know it is possible to bind the model of a radio button to an object. See this for proof: http://plnkr.co/edit/OnHXect37Phij9VAB0ET?p=preview

The Controller:

function MyCtrl($scope) {
    //defines the field types
    $scope.formFields = [
        {
        "fieldName": "Your Name",
        "uniqueId": "your_name_0",
        "fieldType": "text"
        },
        {
        "fieldName": "Description",
        "uniqueId": "description_1",
        "fieldType": "textarea"
        },
        {
         "fieldName": "Favorite Color",
        "uniqueId": "favorite_color_2",
        "fieldType": "radio"
        "fieldTypeOptionsArray":[
            {
                "formFieldId":"favorite_color_2",
                "optionId":"favorite_color_2_0",
                "optionValue":"yellow"

            },
            {
                "formFieldId":"favorite_color_2",
                "optionId":"favorite_color_2_1",
                "optionValue":"blue"

            }
            ] 
        }
    ];

    //values to bind to the model
    $scope.output={
        "your_name_0":"Bob",
        "description_1":"I am a developer",
        "favorite_color_2":
        {
            "optionValue":"yellow",
            "formFieldId":"favorite_color_2",
            "optionId":"favorite_color_2_0"
        }
    };
};

The Directive:

myApp.directive("formField",function($compile){
    var templates = {
        textTemplate:'<div class="form-group"><label for="{{content.uniqueId}}" >{{content.fieldName}}</label><input type="text" ng-model="model" name="{{content.uniqueId}}" class="form-control" id="{{content.uniqueId}}"/> </div><br>',
        textareaTemplate:'<div class="form-group"><label for="{{content.uniqueId}}" >{{content.fieldName}}</label> <textarea ng-model="model" name="{{content.uniqueId}}" id="{{content.uniqueId}}"  class="form-control"></textarea> </div>',
        radioTemplate : '<div class="form-group"><label>{{content.fieldName}}</label><div class=""><div class="radio" ng-repeat="option in content.fieldTypeOptionsArray"><label><input type="radio" name="{{content.uniqueId}}" ng-value="option" id="{{option.optionId}}" ng-model="$parent.model">{{option.optionValue}}</label></div></div></div>',
    };

    var getTemplate = function(content, attrs){
        var template = {};
        template = templates[content.fieldType+"Template"];
        if(typeof template != 'undefined' && template != null) {
                return template;
            }
            else {
                return '';
            }
    };


    var linker = function(scope, element, attrs){        
        element.html(getTemplate(scope.content, attrs)).show();        
        $compile(element.contents())(scope);
    }

    return {
        restrict:"E",        
        replace:true,        
        link:linker,
        scope:{
            content:'=',
            model:'=?'
        }
    };
});

Here is a JSFiddle: http://jsfiddle.net/scheedalla/d2jzmmd7/

I have been stuck for a while and I cannot understand the root of the problem. It has something to do with it being a nested object or because it is within a directive. Any help will be useful and please let me know if you need further clarification! Thanks!!


Solution

  • I found the solution. I added this to my controller. If I mapped the $scope.output[favorite_color_2] to the equivalent value in $scope.formFields it worked. The reason behind this is that the item in the ng-repeat can only be mapped to something within its parent scope. In this case, $scope.formFields.

    angular.forEach($scope.output, function(value,key){        
            for(var f=0;f<$scope.formFields.length;f++){
                if(key == $scope.formFields[f].uniqueId){
                if($scope.formFields[f].fieldType == 'radio'){
                    console.log($scope.formFields[f].fieldTypeOptionsArray.length);
                    for (var z=0;z<$scope.formFields[f].fieldTypeOptionsArray.length;z++){
                        if($scope.formFields[f].fieldTypeOptionsArray[z].optionValue == value.optionValue){
                     $scope.output[key]=$scope.formFields[f].fieldTypeOptionsArray[z];                    
                        }
    
                    }
                }
            }
            }
        });
    

    Updated JSFiddle: http://jsfiddle.net/scheedalla/d2jzmmd7/17/