【问题标题】:AngularJS Ui-Bootstrap ng-bind-html scope resolution of $modal$modal 的 AngularJS Ui-Bootstrap ng-bind-html 范围解析
【发布时间】:2015-12-05 04:28:13
【问题描述】:

我正在尝试打开一个 AngularJS 模式并作为参数传入 HTML 表单控件。到目前为止,我已经设法学习如何传入和接收返回值,只要它们与模式中的硬编码控件相关联。

问题似乎是让软编码(我作为参数传递的表单控件)进入与模态范围的其余部分相同的范围。我四处寻找一个孤立的范围,但甚至不确定这是否朝着正确的方向发展。在某个地方,我读到这与嵌入有关……不管那是什么?

任何帮助将不胜感激。

这是下面显示的代码的一个小插曲。

http://plnkr.co/edit/gg8IJeC62Im0evqmyN0U?p=preview

在我的示例中,我希望能够输入一个种子值,然后单击打开模式按钮,然后看到种子值出现在软编码和硬编码输入文本框中。软编码的文本框好像不太喜欢我……:-(

我的 HTML:

<!DOCTYPE html>
<html ng-app='myApp'>
<head>
    <link data-require="bootstrap-css@*" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
    <script data-require="jquery@>=1.9.1 <3" data-semver="2.1.4" src="https://code.jquery.com/jquery-2.1.4.js"></script>
    <script data-require="bootstrap@*" data-semver="3.3.6" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.js"></script>
    <script data-require="angular.js@1.4.8" data-semver="1.4.8" src="https://code.angularjs.org/1.4.8/angular.js"></script>
    <script data-require="angular-sanitize@*" data-semver="1.4.3" src="https://code.angularjs.org/1.4.3/angular-sanitize.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.14.3/ui-bootstrap-tpls.min.js"></script>
    <!--link rel="stylesheet" href="style.css" /-->
    <script src="script.js"></script>
</head>
<body>
    <div ng-controller="MainController as MainController">
        <h1>How to pass values and code to Modal and maintain Scope?</h1>
        <div>Enter Seed Value below, then click open model and change the value.</div>
        <br /> Seed Value:
        <input type="text" ng-model="MainController.mySeedValue" />
        <button ng-click="MainController.OpenModal()">OpenModal</button>
        <br />
        <br />
        <div>Assuming the seed value was change while the modal was open , the revised value should be refelected below.</div>
        <br /> Result: {{MainController.myModalResults.mySeedValue}}
    </div>
</body>
</html

我的模态模板:

<div class="modal-header">
    <button class="close" data-dismiss="modal" aria-hidden="true" ng-click="cancel()">&times;</button>
    <span>{{params.header}} Report Configuration</span>
</div>
<div class="modal-body">
    <div class="row">
        params.body: {{ params.body }}
        <br />
        params.mySeedValue: {{params.mySeedValue}}
        <br />
        Soft Coded: <div ng-bind-html="params.body | unsafe"></div>
        <br />
        Hard Coded: <input type="text" ng-model="params.mySeedValue" />
        <br />
    </div>
    <div class="row">
        <button class="btn" ng-click="cancel()">Cancel</button>
        <button class="btn btn-primary" ng-click="ok(params)">Save</button>
    </div>
</div>

我的 JavaScript 文件:

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

app.controller('MainController', ['$scope', '$uibModal', '$sce', function ($scope, $uibModal, $sce) {
    _this = this;
    this.OpenModal = function () {

        var scope = $scope.$new(true);
        scope.params = {
            'header': 'TestHeader',
            'body': '<input type="text" ng-model="params.mySeedValue" />',
            'mySeedValue': _this.mySeedValue
        };

        var modalInstance = $uibModal.open({
            scope: scope,
            templateUrl: 'myModal.html',
            controller: myModalController,
            backdrop: 'static'
        });


        modalInstance.result.then(function (modalResults) {
            _this.myModalResults = modalResults
            //on ok button press
            console.log("Modal Saved");
        }, function () {
            //on cancel button press
            console.log("Modal Closed");
        });
    };
}]);

var myModalController = function ($scope, $uibModalInstance) {

    $scope.ok = function () {
        $uibModalInstance.close($scope.params);
    };

    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };
};

// return safe html code
app.filter('unsafe', function ($sce) {
    return function (val) {
        return $sce.trustAsHtml(val);
    };
});

结束

