6

AngularJs と UI Bootstrap を使用して、動的に生成されたタブのコンテンツで ng-include を使用したいと思います。

ここにプランカーがあります: 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>

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

プランカーで、[タブの追加] ボタンをクリックします。新しいタブをコレクションにプッシュする $scope の関数を呼び出しますが、ng-include ディレクティブを含む動的に生成されたコンテンツを渡します。予想される出力は、ng-include がタブ コンテンツ エリア内に表示されることです。

ありがとう

4

2 に答える 2

4

使用している Plunkerng-bind-htmlでは、HTML をコンパイルしません。それを行う新しいディレクティブを作成できます。

のソース コード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)) || '');
        });
      };
    }
  };
}];

新しいディレクティブの名前を選択します (例: ) compile-html

tAttrs.ngBindHtml(または選択しtAttrs.compileHtmlた名前)に置き換えます。

に置き換える必要があります。そうしない$sce.getTrustedHtml$sce.trustAsHtmlError: [$sce:unsafe] Attempting to use an unsafe value in a safe context.

次に、次のように呼び出す必要があります$compile

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

完全なディレクティブ:

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

使用法:

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

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

于 2015-11-13T08:54:06.020 に答える
1

私の状況はそれほど複雑ではないかもしれないので、この簡単な解決策はうまくいきます:

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は

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

私の場合、最初のタブは Angular ルーターによって設定されます。これが、タブ配列が 1 つのインデックスから外れた理由です。tabs.active

于 2016-06-04T06:48:10.270 に答える