Angular UI模式中的转换不起作用

时间:2016-09-27 21:30:56

标签: angularjs angular-ui-bootstrap angular-ui angular-directive

this plunk的目标是将元素从控制器转换为Angular UI Modal,其中Modal由指令包装。解决方案应遵循以下前提:

  • 该指令声明了字段的转换。这些字段包含在控制器HTML标记中的指令声明中。
  • 控制器中声明的这些字段应显示在模态中。
  • 这些字段的范围应该可以在控制器中访问(请参阅我在控制器中声明了一个input1变量,该变量应该在模态中设置一个值。)
  • 我定义了一个content元素来转换字段。此元素位于模态模板中。我不确定此模板何时可用于转录它。

总而言之,目标是在控制器HTML标记中声明一组字段并在模式中可用,其中模式包含在指令中,范围在控制器中管理。任何想法将不胜感激。

HTML

<div the-modal control="modalCtl">
    <p>some text</p>
    <input type="text" ng-model="input1" />
</div>

<button type="button" ng-click="open()">Open me!</button>

的Javascript

var app = angular.module("app", ['ui.bootstrap']);

app.controller("ctl", function($scope,$timeout) {

  $scope.modalCtl = {};

  $scope.input1 = "abc";

  $scope.open = function(){
    $scope.modalCtl.openModal();
  };

});


app.directive("theModal", function($uibModal) {
  return {
    restrict: "AE",        
    scope: {              
      control: "="
    },
    transclude: true,
    link: function (scope, element, attrs, ctrl, transclude) {
      scope.control = scope.control || {}

      scope.control.openModal = function () {
        scope.instance = $uibModal.open({
          animation: false,
          scope: scope,
          template: '<div>in the template</div><div class="content"></div>'
        });
        element.find('.content').append(transclude());
      };
    }
  }
});

3 个答案:

答案 0 :(得分:6)

你已经足够接近实现你的目标,但有一些事情你需要考虑:

  1. 首先,根据UI Bootstrap docsappendTo方法options中有一个$uibModal.open()属性,默认为{{} 1}} 的。

      

    如果未指定body,则模式将附加到您网页的appendTo,并成为body的直接子项。因此,通过body在您的指令中查询.content不会起作用,因为它不存在。

  2. 其次,AngularJS附带 jQLite ,这是jQuery的轻量级版本。这意味着对jQuery的大多数功能的支持有限。其中一种情况是使用element.find('.content')方法,该方法仅适用于标记名称。

    为了使它与jQuery一起工作(虽然你真的不必,因为你仍然可以在链中使用.find()来查询嵌套的DOM元素),你必须在Angular之前加载jQuery(我认为你已经)。

    有关详细信息,请参阅AngularJS docs on angular.element

  3. 渲染DOM需要花费一点时间用于Angular,因为它需要制作与范围和视图相关的正确绑定,以完成摘要周期,等等。 因此,您最终可能会立即查询实际上可能尚未呈现的DOM元素。

      

    等待DOM呈现和完成摘要周期的技巧是将与DOM相关的代码包装到.children()包装器中。

  4. 考虑到以上几点,自定义指令$timeout的链接功能中的openModal方法应如下所示:

    theModal

    请注意scope.control.openModal = function () { scope.instance = $uibModal.open({ animation: false, scope: scope, template: '<div>in the template</div><div class="content"></div>', /** * Make sure the modal is appended to your directive and NOT `body` */ appendTo: element }); /** * Give Angular some time to render your DOM */ $timeout(function (){ /** * In case jQuery is not available */ // var content = element.children('.modal').children('.modal-dialog').children('.modal-content').children('.content'); /** * Since you have jQuery loaded already */ var content = element.find('.content'); /** * Finally, append the transcluded element to the correct position, * while also making sure that the cloned DOM is bound to the parent scope (i.e. ctl) */ transclude(scope.$parent, function(clonedContent){ content.append(clonedContent); }); }); }; 函数如何让您控制如何将某些已转换的DOM绑定到自定义范围而不是默认指令的范围。普通transclude调用将考虑当前可用的范围对象 - 即指令的范围 - 用于绑定已转换的DOM。

    Demo

答案 1 :(得分:4)

如前面的答案所示,您可以使用appendTo属性将指令的元素作为模态的父元素。 您可以等待模式的模板呈现&#34;在UibModalIstance中使用rendered promise。 (Documentation)。

scope.control.openModal = function () {
    scope.instance = $uibModal.open({
        animation: false,
        scope: scope,
        template: '<div>in the template</div><div class="content"></div>',
        appendTo: element  
    });
    // We use the redered promise to make sure
    // the modal's template has been loaded.
    scope.instance.rendered.then(function (){
        // You'll most likely want to pass the `$parent` scope as the first
        // parameter for proper scope binding with your controller.
        element.find('.content').append(transclude(scope.$parent));
    });
};

这里是modified plunker.

答案 2 :(得分:0)

transclude: true,

不会那样工作,它会插入在指令范围内定义的任何标记,并将该标记放在指令模板中(放置ngTransclude的位置)。这不是你(看似)试图做的事情。

您正在寻找的是定义模板,给它一个网址并使用templateUrl属性将其提供给模态。

<强> HTML

<script type="text/ng-template" id="/some-tpl.html">
    <p>some text</p>
    <input type="text" value="1234" />
</script>

<强> JS

$uibModal.open({
    animation: false,
    scope: scope,
    templateUrl: "/some-tpl.html" // link to template url
})

然后你可以将你的指令/你的逻辑放在你提供模态的控制器中。

Here is an updated plunk