当使用$compile绑定HTML内容时,AngularUI引导旋转木马不能正常工作。

时间:2022-03-18 11:03:19

AngularUI Bootstrap version ^2.4.22

AngularUI引导版本^ 2.4.22

AngularJS version 1.6.4

1.6.4 AngularJS版本

Angular Sanitize version ^1.6.1

角Sanitize版本^ 1.6.1

I'm having trouble using AngularUI Bootstrap's Carousel plugin. In my scenario, i need to read an external file containing some template paths, and load each of them as a slide. See example below:

我在使用angularuibootstrap的Carousel插件时遇到了麻烦。在我的场景中,我需要读取一个包含一些模板路径的外部文件,并将它们作为幻灯片加载。请参见下面的例子:

index.html (where directive is being called)

索引。html(调用指令)

     <body id="body" ng-app="homePage">
        <div id="miolo">
            <div example-directive class="ng-hide"></div>
            <div banner-rotativo></div>
            <div id="menu-footer"></div>
        </div>
     </body>

banner-rotativo.directive.js - Basically, in this directive, I have a template following the structure of AngularUI Bootstrap's demo, and i'm binding the response data to $scope.slides array. When i push into htmlContent property the $compile(objResponseInner)($scope) result, the carousel behavior works okay, but it renders [[object HTMLDivElement]] and things like that as an item.

banner-rotativo.directive。基本上,在这个指令中,我有一个遵循AngularUI Bootstrap的演示结构的模板,我将响应数据绑定到$scope。幻灯片数组。当我将$compile(objResponseInner)($scope)的结果推入htmlContent属性时,carousel行为可以正常工作,但它会将[object HTMLDivElement]]和类似的东西呈现为一个条目。

当使用$compile绑定HTML内容时,AngularUI引导旋转木马不能正常工作。

angular.module('homePage')
.directive('bannerRotativo', ['$compile', '$http', 'moduleUrl', '$templateRequest', function ($compile, $http, moduleUrl, $templateRequest) {
    return {
        template:   '<div style="height: 305px" ng-controller="bannerHomeController" class="" >\
                        <div uib-carousel active="active" interval="myInterval" no-wrap="noWrapSlides">\
                            <div uib-slide ng-repeat="slide in slides track by slide.id" index="slide.id">\
                                <div ng-bind-html="slide.htmlContent">\
                                </div>\
                            </div>\
                        </div>\
                    </div>',

        link: function (scope, element, attributes, controller) {

            //Carousel
            scope.myInterval = 5000;
            scope.noWrapSlides = false;
            scope.active = 0;
            scope.slides = [];
            var intCurrentIndex = 0;

            $http({
                method: 'GET',
                url: moduleUrl.getUrl('homepage', '../config/banner-rotativo.conf')
            }).then(function success(objResponse, status, headers, config) {
                var objData = objResponse.data;
                if (objData.slides) {
                    angular.forEach(objData.slides, function (objItem, strObjectName) {
                        var strTemplatePath = moduleUrl.getUrl('homepage', '..' + objItem.caminho);
                        if (strTemplatePath) {
                            $templateRequest(strTemplatePath).then(function success(objResponseInner) {
                                var objContent = $compile(objResponseInner)(scope);
                                scope.slides.push({
                                    htmlContent: objContent,
                                    id: intCurrentIndex++
                                });
                            });
                        }
                    });
                }
            });
        }
    }


}]);

banner-rotativo.conf

banner-rotativo.conf

{
"slides": {
    "banner-ex-one": {
        "titulo": "exone",
        "caminho-imagem": "assets/one.jpg",
        "caminho": "/html/components/banner-rotativo/banner-ex-one.view.html"
    },
    "banner-ex-two" : {
        "titulo": "extwo",
        "caminho-imagem": "assets/two.jpg",
        "caminho": "/html/components/banner-rotativo/banner-ex-two.view.html"
    },
    "banner-rav" : {
        "title": "rav",
        "caminho-imagem": "assets/rav.jpg",
        "caminho": "/html/components/banner-rotativo/banner-rav.view.html"
    },
    "banner-aviso" : {
        "title": "Quadro de comunicações 1",
        "caminho-imagem": "assets/aviso.jpg",
        "caminho": "/html/components/banner-rotativo/banner-aviso.view.html"
    },
    "banner-custom" : {
        "title": "Quadro de comunicações 2",
        "caminho-imagem": "assets/custom.jpg",
        "caminho": "/html/components/banner-rotativo/banner-custom.view.html"
    }
  }
}

