AngularJS:attrs.$观察第一次后不开火

AngularJS:attrs.$观察第一次后不开火,angularjs,angularjs-directive,angularjs-scope,Angularjs,Angularjs Directive,Angularjs Scope,在小提琴中,如果您第一次单击submit按钮,请注意,正确聚焦。在随后的单击中,焦点不再设置 我注意到当submit()更改isFocused时,$observe回调没有被触发,所以我添加了一个blur侦听器来显式重置变量,但这也没有帮助 我如何使焦点集中在提交上 编辑:。改为使用$watch,因为我希望它能够处理任意表达式我认为您无法观察focusOn属性,因为它实际上不作为指令的属性存在。当您执行时,关注的实际上是您的指令名 请尝试以下方法: HTML <div ng-app='foo

在小提琴中,如果您第一次单击submit按钮,请注意,
正确聚焦。在随后的单击中,焦点不再设置

我注意到当
submit()
更改
isFocused
时,
$observe
回调没有被触发,所以我添加了一个
blur
侦听器来显式重置变量,但这也没有帮助

我如何使焦点集中在提交上


编辑:。改为使用
$watch
,因为我希望它能够处理任意表达式

我认为您无法观察
focusOn
属性,因为它实际上不作为指令的属性存在。当您执行
时,
关注的
实际上是您的指令名

请尝试以下方法:

HTML

<div ng-app='foo'>
    <form ng-controller='FormCtrl' ng-submit='submit()'>
        <input focus-on focused='isFocused' />
        <button>Submit</button>
    </form>
</div>
我创建了一个
focused
属性,将
isFocused
属性绑定到指令作用域(我可以将其命名为
focusOn
,但我想拥有
会很奇怪)

更新的JSFIDLE


更新:我将属性名称从
ng model
更改为
focused
,因此它更有意义。

如果您观看该元素,您会注意到当触发模糊回调时,
focus on
属性没有设置为false。原因是
blur
函数超出angular的范围,因此它不知道您在其内部所做的更改

要使angular了解更改,您需要将所有更改包装在对的调用中


对此不确定,因为我需要ng模型来表示表单字段中的实际值。比如说,当ng model='email'时,执行$scope.email=true是没有意义的。哦,我明白了。好的,您可以为属性选择另一个名称。我刚刚将属性名称更改为
聚焦
。现在更有意义了。我很清楚这个$apply的东西,但在我尝试其他东西时完全忽略了它。谢谢+1.斑点很好。尽管如此,我仍然不确定$observe方法是否是最好的,在我看来$broadcast/$on在更短、更易于维护的代码中提供了相同的结果。如果我错过了一个原因,我愿意相信@mikel我实际上偷了$observe这个东西,但看到我的最终解决方案是使用$watch:。我更喜欢不使用事件,因为我遇到过几个实例,当事情因为不匹配的事件字符串而无声地失败时。当变量未定义时,至少会看到错误。另外,我不想硬编码事件字符串,因为除了提交空表单之外,我还有其他原因需要关注字段。似乎不适合在这里使用事件,这很公平。不管怎么说,看到不同的方法很有趣。你可以看看这个实现是件好事,它似乎是实现ngBlur和ngFocus的好方法。
app.directive('focusOn', function () {
    return {
        scope: { focused: '=' },
        link: function(scope, element) {
            scope.$watch('focused', function (newValue) {
                console.log('$watch', newValue)
                if (newValue) {
                    element[0].focus();                    
                }
            });

            element.bind('blur', function () {
                scope.focused = false;
                scope.$apply(); // required so that the scope is updated correctly.
                console.log('blur');
            });
        }
    };
});

app.controller('FormCtrl', function ($scope) {
    $scope.submit = function () {
        $scope.isFocused = true;
        console.log('submit');
    };
});
element.bind('blur', function () {
    scope.$apply(function() {
        scope.isFocused = false;
        console.log('blur');
    });
});