2013-04-02 13 views
9

Stworzyłem bardzo prostą dyrektywę, która wyświetla parę klucz/wartość. Chciałbym móc automatycznie ukryć element, jeśli treść zawarta w transkluzji jest pusta (zero lub tylko biały znak).Jak ukryć element, jeśli zawarta w translatach zawartość jest pusta?

Nie mogę dowiedzieć się, jak uzyskać dostęp do treści, które są zawarte w dyrektywie.

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

Na przykład chciałbym wyświetlić następujący element.

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

Ale kolejne dwa elementy powinny zostać ukryte, ponieważ nie zawierają żadnej treści tekstowej.

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

Jestem nowy w Angular, więc może być świetny sposób poradzić sobie z tego rodzaju rzeczy po wyjęciu z pudełka. Każda pomoc jest doceniana.

Odpowiedz

8

Oto podejście polegające na użyciu szablonu na ng-show oraz w ramach compile transcludeFn sprawdzania, czy przetłumaczony html ma długość tekstu.

Jeśli nie długość tekstu ng-show jest ustawiony do ukrycia

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

+1 dla każdej odpowiedzi, która pokazuje przypadek użycia dla ezoterycznego transcludeFn :). –

+1

w transcludeFn, 'clone.text(). Trim(). Length' byłby nieco dokładniejszy – alalonde

+0

+1 dzięki, to właśnie zaoszczędziło mi dużo czasu. – cgTag

0

Nie jestem strasznie zaznajomiony z transclude, więc nie jestem pewien, czy to pomaga, czy nie.

ale jednym ze sposobów sprawdzenia pustej zawartości w kodzie dyrektywy jest użycie obiektu iElement.text() lub iElement.context, a następnie ukrycie go.

+0

Dzięki. Tak naprawdę próbowałem to zrobić w funkcji 'link', ale zawartość nie została jeszcze przetłumaczona przez ten punkt. – jessegavin

0

zrobiłem to w ten sposób, przy użyciu controllerAs.

/* wewnątrz dyrektywy */

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

/* wewnątrz szablonu */

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

Uprzednio przewidziane odpowiedzi były pomocne, ale nie rozwiąże moją sytuację doskonale, więc wymyśliłem inne rozwiązanie, tworząc oddzielną dyrektywę.

Utwórz dyrektywę opartą na atrybutach (tj. restrict: 'A'), która po prostu sprawdza, czy na wszystkich węzłach potomnych elementu znajduje się dowolny tekst.

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

Jeśli chcesz tylko sprawdzić główny element:

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

rozwiązać mój problem, wszystko, co było potrzebne, aby sprawdzić, czy są jakieś węzły potomne:

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

YMMV

1

Jeśli nie chcesz używać programu ng-show za każdym razem, możesz utworzyć dyrektywę automatycznie:

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

    return { 
     restrict: 'A', 

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

}]); 

Następnie można go zastosować do dowolnego elementu. W twoim przypadku będzie to:

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

Może trochę za późno, ale możesz także rozważyć użycie pseudo klasy CSS: empty. Tak, to będzie działać (IE9 +)

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

Element nadal będzie zarejestrowana w dom ale będzie pusty i niewidoczne.

Powiązane problemy