【问题讨论】:

    标签: angularjs angularjs-scope angular-ui-bootstrap ngsanitize


    【解决方案1】:

    一段时间以来,我很幸运有一位导师帮助我学习 AngularJS。昨晚我和他谈了另一个会议,一个小时内他设法向我展示了语法,但解释了整个过程中发生了什么。再次感谢 Olen Davis,导师、大师和朋友!

    这是 plunker 的一个叉子 http://plnkr.co/edit/CevME8WBdZx7mqfoNfsj?p=preview

    基本上,他解释说,出于安全原因,不推荐我这样做,如果我不小心处理 HTML,就有可能被黑客注入脚本。正如我所解释的,我将在 HTML 字符串中加载的功能是报表编写器选择过程的一部分,所有 HTML 将以单向路径来自服务器数据库。发回无效内容的机会不大。

    如下所示的答案是将 HTML 编译并链接到 MainController 范围。需要一个我们称为“bind-compiled-html”的新指令来替换 AngularJS ng-bind-html 指令。我不明白他向我展示的所有细节和语法,但它现在可以工作了,我现在可以开始研究为使 $compile 工作而发生的所有参数传递。

    我希望我正确回忆的一些关键点包括:当我定义指令“bindCompiledHtml”的范围时,等号符号正在创建一个隔离范围。我们创建了一个 childScope 并防止对指令的第二次请求出错,我们添加了 if(childScope) exists 在创建另一个新的之前将其销毁......我认为他所说的可能是内存泄漏。如果没有字符串传递给 $compile,if(bindCompiledHtml) 确保我不会生成错误。很好,在链接函数中,我们编译传递的 HTML 并将其添加到 MainController 范围内的 DOM ...$scope.$parent.$new()。

    在 MainController 中,我们从 $new(true) 中删除了创建隔离作用域的参数。并将我的种子值重新定义为一个对象,以允许我在 MainController 范围内轻松传递更多参数。

    在模态模板上,种子值现在通过引用 MainController 点键符号来调用。

    代码如下:

    Script.js

    var app = angular.module('myApp', ['ui.bootstrap', 'ngSanitize']);
    
    
    // *** data driven injection ***
    app.directive('bindCompiledHtml', function ($compile) {
        // return directive defination object
        return {
            scope: {
                bindCompiledHtml: '='
            },
            link: function ($scope, $element) {
                var childScope;
                $scope.$watch('bindCompiledHtml', function (bindCompiledHtml) {
                    if (childScope) {
                        childScope.$destroy();
                    }
                    if (bindCompiledHtml) {
                        var linkFunc = $compile(bindCompiledHtml);
                        childScope = $scope.$parent.$new();
                        linkFunc(childScope, function (compElement) {
                            $element.html('');
                            $element.append(compElement);
                        });
                    }
                })
            }
        };
    });
    
    app.controller('MainController', ['$scope', '$uibModal', '$sce', function ($scope, $uibModal, $sce) {
        _this = this;
        _this.mySeedValue = { 'key': 'test' };
    
        this.OpenModal = function () {
    
            var scope = $scope.$new();
            scope.params = {
                'header': 'TestHeader',
                'body': '<input type="text" ng-model="MainController.mySeedValue.key" />',
            };
    
            var modalInstance = $uibModal.open({
                scope: scope,
                templateUrl: 'myModal.html',
                controller: myModalController,
                backdrop: 'static'
            });
    
    
            modalInstance.result.then(function () {
                //on ok button press
                console.log("Modal Saved");
            }, function () {
                //on cancel button press
                console.log("Modal Closed");
            });
        };
    }]);
    
    var myModalController = function ($scope, $uibModalInstance) {
    
        $scope.ok = function () {
            $uibModalInstance.close();
        };
    
        $scope.cancel = function () {
            $uibModalInstance.dismiss('cancel');
        };
    };
    

    ...和主 HTML 页面

    <!DOCTYPE html>
    <html ng-app='myApp'>
    <head>
        <link data-require="bootstrap-css@*" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
        <script data-require="jquery@>=1.9.1 <3" data-semver="2.1.4" src="https://code.jquery.com/jquery-2.1.4.js"></script>
        <script data-require="bootstrap@*" data-semver="3.3.6" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.js"></script>
        <script data-require="angular.js@1.4.8" data-semver="1.4.8" src="https://code.angularjs.org/1.4.8/angular.js"></script>
        <script data-require="angular-sanitize@*" data-semver="1.4.3" src="https://code.angularjs.org/1.4.3/angular-sanitize.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.14.3/ui-bootstrap-tpls.min.js"></script>
        <!--link rel="stylesheet" href="style.css" /-->
        <script src="script.js"></script>
    </head>
    <body>
        <div ng-controller="MainController as MainController">
            <h1>How to pass values and code to Modal and maintain Scope?</h1>
            <div>Enter Seed Value below, then click open model and change the value.</div>
            <br /> Seed Value:
            <input type="text" ng-model="MainController.mySeedValue.key" />
            <button ng-click="MainController.OpenModal()">OpenModal</button>
            <br />
            <br />
            <div>Assuming the seed value was change while the modal was open , the revised value should be refelected below.</div>
            <br /> Result: {{MainController.mySeedValue.key}}
        </div>
    </body>
    </html>
    

    ...以及修改后的模态模板页面:

    <div class="modal-header">
        <button class="close" data-dismiss="modal" aria-hidden="true" ng-click="cancel()">&times;</button>
        <span>{{params.header}} Report Configuration</span>
    </div>
    <div class="modal-body">
        <div class="row">
            params.body: {{ params.body }}
            <br />
            MainController.mySeedValue.key: {{MainController.mySeedValue.key}}
            <br />
            Soft Coded: <div bind-compiled-html="params.body"></div>
            <br />
            Hard Coded: <input type="text" ng-model="MainController.mySeedValue.key" />
            <br />
        </div>
        <div class="row">
            <button class="btn" ng-click="cancel()">Cancel</button>
            <button class="btn btn-primary" ng-click="ok()">Save</button>
        </div>
    </div>
    

    我们随时欢迎任何反馈。 (...希望我只会得到积极的回应,...如果有一天能获得足够高的分数来评论其他人的帖子,那就太好了:-)。)

    【讨论】:

      【解决方案2】:

      我注意到至少 2 个问题。

      问题:

      • 您正在混合使用两种方法来使用控制器,$scope 和 this。
      • 模式模板缺少控制器。

      解决方案:

      • 从控制器中删除“$scope.model”,这就是 Angular 建议您应该如何做的事情,将来在 Angular 2 中,将没有 $scope。

      角度推荐:https://docs.angularjs.org/api/ng/directive/ngController
      Angular2 $scope 省略:http://paislee.io/migrating-to-angularjs-2-0/

      • 在模态实例中定义“控制器为:someAlias”。在模态模板中使用此别名,例如 someAlias.param,这样您将与模态进行完整的数据绑定。

      这里我没有检查也没有写完整的代码,这只是为了给你一个适用于你的案例的基本思路。

      JavaScript 文件:

      app.controller('MainController', ['$scope', '$uibModal', '$sce', function ($scope, $uibModal, $sce){
      
          var vm = this;  // "this" here has the scope of "MainController", main html.
      
              var modalInstance = $uibModal.open({
              templateUrl: 'myModal.html',
              controller: myModalController,
              controllerAs: 'modalcontrollerAlias',
              backdrop: 'static'
      
              // if you wanna send data from here to the modal's controller, use "resolve" here, and include it in "myModalController", app.controller('myModalController', ['$scope', 'someName', '$uibModalInstance', function ($scope ,someName, uibModalInstance)
      
      //        resolve: {
      //            someName: function () {
      //                return vm.mySeedValue;
      //            }
      //        }
          });
      }]);
      
      app.controller('myModalController', ['$scope', '$uibModalInstance', function ($scope, uibModalInstance) {
      
          var vm = this;  // "this" here has the scope of "myModalController", modal template.
      
              vm.ok = function () {
                  $uibModalInstance.close(vm.params);
              };
      
              vm.cancel = function () {
                  $uibModalInstance.dismiss('cancel');
              };
      }]);
      

      模态模板:

      <div class="modal-header">
          <button class="close" data-dismiss="modal" aria-hidden="true" ng-click="cancel()">&times;</button>
          <span>{{modalcontrollerAlias.params.header}} Report Configuration</span>
      </div>
      <div class="modal-body">
          <div class="row">
              params.body: {{ modalcontrollerAlias.params.body }}
              <br />
              params.mySeedValue: {{modalcontrollerAlias.params.mySeedValue}}
              <br />
              Soft Coded: <div ng-bind-html="modalcontrollerAlias.params.body | unsafe"></div>
              <br />
              Hard Coded: <input type="text" ng-model="modalcontrollerAlias.params.mySeedValue" />
              <br />
          </div>
          <div class="row">
              <button class="btn" ng-click="modalcontrollerAlias.cancel()">Cancel</button>
              <button class="btn btn-primary" ng-click="modalcontrollerAlias.ok(modalcontrollerAlias.params)">Save</button>
          </div>
      </div>
      

      【讨论】:

      • 感谢您提出建议。我似乎无法使您的方法起作用。一个完整的工作示例,包括向模态传递一个 html 字符串并将该字符串作为公开范围内的输入控件(命名或以其他方式命名)将非常有帮助。我发布了一个解决方案,并包含了一个我想要实现的工作 Plunker 示例。再次感谢您提供帮助。
      猜你喜欢
      • 2013-06-18
      • 2013-01-31
      • 2015-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多