Вопрос

I have two Angular directives, one nested inside the other as shown below.

HTML

<gss-response-group response-group-id="43" response-group-title="'Group Title'">
  <gss-response-option option-id="5" option-text="'Very Often'" option-value="5.00" options-inline="true" type="'radio'"></gss-response-option>
  <gss-response-option option-id="6" option-text="'Often'" option-value="4.00" options-inline="true" type="'radio'"></gss-response-option>
  <gss-response-option option-id="7" option-text="'Sometimes'" option-value="3.00" options-inline="true" type="'radio'"></gss-response-option>
  <gss-response-option option-id="8" option-text="'Rarely'" option-value="2.00" options-inline="true" type="'radio'"></gss-response-option>
  <gss-response-option option-id="9" option-text="'Never'" option-value="1.00" options-inline="true" type="'radio'"></gss-response-option>
</gss-response-group>

responseGroup.template.html

  <div class="gss-response-group">
    <label class="gss-response-group-title" ng-if="responseGroupTitle != null">{{responseGroupTitle}}</label>
    <placeholder></placeholder>
  </div>

responseOption.template.html

<div ng-class="{'gss-response-option': optionsInline}">
  <input class="gss-{{type}}-option" id="{{id}}" name="{{groupName}}" type="{{type}}" value="{{optionValue}}" />
  <label class="gss-option-text" for="{{id}}">{{optionText}}</label>
  <div class="gss-specifyanswer" ng-if="specify">
    <label class="gss-specifyanswer" ng-if="specifyText != null">{{specifyText}}</label>
    <textarea class="gss-specifyanswer" maxlength="5000" disabled></textarea>
  </div>
</div>

JavaScript

'use strict';

angular.module( 'gssApp', [ 'gss.directives' ] );

angular.module( 'gssApp' )

.controller( 'gssAppController', [

    '$scope',
    '$http',
    '$rootScope',

    function ( $scope, $http, $rootScope )
    {

    }] );

var directiveModule = angular.module( 'gss.directives', [] );

directiveModule.directive( 'gssResponseGroup', function ()
{
  return {
    restrict: 'E',
    transclude: true,
    replace: true,
    scope: {
      responseGroupTitle: '=',
      responseGroupId: '='
    },
    templateUrl: 'responseGroup.template.html',
    link: function ( scope, element, attrs, ctrl, transclude )
    {
      element.find( 'placeholder' ).replaceWith( transclude() );
    },
    controller: [

        '$scope',
        '$rootScope',
        '$element',
        '$attrs',

    function ( $scope, $rootScope, $element, $attrs )
    {

    }]
  };
} );

directiveModule.directive( 'gssResponseOption', function ()
{
  return {
    restrict: 'E',    
    transclude: true,
    replace: true,
    scope: {
      responseGroupId: '=',
      optionId: '=',
      optionText: '=',
      optionValue: '=',
      type: '=',
      optionsInline: '=',
      specify: '=',
      specifyText: '='      
    },
    templateUrl: 'responseOption.template.html',
    controller: [

        '$scope',
        '$rootScope',
        '$element',
        '$attrs',

    function ( $scope, $rootScope, $element, $attrs )
    {
      // HOW DO I GET THE PARENT DIRECTIVE'S SCOPE TO USE THE
      // responseGroupId FROM IT?
      $scope.id = 'rgID' + '_' + $scope.responseGroupId + '_' + $scope.optionId;
      $scope.groupName = 'rg' + '_' + $scope.responseGroupId;
    }]
  };
} );

I want the child directive to have access to the "response-group-id" field in the parent. How do I do this? I was able to get the value by having the parent directive be required by the child directive and then getting it within the "link" method of the child directive but by then it was too late to be applied to the child template.

Code in Plunker.

Also, if anyone could tell me why the CSS isn't being applied within my Plunker project, I'd appreciate it (though not a big deal).

Это было полезно?

Решение

To share data between directives, it is recommended to define the shared data on the controller of the parent directive, and access it from the link function of the child directive (see last example "Creating Directives that Communicate" in angular Developer Guide).

So your parent directive's controller would look like:

function ( $scope, $rootScope, $element, $attrs )
{
  this.id = $scope.responseGroupId;
}]

And your child directive would look like:

directiveModule.directive( 'gssResponseOption', function ()
{
  return {
  ...
  require: '^gssResponseGroup',
  link: function(scope, element, attrs, gssResponseGroupCtrl) {
    scope.id = 'rgID' + '_' + gssResponseGroupCtrl.id + '_' + scope.optionId;
    scope.groupName = 'rg' + '_' + gssResponseGroupCtrl.id;
  }

Note that this solution will break if the responseGroupId is interpolated. If the value changes, it will not be reflected in the controller id property since it is only set once. Instead of the id property, the controller would have to define a getter method that always checks the latest value of $scope.responseGroupId.

Другие советы

Though I think you're making things a lot harder than they need to be, here's a solution:

<gss-response-group response-group-id="43">
  <gss-response-option response-group-id="responseGroupId"></gss-response-option>
</gss-response-group>

Then in your responseGroupOption directive:

return {
  // Other Logic...
  scope: {
    responseGroupId: '='
  }
};
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top