2013-04-02 8 views
9

Ho creato una direttiva molto semplice che mostra una coppia chiave/valore. Vorrei poter nascondere automaticamente l'elemento se il contenuto escluso è vuoto (lunghezza zero o solo spazi bianchi).Come nascondere l'elemento se i contenuti esclusi sono vuoti?

Non riesco a capire come accedere al contenuto che viene transclusionato da una direttiva.

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

Ad esempio, desidero visualizzare il seguente elemento.

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

Ma i prossimi due elementi devono essere nascosti perché non contengono alcun contenuto di testo.

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

Sono nuovo di Angular quindi ci può essere un ottimo modo per gestire questo genere di cose fuori dalla scatola. Qualsiasi aiuto è apprezzato.

risposta

8

Ecco un approccio che utilizza ng-show nel modello e all'interno di compile transcludeFn che verifica se l'html transclusionato ha una lunghezza di testo.

Se no Lunghezza testo ng-show è impostato per nascondere

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 per ogni risposta che mostra un caso d'uso per l'esoterico transcludeFn :). –

+1

nel transcludeFn, 'clone.text(). Trim(). Length' sarebbe un po 'più preciso – alalonde

+0

+1 grazie, questo mi ha fatto risparmiare un sacco di tempo. – cgTag

0

Non ho molta familiarità con la transazione, quindi non sono sicuro che sia d'aiuto o meno.

ma un modo per verificare la presenza di contenuti vuoti all'interno del codice di direttiva è utilizzare l'oggetto iElement.text() o iElement.context e quindi nasconderlo.

+0

Grazie. In realtà ho provato a farlo con la funzione 'link', ma il contenuto non era ancora stato completato da quel punto. – jessegavin

0

ho fatto in questo modo, utilizzando controllerAs.

/* all'interno direttiva */

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

/* dentro * template/

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

Le risposte in precedenza forniti erano utili, ma non ha risolto la mia situazione perfettamente, così mi si avvicinò con una soluzione diversa creando una direttiva separata.

Creare una direttiva basata sugli attributi (ad esempio restrict: 'A') che controlla semplicemente se è presente del testo su tutti i nodi figlio dell'elemento.

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

Se solo si desidera controllare l'elemento principale:

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

per risolvere il mio problema, tutto quello che serviva era di verificare se ci fossero nodi figli:

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

YMMV

1

Se non si desidera utilizzare ng-show ogni volta, è possibile creare una direttiva per farlo automaticamente:

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

    return { 
     restrict: 'A', 

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

}]); 

Quindi è possibile applicarlo su qualsiasi elemento. Nel tuo caso sarebbe:

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

Forse un po 'in ritardo, ma si può anche considerare l'uso del CSS classe Pseudo: vuota. Quindi, questo funzionerà (IE9 +)

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

L'elemento sarà ancora registrata nel Regno, ma sarà vuoto e invisibile.

Problemi correlati