Loaded template example:

加载模板示例:

<div id="frameOne" ng-controller="slideOneController" class="varejo-clique-promocao-one" title="Conteúdo Varejo - Quadro One">
<div class="item">
    <div id="dados">

        <!-- Imagem banner one -->
        <img id="one" ng-click="enviarFormOne()" class="one" alt="" ng-if="1==1" ng-src="caminhoImagem"
        />
        <!-- End imagem banner -->
        <span ng-if="hasText">{{bannerText}}</span>
    </div>
    <div id="excecao" class="excecao" ng-if="typeof(one.excecao) !== 'undefined'">
        DEU EXCECAO
    </div>
    <div class="carousel-title" id="tituloOne" ng-if="1==1" title="{{bannerTitle}}">
        {{bannerTitle}}
    </div>
</div>

Some important points:

一些重要的点:

  • I'm using $compile because my injected templates have controllers too. If i don't use it, my controllers aren't processed. When i simply insert the HTML without the $compile, it renders okay.
  • 我使用$compile是因为我的注入模板也有控制器。如果我不使用它,控制器就不会被处理。当我在不使用$compile的情况下插入HTML时,它会呈现为ok。

What's wrong?

怎么了?

1 个解决方案

#1


2  

The problem is that ng-bind-html expects html string and you are giving it the result from $compile that is actually an element object. You could take the HTML string from the compiled element and pass that instead, but you would probably run into all kind of trouble with that.

问题是,ng-bin -html期望得到html字符串,而您提供的结果是$compile,它实际上是一个元素对象。您可以从已编译的元素中获取HTML字符串并传递它,但是您可能会遇到各种各样的麻烦。

But you can actually just skip the hassle with $compile by using ngInclude instead of ng-bind-html. It will handle both the template request and the compilation for you.

但是实际上您可以通过使用ngInclude而不是ng-bind-html来跳过这些麻烦。它将处理模板请求和编译。

So instead of requesting and compiling strTemplatePath, store that to the slide list:

因此,与其请求和编译strTemplatePath,不如将其存储到幻灯片列表中:

var strTemplatePath = moduleUrl.getUrl('homepage', '..' + objItem.caminho);
if (strTemplatePath) {
    scope.slides.push({
        htmlUrl: strTemplatePath,
        id: intCurrentIndex++
    });
}

And then use that in the template:

然后在模板中使用:

<div uib-slide ng-repeat="slide in slides track by slide.id" index="slide.id">
    <div ng-include="slide.htmlUrl"></div>
</div>

Here's a somewhat working fiddle: jsfiddle.net, although I had to fill in a few blanks here and there.

这里有一个可以工作的东西:jsfiddle.net,尽管我必须在这里和那里填一些空格。

#1


2  

The problem is that ng-bind-html expects html string and you are giving it the result from $compile that is actually an element object. You could take the HTML string from the compiled element and pass that instead, but you would probably run into all kind of trouble with that.

问题是,ng-bin -html期望得到html字符串,而您提供的结果是$compile,它实际上是一个元素对象。您可以从已编译的元素中获取HTML字符串并传递它,但是您可能会遇到各种各样的麻烦。

But you can actually just skip the hassle with $compile by using ngInclude instead of ng-bind-html. It will handle both the template request and the compilation for you.

但是实际上您可以通过使用ngInclude而不是ng-bind-html来跳过这些麻烦。它将处理模板请求和编译。

So instead of requesting and compiling strTemplatePath, store that to the slide list:

因此,与其请求和编译strTemplatePath,不如将其存储到幻灯片列表中:

var strTemplatePath = moduleUrl.getUrl('homepage', '..' + objItem.caminho);
if (strTemplatePath) {
    scope.slides.push({
        htmlUrl: strTemplatePath,
        id: intCurrentIndex++
    });
}

And then use that in the template:

然后在模板中使用:

<div uib-slide ng-repeat="slide in slides track by slide.id" index="slide.id">
    <div ng-include="slide.htmlUrl"></div>
</div>

Here's a somewhat working fiddle: jsfiddle.net, although I had to fill in a few blanks here and there.

这里有一个可以工作的东西:jsfiddle.net,尽管我必须在这里和那里填一些空格。