6

Chciałbym użyć ng-include w zawartości dynamicznie generowanej karty za pomocą AngularJs i UI Bootstrap.Zawartość dynamiczna w karcie dynamicznej (Angular, UI Bootstrap)

Mam Plunker tutaj: http://plnkr.co/edit/2mpbovsu2eDrUdu8t7SM?p=preview

<div id="mainCntr" style="padding: 20px;"> 
    <uib-tabset> 
    <uib-tab ng-repeat="tab in tabs" active="tab.active" disable="tab.disabled"> 
     <uib-tab-heading> 
     {{tab.title}} <i class="glyphicon glyphicon-remove-sign" ng-click="removeTab($index)"></i> 
     </uib-tab-heading> 
     {{tab.content}} 
    </uib-tab> 
    </uib-tabset> 
</div> 

kodu JS:

$scope.addTab = function() { 
    var len = $scope.tabs.length + 1; 
    var numLbl = '' + ((len > 9) ? '' : '0') + String(len); 

    var mrkUp = '<div>' + 
     '<h1>New Tab ' + numLbl + ' {{foo}}</h1>' + 
     '<div ng-include="tab.tabUrl" class="ng-scope"></div>' + 
     '</div>'; 

    $scope.tabs.push({title: 'Tab ' + numLbl, content: $compile(angular.element(mrkUp))($scope)}); 
} 

W Plunker, kliknij przycisk "Dodaj Tab". Wywołuje funkcję w polu $ scope, która przesuwa nową kartę do kolekcji, ale przekazuje ją w dynamicznie generowanej treści zawierającej dyrektywę ng-include. Oczekiwanym wynikiem jest to, że ng-include zostanie wyświetlone wewnątrz obszaru zawartości karty.

Dzięki

+0

Twój plunk nie działa poprawnie, tak myślę? –

+0

Nie mogłem go uruchomić. Pijak to tylko moja próba - mam nadzieję, że ktoś tutaj pomoże mi go uruchomić. – vdiaz1130

+0

... oh, teraz działa. Kiedy spojrzałem na to wcześniej, było zepsute. Przyjrzymy się ponownie. –

Odpowiedz

4

W swojej Plunker używanego ng-bind-html które nie kompiluje kod HTML dla Ciebie. Możesz utworzyć nową dyrektywę, która zrobi to za Ciebie.

Kod źródłowy ng-bind-html:

var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) { 
    return { 
    restrict: 'A', 
    compile: function ngBindHtmlCompile(tElement, tAttrs) { 
     var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml); 
     var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) { 
     return (value || '').toString(); 
     }); 
     $compile.$$addBindingClass(tElement); 

     return function ngBindHtmlLink(scope, element, attr) { 
     $compile.$$addBindingInfo(element, attr.ngBindHtml); 

     scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() { 
      // we re-evaluate the expr because we want a TrustedValueHolderType 
      // for $sce, not a string 
      element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || ''); 
     }); 
     }; 
    } 
    }; 
}]; 

Wybierz nazwę dla nowej dyrektywy, na przykład compile-html.

Wymień tAttrs.ngBindHtml na tAttrs.compileHtml (lub dowolną wybraną przez siebie nazwę).

Trzeba zastąpić $sce.getTrustedHtml z $sce.trustAsHtml lub dostaniesz Error: [$sce:unsafe] Attempting to use an unsafe value in a safe context.

Następnie trzeba zadzwonić $compile:

$compile(element.contents())(scope); 

Pełna dyrektywy:

app.directive('compileHtml', ['$sce', '$parse', '$compile', 
    function($sce, $parse, $compile) { 
    return { 
     restrict: 'A', 
     compile: function ngBindHtmlCompile(tElement, tAttrs) { 
     var ngBindHtmlGetter = $parse(tAttrs.compileHtml); 
     var ngBindHtmlWatch = $parse(tAttrs.compileHtml, function getStringValue(value) { 
      return (value || '').toString(); 
     }); 
     $compile.$$addBindingClass(tElement); 

     return function ngBindHtmlLink(scope, element, attr) { 
      $compile.$$addBindingInfo(element, attr.compileHtml); 

      scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() { 

      element.html($sce.trustAsHtml(ngBindHtmlGetter(scope)) || ''); 
      $compile(element.contents())(scope); 
      }); 
     }; 
     } 
    }; 
    } 
]); 

Zastosowanie:

<div compile-html="tab.content"></div> 

Demo:http://plnkr.co/edit/TRYAaxeEPMTAay6rqEXp?p=preview

1

Moja sytuacja nie może być tak skomplikowane, więc to proste rozwiązanie działa:

sdo.tabs:{ 
     data:[], 
     active:0, 
     reset: function(){ 
      var tabs = this.data; 
      while(tabs.length > 0) { 
       this.removeTab(tabs[tabs.length-1].child.name); 
      } 
      this.active = 0; 
     }, 
     childExists: function(childName) { 
      var fromTheTop = this.data.length, 
       parentName = (this.active > 0 ? this.data[ this.active - 1 ].child.name : 'zero'); 
      while(fromTheTop > this.active) { 
       var child = this.data[ fromTheTop-1 ].child; 
       if(child && child.parent === parentName && child.name === childName) return fromTheTop; 
       fromTheTop--; 
      } 
      return false; 
     }, 
     removeTab: function(name) { // will remove any descendents of this tab as well, see recursive call near end 
      var fromTheTop = this.data.length; 
      while(fromTheTop > 0) { 
       var tab = this.data[fromTheTop - 1]; 
       if(tab.child.name === name) { 
        angular.element('#'+name).empty(); 
        this.data.splice(fromTheTop - 1); 
        return; 
       } 
       if(tab.child.parent === name) this.removeTab(tab.child.name); 
       fromTheTop--; 
      }; 
     }, 
     /* 
     * tab is string identifies tab but doesn't show in the UI 
     * tempmlate is HTML template 
     * scope is used to compile template 
     * title is string or function for UI tab title, appears in the tab row 
     */ 
     create: function(tab, template, scope, title) { 
      var childName = tab; 
      var tabs = this.data; 
      tab = this.childExists(childName); 
      if(tab === false) { 
       tab = tabs.length + 1; 
      } else { // recycling a tab, kill it & its descendents 
       this.removeTab(childName); 
      } 
      tabs[tab-1] = { 
       title:function(){ 
        if(angular.isFunction(title)) return title(); 
        return title; 
       }, 
       child: { 
        parent:(this.active > 0 ? this.data[ this.active - 1 ].child.name : 'zero'), 
        name:childName 
       }      
      }; 
      var ct = $timeout(function() { 
       angular.element('#'+tabs[tab-1].child.name).html($compile(template)(scope)); 
       sdo.tabs.active = tab; 
       return; // return nothing to avoid memory leak 
      }); 
      scope.$on('$destroy', function() { 
       $timeout.cancel(ct); 
      }); 
      return ct; // ct is a promise 
     } 
    } 

HTML jest

<uib-tabset active="tabs.active"> 
 
    <uib-tab index='0' heading="{{title}}"> 
 
     <ng-view></ng-view> 
 
    </uib-tab> 
 
    <uib-tab ng-repeat="tab in tabs.data track by tab.child.name" heading="{{tab.title()}}" index='$index+1' > 
 
     <div id="{{tab.child.name}}"></div> 
 
    </uib-tab> 
 
</uib-tabset>

W moim przypadku pierwsza karta jest zapełniana przez router Angular, dlatego tablica tabulacji jest jednym z indeksów od tabs.active

Powiązane problemy