AngularJS 通用控制器功能 - 在需要的地方混合或在 $rootScope 上定义? [英] AngularJS common controller functionality - mix-in where needed or define on $rootScope?

查看:22
本文介绍了AngularJS 通用控制器功能 - 在需要的地方混合或在 $rootScope 上定义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 AngularJS 的 v1.2.0 rc2,想知道为多个控制器提供通用功能的最佳方法是什么.

我想在所有编辑模型的控制器中使用以下验证函数:

$scope.canSave = function (formController) {返回 formController.$dirty &&formController.$valid;};$scope.validationClasses = 函数(模型控制器){返回 {有错误":modelController.$invalid &&modelController.$dirty,已成功":modelController.$valid &&模型控制器.$dirty};};

我想让我的控制器保持干燥,所以我定义了一个工厂,如下所示:

angular.module('myModule', []).factory('validationFactory', [function () {返回 {验证类:函数(模型控制器){返回 {有错误":modelController.$invalid &&modelController.$dirty,已成功":modelController.$valid &&模型控制器.$dirty};},isFormValid: 函数 (formController) {返回 formController.$dirty &&formController.$valid;}};}]);

最初,我只是将工厂混合到需要它的控制器中,如下所示:

$scope.canSave = validationFactory.isFormValid;$scope.validationClasses = validationFactory.validationClasses;

但我意识到我可以将它们添加到模块的 run 方法中的 $rootScope 中,如下所示:

angular.module('myModule', []).跑(['$rootScope','验证工厂',函数($rootScope,validationFactory){$rootScope.canSave = $rootScope.canUpdate = validationFactory.isFormValid;$rootScope.validationClasses = validationFactory.validationClasses;}]);

现在它们可以在每个控制器中随意使用,而且接线工作更少.

在视图模板中使用的函数如下:

<div class="form-group" ng-class="validationClasses(questionForm.question)"><label for="questionText" class="control-label">Text</label><input type="text" ng-model="question.text" name="question"id="questionText" class="form-control" required/><span ng-show="questionForm.question.$error.required"class="help-block">问题文本是必需的</span>

...<div class="form-group" ng-switch on="action"><button type="button" ng-switch-when="New" ng-click="save()"ng-disabled="!canSave(questionForm)"class="btn btn-primary">保存</button><button type="button" ng-switch-default ng-click="update()"ng-disabled="!canUpdate(questionForm)"class="btn btn-primary">更新</button><button type="button" ng-click="cancel()"class="btn btn-default">取消</button>

</表单>

我的问题是:

  1. 我应该避免向 $rootScope 添加常用函数吗?如果是这样,有哪些陷阱?
  2. 仅在必要时混合使用通用功能是否更好?
  3. 是否有更好的方法来实现相同的结果?

更新的解决方案

我选择使用自定义指令,而不是向 $rootScope 添加函数,因为 $rootScope 有一种令人讨厌的气味.

我创建了自定义属性 validation-class-for="<input.name>"disabled-when-invalid 所以标记如下所示:

<label for="questionText" class="control-label">Text</label><input type="text" ng-model="question.text" name="question"id="questionText" class="form-control" required/><span ng-show="questionForm.question.$error.required"class="help-block">问题文本是必需的</span>

<button type="button" ng-click="save()" disabled-when-invalidclass="btn btn-primary">保存</button>

指令只需要一个表单祖先并观察一个函数来确定状态.

angular.module('myModule', []).directive('validationClassFor', function () {返回 {要求:'^形式',链接:函数(范围、元素、属性、formController){范围.$watch(函数(){var field = formController[attributes.validationClassFor];if (field.$invalid && field.$dirty) {element.removeClass('has-success').addClass('has-error');} else if (field.$valid && field.$dirty) {element.removeClass('has-error').addClass('has-success');} 别的 {element.removeClass('has-error').removeClass('has-success');}});}};}).directive('disabledWhenInvalid', function () {返回 {要求:'^形式',链接:函数(范围、元素、属性、formController){范围.$watch(函数(){返回 formController.$dirty &&formController.$valid;}, 函数(值){element.prop('禁用', !value);});}};});

现在也不需要验证工厂了.

解决方案

你如何使用这个validationFactory?是改变提交按钮的外观吗?如果是这样,我建议为按钮本身创建自定义组件,并让组件引用验证工厂.

I am using v1.2.0 rc2 of AngularJS and want to know what is the best method to provide common functionality to multiple controllers.

