2013-04-02 58 views
9

我創建了一個非常簡單的指令,顯示一個鍵/值對。我希望能夠自動隱藏元素,如果transcluded內容是空的(零長度或只是空白)。如果包含的內容爲空,如何隱藏元素?

我不知道如何訪問從指令中獲取的內容。

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> 

我是Angular的新手,所以可能有很好的方法來處理這種開箱即用的事情。任何幫助表示讚賞。

回答

8

以下是在模板上使用ng-show並在compile transcludeFn內檢查包括的HTML是否具有文本長度的方法。

如果沒有文本長度ng-show設置爲隱藏

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

在transcludeFn,'clone.text()。trim()。length'會更精確一點點 – alalonde

+0

+1謝謝,這只是爲我節省了很多時間。 – cgTag

0

我對transclude並不熟悉,所以不確定它是否有幫助。

但是,檢查指令代碼內部空白內容的一種方法是使用iElement.text()或iElement.context對象,然後隱藏它。

+0

謝謝。我實際上試過在'link'函數中做這件事,但內容還沒有被這個點所包含。 – jessegavin

0

我做到了這樣,使用controllerAs。

/*內部指令*/

  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;'); 
    } 
} 

因人而異

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僞類:空。 所以,這將工作(IE9 +)

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

元素仍然會在DOM被註冊,但會是空的和無形的。