angularjs在控制器之间共享数据配置

时间:2014-01-29 09:34:37

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

我想知道什么是分享指令的好方法 在控制器之间 我有两个指令在不同的控制器中使用 不同的配置首先想到我想到的 使用like:

//html
<body data-ng-controller="MainCtrl">
    <div class="container">
        <div data-ui-view></div>
    </div>
</body>

//js
.controller('MainCtrl', function ($scope,$upload) {
    /*File upload config*/
    $scope.onFileSelect = function($files) {
        for (var i = 0; i < $files.length; i++) {
          var file = $files[i];
          $scope.upload = $upload.upload({
                url: 'server/upload/url', 
                method: 'POST',
                data: {myObj: $scope.myModelObj},
                file: file,
          }).progress(function(evt) {
            console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
          }).success(function(data, status, headers, config) {

            console.log(data);
          });

        }
    };
    /* Datepicker config */
    $scope.showWeeks = true;
    $scope.minDate = new Date();
    $scope.open = function($event) {
        $event.preventDefault();
        $event.stopPropagation();
        $scope.opened = true;
    };
    $scope.dateOptions = {
        'year-format': "'yy'",
        'starting-day': 1
    };
    $scope.format = 'MMM d, yyyy';
})
.controller('IndexCtrl', function ($scope) {

})

这样做我可以使用我的子控制器中的所有功能 但由于碰撞问题,我不太喜欢。 由于您不能使用服务(您不能在服务中使用$ scope),其他替代方法可能是制定其他指令或将代码放在运行块中 但是使用父控制器是完全相同的 你怎么看?

更新

您如何看待这种方法?

//outside of angular stauff
function MyTest(){
    this.testScope = function(){
        console.log('It works');
    }
}

//inside a controller
$scope.ns = new MyTest();

//in the view
<p ng-click="ns.testScope()">ppp</p>

RIUPDATE 这似乎是最好的选择:)

MyTest.call($scope);

4 个答案:

答案 0 :(得分:6)

考虑这篇文章描述的方法:Extending AngularJS Controllers Using the Mixin Pattern

不是将方法复制出服务,而是创建包含这些方法的基本控制器,然后在派生控制器上调用extend以将它们混合在一起。来自帖子的示例:

function AnimalController($scope, vocalization, color, runSpeed) {

    var _this = this;

    // Mixin instance properties.
    this.vocalization = vocalization;
    this.runSpeed = runSpeed;

    // Mixin instance methods.
    this.vocalize = function () {
        console.log(this.vocalization);
    };

    // Mixin scope properties.
    $scope.color = color;

    // Mixin scope methods.
    $scope.run = function(){
        console.log("run speed: " + _this.runSpeed );
    };
}

现在我们可以将AnimalController混合到DogController中:

function DogController($scope) {

    var _this = this;

    // Mixin Animal functionality into Dog.
    angular.extend(this, new AnimalController($scope, 'BARK BARK!', 'solid black', '35mph'));

    $scope.bark = function () {
        _this.vocalize(); // inherited from mixin.
    }
}

然后在我们的模板中使用DogController:

<section ng-controller="DogController">
    <p>Dog</p>

    <!-- Scope property mixin, displays: 'color: solid black' -->
    <p ng-bind-template="color: {{ color }}"></p>

    <!-- Calls an instance method mixin, outputs: 'BARK BARK!' -->
    <button class="btn" ng-click="bark()">Bark Dog</button>

    <!-- Scope method mixin, outputs: 'run speed: 35mph' -->
    <button class="btn" ng-click="run()">Run Dog</button>
</section>

此示例中的控制器都在全局空间中,并包含在标记中,如下所示。

<script type="text/javascript" src="lib/jquery.js"></script>
<script type="text/javascript" src="lib/angular.js"></script>
<script type="text/javascript" src="app/controllers/animal-controller.js"></script>
<script type="text/javascript" src="app/controllers/dog-controller.js"></script>
<script type="text/javascript" src="app/controllers/cat-controller.js"></script>
<script type="text/javascript" src="app/app.js"></script>

我没有测试过,但我不明白为什么以下内容不起作用:

var myApp = angular.module('myApp', [])

.controller('AnimalController', ['$scope', 'vocalization', 'color', 'runSpeed', function ($scope, vocalization, color, runSpeed) { /* controller code here */}]);