I have the following validation functions that I want to use in all controllers that edit a model:

$scope.canSave = function (formController) {
    return formController.$dirty && formController.$valid;
};

$scope.validationClasses = function (modelController) {
    return {
        'has-error': modelController.$invalid && modelController.$dirty,
        'has-success': modelController.$valid && modelController.$dirty
    };
};

I want to keep my controllers DRY so I defined a factory as follows:

angular.module('myModule', [])
    .factory('validationFactory', [function () {
        return {
            validationClasses: function (modelController) {
                return {
                    'has-error': modelController.$invalid && modelController.$dirty,
                    'has-success': modelController.$valid && modelController.$dirty
                };
            },
            isFormValid: function (formController) {
                return formController.$dirty && formController.$valid;
            }
        };
    }]);

Initially, I just mixed the factory into the controllers that needed it as follows:

$scope.canSave = validationFactory.isFormValid;

$scope.validationClasses = validationFactory.validationClasses;

But I realised I could add them to the $rootScope in the module's run method as follows:

angular.module('myModule', [])
    .run([
        '$rootScope',
        'validationFactory',
        function ($rootScope, validationFactory) {
            $rootScope.canSave = $rootScope.canUpdate = validationFactory.isFormValid;
            $rootScope.validationClasses = validationFactory.validationClasses;
        }]);

Now they are available in every controller indiscriminately and there is less wiring up to do.

The functions are used in the view templates as follows:

<form name="questionForm" novalidate>
    <div class="form-group" ng-class="validationClasses(questionForm.question)">
        <label for="questionText" class="control-label">Text</label>
        <input type="text" ng-model="question.text" name="question"
               id="questionText" class="form-control" required/>
        <span ng-show="questionForm.question.$error.required"
              class="help-block">Question text is required</span>
    </div>
    ...
    <div class="form-group" ng-switch on="action">
        <button type="button" ng-switch-when="New" ng-click="save()" 
                ng-disabled="!canSave(questionForm)" 
                class="btn btn-primary">Save</button>
        <button type="button" ng-switch-default ng-click="update()" 
                ng-disabled="!canUpdate(questionForm)" 
                class="btn btn-primary">Update</button>
        <button type="button" ng-click="cancel()"
                class="btn btn-default">Cancel</button>
    </div>
</form>

My questions are:

  1. should I avoid adding common functions to the $rootScope? if so, what are the pitfalls?
  2. is it better to mix-in common functionality only where necessary?
  3. is there a better way of achieving the same outcome?

Updated Solution

I opted to use custom directives instead of adding functions to the $rootScope which had a nasty smell about it.

I created custom attributes validation-class-for="<input.name>" and disabled-when-invalid so the markup looks like this:

<div class="form-group" validation-class-for="question">
    <label for="questionText" class="control-label">Text</label>
    <input type="text" ng-model="question.text" name="question"
           id="questionText" class="form-control" required/>
    <span ng-show="questionForm.question.$error.required"
          class="help-block">Question text is required</span>
</div>

<button type="button" ng-click="save()" disabled-when-invalid 
    class="btn btn-primary">Save</button>

The directives simply require a form ancestor and watch a function to determine state.

angular.module('myModule', [])
    .directive('validationClassFor', function () {
        return {
            require: '^form',
            link: function (scope, element, attributes, formController) {
                scope.$watch(function () {
                    var field = formController[attributes.validationClassFor];
                    if (field.$invalid && field.$dirty) {
                        element.removeClass('has-success').addClass('has-error');
                    } else if (field.$valid && field.$dirty) {
                        element.removeClass('has-error').addClass('has-success');
                    } else {
                        element.removeClass('has-error').removeClass('has-success');
                    }
                });
            }
        };
    })
    .directive('disabledWhenInvalid', function () {
        return {
            require: '^form',
            link: function (scope, element, attributes, formController) {
                scope.$watch(function () {
                    return formController.$dirty && formController.$valid;
                }, function (value) {
                    element.prop('disabled', !value);
                });
            }
        };
    });

Now there is no need for the validation factory either.

解决方案

How are you using this validationFactory? Is it to change the appearance of for submit buttons? If so, I'd suggest creating custom components for the buttons themselves, and have the component reference the validationFactory.

这篇关于AngularJS 通用控制器功能 - 在需要的地方混合或在 $rootScope 上定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