【问题标题】:Updating data/state between directives in AngularJS在 AngularJS 中的指令之间更新数据/状态
【发布时间】:2013-12-28 05:22:25
【问题描述】:

这可能是一个愚蠢的问题,我可能无法很好地解释自己,但这里是……我有一个带有当前 HTML 标记的表单,请注意指令:

<input type="password" name="password1" id="password1" ng-model="user.plaintextPassword" equals="{{user.password2}}" required ng-trim="false" error-popover>
<label for="password1">Password 1</label>

<input type="password" name="password2" id="password2" ng-model="user.password2" equals="{{user.plaintextPassword}}" required ng-trim="false" error-popover >
<label for="password2">Password 2</label>

现在在这两个标签上我都有 AngularJS 指令。 equals 指令监视密码的两个值,如果它们匹配/不匹配,它会设置模型的有效性,如下所示:

   .directive('equals', function() {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function(scope, elm, attrs, ngModel) {
                if(!ngModel) {
                    return;    // do nothing if no ng-model
                }

                // watch own value and re-validate on change
                scope.$watch(attrs.ngModel, function() {
                    validate();
                });

                // observe the other value and re-validate on change
                attrs.$observe('equals', function () {
                    validate();
                });

                var validate = function() {
                    // values
                    var val1 = ngModel.$viewValue;
                    var val2 = attrs.equals;

                    // set validity
                    ngModel.$setValidity('equals', val1 === val2);
                    //console.log(ngModel);
                };
            }
        }

现在我有另一个指令,如果表单项无效,它会产生一个验证弹出窗口,这是在表单项的 keydown 或焦点上触发的(这里是一个编辑版本):

   .directive('errorPopover', function() {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function(scope, element, attrs, ngModel) {

                // validate on keydown and focus in input field
                element.on('keydown focus', function() {
                    scope.$evalAsync(function() {

                        var popoverOptions = {
                            'placement': (attrs.errorPopover) ? attrs.errorPopover : 'left',
                            'trigger': 'manual',
                            'content': setValidationText(attrs, ngModel)
                        };

                        // raise the error etc...
                    });
                });


                // hide popover when user leaves input
                element.on('blur', function() {
                    // do stuff
                });

                var setValidationText = function(attrs, ngModel) {
                    var errorText = '';

                    // lots going on here... and then
                    if(attrs.equals && ngModel.$error.equals === false) {
                        // add to the error text
                    }

                    return errorText;
                };
            }
        };

现在这不起作用,因为 ngModel 不同,而 equals 指令保持正确的有效性值 errorPopover 指令没有。因此该值可能为假,但在errorPopover 指令中,ngModel.$error.equals 始终保持为真。如何使用equals 指令确定的正确值更新errorPopover 指令?

请注意:我在寻求建议或推动正确的方向而不是代码示例......因为我不确定这是否是关于隔离范围或广播等......强>

【问题讨论】:

  • plunker 中的演示会有所帮助。无法使用控制台很难帮助解决问题
  • 在我看来 errorPopover 应该只关注模型有效性,而不是绑定到元素事件。

标签: javascript angularjs angularjs-directive angularjs-scope


【解决方案1】:

我认为你把这件事弄得太复杂了。指令主要用于 DOM 操作。在您的 equals 指令中,您只是在进行数据验证,因此控制器功能会更好。

您可以消除您的“等于”自定义指令,并在两个输入上添加 ng-change="validatePassword()" 代替它(如果您包含其他验证,您可能还希望在提交表单时调用此函数密码强度测试等逻辑)。然后在函数中进行比较检查很简单,如果两个变量不匹配,则显示您的弹出框。

您的弹出框似乎也太复杂了。我会尝试将 HTML 保留在您的 HTML 文件中,然后从您的控制器功能中控制显示/隐藏(或使用 ng-if)。我会将弹出窗口中的任何相关逻辑移至验证函数,或者如果它可在不同类型的验证中重用,则可能移至单独的函数中。因此,如果验证功能为真或假,您最终只是显示/隐藏 HTML 的一部分。这是一种易于遵循的模式,可以将您的 HTML 保持在一起。

希望这会让您朝着更简单的方向前进。

【讨论】:

    猜你喜欢
    • 2017-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-09
    • 2014-09-25
    • 1970-01-01
    • 2015-02-17
    相关资源
    最近更新 更多