【问题标题】:I am unable to get $apply inside $watch to work我无法让 $apply 在 $watch 中工作
【发布时间】:2014-05-14 20:38:42
【问题描述】:

我有一个与服务器通信并返回scope.dbInsertId 的上传文件指令。我想看这个,然后用这个值更新 ng-model。我无法使用$apply 让它工作。这是我的代码:

            scope.$watch('dbInsertId', function(newValue, oldValue) {
                if (newValue)
                    scope.$apply(function() {
                        scope.ngModel = scope.dbInsertId;
                    });
                    console.log("I see a data change!"); 
                    return ngModel.$modelValue;
            }, true);

我的代码错了吗?

【问题讨论】:

  • 你试过 scope.$apply
  • 抱歉,这里打错了。我确实尝试过scope.$apply 并且确实有效..
  • second - 删除 apply 并将您的代码放入 watch 函数中,在所有 watch 迭代中应用触发
  • 尝试将您的指令 ng-model 与父范围变量 $scope.someVar 绑定 - 在控制器中
  • 如果你想在指令中使用父作用域,请使用:scope: true :) 但我认为,所有指令都应该有自己的作用域

标签: angularjs scope angularjs-directive angularjs-scope watch


【解决方案1】:

我对你的问题的回答

<div ng-app="app">
    <div ng-controller="MyController">

        <form name="someForm">
            <div this-directive ng-model="theModel"></div>
            <div>theModel='{{ theModel }}'</div>
        </form>

     </div>
</div>

var app = angular.module('app', []);
app.controller('MyController', function($scope,$rootScope,$log) {

    $scope.theModel = '';

    $scope.$watch('theModel',function(newVal,oldVal){
        $log.info('in *MyController* model value changed',newVal,oldVal);
    });
});

app.directive('thisDirective', function($compile, $timeout, $log) {

    return {
        scope: {
            ngModel: '='
        },
        require: 'ngModel',
        template: '<input type="text" ng-model="ngModel" /><div child-directive ng-model="ngModel"></div>',

        link: function(scope, element, attrs, ngModel) {

        }, // end link
    } // end return

});

app.directive('childDirective', function($compile, $timeout, $log) {
    return {
        scope: {
            ngModel: '='
        },
        template: '<input type="text" ng-model="ngModel" />',
        require: 'ngModel',

        link: function(scope, element, attrs, ngModel) {

        },

    } // end return
});

jsfiddle.net/dXL4w/3

【讨论】:

  • 嗨 KolleY,我尝试将范围更改为隔离并将 compile 更改为 template。当我们在文本框中键入时绑定有效,但是当子指令的模型从 $watch 更改时,父指令中的范围不会更新。发生这种情况时,控制台会显示来自子指令的 I see a data change! 消息,但不会显示应该根据控制器设置显示的 *MyController* model value changed 消息。所以这意味着当子指令的作用域值动态改变时,父指令的作用域是不知道的。 :(
  • 可能是您忘记将控制器变量绑定到第一个指令?
  • 嗨 KolleY,我终于让它工作了。在我的应用程序中,我的子指令有一个控制器,它定义了$scope.dbInsertId。当我在子指令中有scope.$apply(或)scope.$watch 时,虽然子指令中的 ng-model 正在更新,但它并没有更新父指令中的范围。但是,一旦我将 $apply 方法添加到子指令控制器本身的 $scope.dbInsertId 中,每次 dbInsertId 更改时,它都会更新子指令和父指令的范围。
  • 终于成功了!唷...我被困在这两天了。我很高兴它可以工作,但仍然想知道为什么当我在子指令而不是控制器中使用 $apply 时,它没有与父范围绑定。对我来说太神奇了.. :) 非常感谢 KolleY。我现在也更喜欢我的代码,因为我使用模板而不是编译,并且为指令提供了独立的范围。谢谢你指导我..
  • 关于 JSON 请求:角度使用承诺,只需将您的数据放入模型中,模型应该随处更改。示例: someAjaxService.query({id: 'blabla'}).$promice.then(function(data){ $scope.model = data; });是异步请求,数据加载后应该会显示出来。
【解决方案2】:

你需要scope:

scope.$watch('dbInsertId', function(newValue, oldValue, scope) { // here
    if (newValue)
        scope.$apply(function() {
            scope.ngModel = scope.dbInsertId;
        });
        console.log("I see a data change!"); 
        return ngModel.$modelValue;
}, true);

【讨论】:

  • 我尝试添加scope。但是父指令不知道对子指令所做的更改。
  • 嗨,阿什什,感谢您的意见。出于某种原因,当我在子指令中使用 $apply 时,它不起作用,但是一旦我在子指令的控制器中添加了 $apply 方法,该控制器在 Ajax 请求之后更新了 dbInsertId,它就起作用了。它终于起作用了。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2020-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-02
  • 2015-05-20
  • 2015-10-22
  • 2023-03-24
相关资源
最近更新 更多