.controller('DogController', ['$scope', '$controller', function($scope, $controller) {
    var _this = this;

    // Mixin Animal functionality into Dog.
    angular.extend(this, $controller('AnimalController', {
         $scope: scope,
         vocalization: 'BARK BARK!', 
         color: 'solid black', 
         runSpeed:'35mph' 
    }));

    $scope.bark = function () {
        _this.vocalize(); // inherited from mixin.
    }
}]);

请参阅:docs for $ controller service

答案 1 :(得分:3)

你想要的是可怕的。

您不希望您的控制器彼此了解任何事情,更不用说能够访问另一个人的功能了。您可以使用服务来实现这一目标。至于使用指令,不确定你想要发生什么。

至于你的第二件事,你可以轻松地做到这一点

.service('MyTestService', function(){
    return {
       testScope: function(){
           console.log('It works');
       }
    };
})

.controller('MyController', ['$scope', 'MyTestService', function($scope, MyTestService){
   $scope.testScope = MyTestService.testScope;
}])

并在您看来:

<p ng-click="testScope()">ppp</p>

答案 2 :(得分:0)

我最终得到了:

//service
.service('PostUploader',function($upload){
        var that = this;
        var fileReaderSupported = window.FileReader !== null;
        this.notify = null;
        this.success = null;
        this.showAlert = false;
        this.avatar = '';
        this.onFileSelect = function($files) {
            var $file = $files[0];
            var filename = $file.name;
            this.avatar = filename;
            var isImage = /\.(jpeg|jpg|gif|png)$/i.test(filename);
            if(!isImage){
                this.showAlert = true;
                return;
            }
            this.showAlert = false;
            if (fileReaderSupported && $file.type.indexOf('image') > -1) {
                var fileReader = new FileReader();
                fileReader.readAsDataURL($file);
                fileReader.onload = that.notify;
            }
            $upload.upload({
                url :'/api/post/upload',
        method: 'POST',
        headers: {'x-ng-file-upload': 'nodeblog'},
        data :null,
        file: $file,
        fileFormDataName: 'avatar'
            })
            .success(that.success)
            .progress(function(evt) {

            })
            .error(function(data, status, headers, config) {
                throw new Error('Upload error status: '+status);
            })

        };
        this.closeAlert = function() {
            this.showAlert = false;
        };
    })    

//controller
 /* Uploader post */
        $scope.dataUrl = null;
        $scope.avatar = PostUploader.avatar;
        $scope.showAlert = PostUploader.showAlert;
        $scope.onFileSelect = PostUploader.onFileSelect;
        $scope.closeAlert = PostUploader.closeAlert;
        PostUploader.notify = function(e){
            $timeout(function() {
                $scope.dataUrl = e.target.result;
            });
        };
        PostUploader.success = function(data, status, headers, config) {
           $timeout(function() {
                $scope.post.avatar = data.url;
            });
        }
        $scope.$watch('avatar',function(newVal, oldVal){
            if(newVal) { 
                $scope.avatar = newVal;
            }  
        }); 
        $scope.$watch('showAlert',function(newVal, oldVal){
            $scope.showAlert = newVal;
            $scope.dataUrl = null;
        }); 

我这样做是因为我要在创建帖子和编辑帖子中做同样的事情,但总而言之 我有相同的重复代码! :)

唯一的好处是代码逻辑较少。

答案 3 :(得分:0)

显而易见但很出色的解决方案(可能是)

(function(window, angular, undefined) {
                'use strict';
                angular.module('ctrl.parent', [])
                    .run(function ($rootScope) {
                        $rootScope.test = 'My test'   
                        $rootScope.myTest = function(){
                            alert('It works');
                        }
                });
            })(window, angular);
            angular.module('app',['ctrl.parent'])
                .controller('ChildCtrl', function($scope){

            });

它既简单又干净,没有任何缺点(它不是全球性的)

更新

'use strict';
                (function(window, angular, undefined) {
                    'use strict';
                    angular.module('ctrl.parent', [])
                        .controller('ParentController',function (scope) {
                            scope.vocalization = '';
                            scope.vocalize = function () {
                                console.log(scope.vocalization);
                            };
                    });
                })(window, angular);
                angular.module('app',['ctrl.parent'])
                    .controller('ChildCtrl', function($scope,$controller){
                    angular.extend($scope, new $controller('ParentController', {scope:$scope}));
$scope.vocalization = 'CIP CIP';
                });

只是有点整洁,它工作CIP CIP :)