来自控制器的Angular调用指令

时间:2014-10-30 14:12:02

标签: angularjs angularjs-directive

我有以下指令用于显示弹出窗口以确认单击时执行函数。

现在我想在我的控制器中使用它来显示一个弹出窗口,如果一个对象的属性已被更改,并且用户想要更改位置而不保存之前的对象。这可能吗?

angular.module('app.confirm', [
    'ui.bootstrap',
    'template/modal/confirm.html',
])

.controller('ConfirmModalController', ['$scope', '$modalInstance', function($scope, $modalInstance) {
    $scope.confirm = function() {
        $modalInstance.close();
    };

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

.directive('confirm', ['$modal', function($modal) {
    return {
        restrict: 'A',
        scope: {
            confirm: '&',
            title: '@confirmTitle',
            message: '@confirmMessage',
            confirmButtonText: '@confirmButtonText',
            cancelButtonText: '@cancelButtonText'
        },
        link: function(scope, element, attributes) {
            element.bind('click', function() {
                var modal= $modal.open({
                    controller: 'ConfirmModalController',
                    templateUrl: 'template/modal/confirm.html',
                    size: 'sm',
                    scope: scope
                });

                modal.result.then(function() {
                    scope.confirm();
                }, function() {
                    // Modal dismissed
                });
            });
        }
    };
}]);

angular.module('template/modal/confirm.html', []).run(['$templateCache', function($templateCache) {
    $templateCache.put(
        'template/modal/confirm.html',
        '<div class="modal-header" ng-show="title">' + 
            '<strong class="modal-title">{{title}}</strong>' + 
        '</div>' + 
        '<div class="modal-body">' +
            '{{message}}' + 
        '</div>' + 
        '<div class="modal-footer">' +
            '<a href="javascript:;" class="btn btn-link pull-left" ng-click="cancel()">{{cancelButtonText}}</a>' + 
            '<button class="btn btn-danger" ng-click="confirm()">{{confirmButtonText}}</button>' +
        '</div>'
    );
}]);

你可以这样使用它:

<button 
    confirm="delete(id)" 
    confirm-title="Really?"
    confirm-message="Really delete?"
    confirm-button-text="Delete"
    cancel-button-text="Cancel"
    class="btn btn-danger"
>
    Delete
</button>

2 个答案:

答案 0 :(得分:7)

N0- $观看解决方案:

<强> 1
为您的控制器提供一个回调,该回调从您的指令接收一个公开的接口。您的控制器会抓取界面并在其所需的脚本中使用它。简单,可以在任何现有指令上实现。

Plnkr for interface callback

  app.directive("simpleDialog",function(simpleDialog){
    return{
      template:"<button ng-click='open()'>open from directive</button>",
      scope:{
        onInit : "&onInit"
      },
      link: function(scope){
        scope.open = simpleDialog.open;
        scope.onInit({interface:{open:scope.open}});
      }
    }
  });

更复杂但是很好的模式......

<强> 2
如果你想制作一个也有可编程接口的指令,那么我建议将指令的核心作为提供者来实现。然后,您可以基于提供程序实现您的指令,并且在您希望通过脚本完全访问相同功能的情况下,您可以通过将其注入控制器直接在提供程序上运行。

这是ngDialog

后面的实施策略

此外,正如您正在创建一个确认对话框,您会发现此模式很有用,因为您的open方法可以返回一个可以通过对话框解决或拒绝的承诺,允许您的控制器根据承诺做出响应。

PLNKR DEMO

<!DOCTYPE html>
<html>

  <head>
    <script data-require="angular.js@*" data-semver="1.3.0" src="//code.angularjs.org/1.3.0/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    
  </head>

  <body ng-controller="myCtrl">
  
    <h1>Exposing a  Directive interface to a controller</h1>
    <div simple-dialog on-init="initCallback(interface)"></div>
    <p><button ng-click="open()">Open from controller</button></p>
    <p><button ng-click="open2()">Open from Exposed interface</button></p>
    
    <script>
      
      
      var app = angular.module("app",[]);
      
      app.controller("myCtrl",function(simpleDialog,$scope){
        $scope.open = simpleDialog.open;
        $scope.open2 = function(){
          this.interface.open();
        }
        $scope.initCallback = function(interface){
          this.interface = interface;
        }
      });
      
    
      app.provider("simpleDialog",function(){
        
        this.$get = function(){
          
          var publicMethods={
            open:function(){
              alert("Impelment Dialog Here");
            }
          }
          
          return publicMethods;
          
        }
      });
      
      app.directive("simpleDialog",function(simpleDialog){
        return{
          template:"<button ng-click='open()'>open from directive</button>",
          scope:{
            onInit : "&onInit"
          },
          link: function(scope){
            scope.open = simpleDialog.open;
            scope.onInit({interface:{open:scope.open}});
          }
        }
      });
      
      angular.bootstrap(document,["app"]);
      
    </script>
  </body>
</html>

答案 1 :(得分:0)

您可以在指令中观察范围属性的更改。

例如,添加confirm-show-when

<button 
    confirm="delete(id)" 
    ...
    confirm-show-when="state.showConfirmDialog"
    ...
>
    Delete
</button>

将其添加到指令定义

.directive('confirm', ['$modal', function($modal) {
    return {
        restrict: 'A',
        scope: {
            confirm: '&',
            title: '@confirmTitle',
            message: '@confirmMessage',
            confirmButtonText: '@confirmButtonText',
            cancelButtonText: '@cancelButtonText',
            showWhen: '=confirmShowWhen'
        },
        link: function(scope, element, attributes) {
            var showModal = function() {
                var modal= $modal.open({
                    controller: 'ConfirmModalController',
                    templateUrl: 'template/modal/confirm.html',
                    size: 'sm',
                    scope: scope
                });

                modal.result.then(function() {
                    scope.confirm();
                }, function() {
                    // Modal dismissed
                    // set showWhen back to false
                    scope.showWhen = false;
                });
            };
            element.bind('click', showModal);
            scope.$watch('showWhen', function(newVal) {
                if (newVal) {showModal()};
            });
        }
    };
}]);

在您的控制器中,只需将showConfirmDialog设置为true即可显示。

// controller code
// set up the state object so we use the 'dot' notation
$scope.state = { showConfirmDialog: false };
// other controller code
if (userWantsToDelete) {
    $scope.state.showConfirmDialog = true;
}
相关问题