2013-04-02 4 views
9

키/값 쌍을 표시하는 아주 간단한 지시문을 만들었습니다. 변환 된 내용이 비어 있다면 (길이가 0이거나 공백 만있는 경우) 요소를 자동으로 숨길 수 있어야합니다.변환 된 내용이 비어 있다면 요소를 숨기는 방법은 무엇입니까?

지시어 내에서 중첩 된 콘텐츠에 액세스하는 방법을 알 수 없습니다.

app.directive('pair', function($compile) { 
    return { 
    replace: true, 
    restrict: 'E', 
    scope: { 
     label: '@' 
    }, 
    transclude: true, 
    template: "<div><span>{{label}}</span><span ng-transclude></span></div>" 
    } 
}); 

예를 들어, 다음 요소를 표시하고 싶습니다.

<pair label="My Label">Hi there</pair> 

그러나 다음 두 요소는 텍스트 콘텐츠가 포함되어 있지 않아 숨겨져 있어야합니다. 좋은 방법은 상자 밖으로 이런 종류의 처리가 될 수 있도록

<pair label="My Label"></pair> 
<pair label="My Label"><i></i></pair> 

나는 각도에 새로운 오전. 어떤 도움을 주셔서 감사합니다.

답변

8

템플릿에 ng-show을 사용하고 transluluded html에 텍스트 길이가 있는지 확인하는 방법은 compile transcludeFn입니다.

더 텍스트 길이 ng-show은 내가 controllerAs를 사용하여, 다음과 같이 그것을했다

app.directive('pair', function($timeout) { 
    return { 
    replace: true, 
    restrict: 'E', 
    scope: { 
     label: '@' 
    }, 
    transclude: true, 
    template: "<div ng-show='1'><span>{{label}} </span><span ng-transclude></span></div>", 
    compile: function(elem, attrs, transcludeFn) { 
      transcludeFn(elem, function(clone) { 
       /* clone is element containing html that will be transcludded*/ 
       var show=clone.text().length?'1':'0' 
       attrs.ngShow=show; 
      }); 
     } 
    } 
}); 

Plunker demo

+1

난해한 transcludeFn :)에 대한 유스 케이스를 보여주는 모든 대답에 +1. –

+1

은 clludeFn에서'clone.text(). trim(). length'가 조금 더 정확합니다. – alalonde

+0

+1 덕분에 방금 많은 시간을 절약 할 수있었습니다. – cgTag

0

나는 transclude에 익숙하지 않으므로 도움이되는지 확실하지 않습니다.

그러나 지시어 코드에서 빈 내용을 확인하는 한 가지 방법은 iElement.text() 또는 iElement.context 객체를 사용하여 숨기는 것입니다.

+0

감사합니다. 나는 실제로'link' 함수 내에서 그렇게하려고 시도했지만, 그 내용은 그 시점까지는 아직 옮겨지지 않았다. – jessegavin

0

를 숨기도록 설정되어 있지 않은 경우.

/* 지시어 내부 */

  controllerAs: "my", 
controller: function ($scope, $element, $attrs, $transclude) { 
//whatever controller does 
}, 
     compile: function(elem, attrs, transcludeFn) { 
        var self = this; 
        transcludeFn(elem, function(clone) { 
         /* clone is element containing html that will be transcluded*/ 
         var showTransclude = clone.text().trim().length ? true : false; 
         /* I set a property on my controller's prototype indicating whether or not to show the div that is ng-transclude in my template */ 
         self.controller.prototype.showTransclude = showTransclude; 
        }); 
       } 

/* 템플릿 내부 */

<div ng-if="my.showTransclude" ng-transclude class="tilegroup-header-trans"></div> 
1

이전에 제공된 답변 도움이되었다하지만 완벽하게 내 상황을 해결하지 않았다, 그래서 나는 함께했다 별도의 지시어를 작성하여 다른 해결책.

모든 요소의 하위 노드에 텍스트가 있는지 단순히 확인하는 속성 기반 지시문 (예 : restrict: 'A')을 만듭니다.

function hideEmpty() { 
    return { 
     restrict: 'A', 
     link: function (scope, element, attr) { 
      let hasText = false; 

      // Only checks 1 level deep; can be optimized 
      element.children().forEach((child) => { 
       hasText = hasText || !!child.text().trim().length; 
      }); 

      if (!hasText) { 
       element.attr('style', 'display: none;'); 
      } 
     } 
    }; 
} 

angular 
    .module('directives.hideEmpty', []) 
    .directive('hideEmpty', hideEmpty); 

만 주요 요소를 확인하려면

:

link: function (scope, element, attr) { 
    if (!element.text().trim().length) { 
     element.attr('style', 'display: none;'); 
    } 
} 

내 문제를 해결하기를, 내가 필요한 모든 자식 노드가이 있다면 확인하는 것이 었습니다 :

link: function (scope, element, attr) { 
    if (!element.children().length) { 
     element.attr('style', 'display: none;'); 
    } 
} 

YMMV

1

매번 ng-show를 사용하지 않으려는 경우 자동으로 수행하라는 지시문을 만들 수 있습니다.

.directive('hideEmpty', ['$timeout', function($timeout) { 

    return { 
     restrict: 'A', 

     link: { 
      post: function (scope, elem, attrs) { 
       $timeout(function() { 
        if (!elem.html().trim().length) { 
         elem.hide(); 
        } 
       }); 
      } 
     } 
    }; 

}]); 

그런 다음 모든 요소에 적용 할 수 있습니다. 귀하의 경우에는 :

<span hide-empty>{{label}}</span> 
2

조금 늦을 지 모르지만 CSS Pseudo class : empty를 사용하는 것도 좋습니다. 그래서이 작동합니다 (IE9 +)

.trancluded-item:empty { 
    display: none; 
} 

요소는 여전히 DOM에 등록되지만 비어 보이지 않는 것입니다.