当前位置: 首页 > 面试题库 >

AngularJS-如何强制范围更新(对数组项的承诺)

鲁烨
2023-03-14
问题内容

我已经在Angular中创建了一个如下所示的控制器(为简洁起见进行了编辑):

function AppCtrl($scope, $http, $location, $dataService) {
    $scope.projects = $dataService.data.projects;
}

正确加载了$scope.projects我的$dataService服务中的承诺。

app.service('$dataService', function($q, $http, $location, $rootScope) {
    var dataService = this; //Provides access 'this' inside functions below
    var projectsDeferred = $q.defer();

    $http.get('/api').success(function(data, status, headers, config) {
        projectsDeferred.resolve(data.projects);
    }).error(function(err) {
        projectsDeferred.reject(err);
    });

    this.data = {projects: projectsDeferred.promise};

    //UPDATE FUNCTION
    function updateObjectInArray(array, object, newData) {
        for(i in array) {
            if(array[i] == object) {
                if(newData != undefined) {
                    array[i] = newData;
                } else {
                    return array[i];
                }
            }
        }
        return undefined;
    }


    this.updateProject = function(project, updateData) {
        $http.put('/api/projects/' + project._id, updateData)
            .success(function(data, status, headers, config) {
            updateObjectInArray(dataService.data.projects.$$v, project, data);
        }).error(function(data, status, headers, config) {});
    };

});

我创建了另一个看起来像这样的控制器,该控制器根据当前URL从项目数组中选择一个项目:

function ProjectCtrl($scope, $route) {
    //Getting the current project from the array of projects
    $scope.project = $scope.projects.then(function(projects) {
        for(i in projects) {
            if(projects[i]._id == $route.current.params.projectId) {
                return projects[i];
            }
        }
    });
}

当我尝试运行我的updateObjectInArray()功能(我的成功$http.put()要求),我$scope.projectsAppCtrl正确更新(项目的阵列),但我$scope.projectProjectCtrl

更新。我可以登录array[i]的内部updateObjectInArray()功能,它会记录正是我期待的,我可以登录$scope.projectsAppCtrl,它会相应地更新,但是当我尝试登录$scope.project我的ProjectCtrl控制器,它
不会 随之更新。

我以为原因是因为必须调用$rootScope.$apply()$rootScope.$digest()更新了其中的array[i]对象之后updateObjectInArray(),但是出现的错误$digest is already in progress

我该怎么做才能确保$scope.project阵列中的商品在我的商店中得到更新ProjectCtrl?我需要为此解决新的承诺吗?


问题答案:

一旦projects被加载,你使用该数组中的项目之一projects[i],让我们从理论上假设它的对象0x1在内存中。问题在于,当加载新项目(假设0x2)并更新数组时,您将更改位于数组位置(0x1)的对象,但$scope.project仍引用现在废弃的对象0x1。您不能只在数组中更改它,而必须对其进行修改,因此您无需重新绑定$scope.project变量。

最好的解决方案是 更改 array[i] = newData angular.extend(array[i], newData)。这样,您将只更改array [i]的所有属性,并且$scope.project指向内存中相同对象的指针将被更新。

反正,我也相信你可能要 改变 if(array[i] == object) { if(array[i]._id === object._id) {和你 平等的比较(==)_以 _严格相等比较(===。这if更适合您的原因,因为新创建的对象与旧对象不同。



 类似资料:
  • 问题内容: 在父控制器作用域中,我已定义将其设置为“ x”。然后在子范围中,我使用ngModel 进行了定义: 加载页面后,会按预期正确设置为“ x”。当我选择“ y”时,在CtrlB中$ scope会按预期给出“ y”。 但是,当我检查的范围(使用AngularJS的batarang),它给“X”。 jsFiddle:http : //jsfiddle.net/sudhh/GGKjp/2/ 预览

  • 问题内容: 经过数小时令人沮丧的搜索,我觉得我需要在这里提交我的问题。如果此问题以前得到过解答,我事先表示歉意,但是到目前为止,我的搜索都没有帮助。所以这是我的问题: 我的JavaScript代码正在创建一个对象,该对象由AngularJS修改和监视。对于某些事件(例如加载对象的先前设置),我希望从范围之外更改该对象的属性。问题是输入不会改变… 这是我希望如何执行这些更改的示例: HTML代码:

  • 问题内容: 我有两个控制器,一个封装在另一个中。现在,我知道子范围从父范围继承属性,但是有没有办法更新父范围变量?到目前为止,我还没有遇到任何明显的解决方案。 在我的情况下,我在表单中有一个日历控制器。我想从父范围(即表单)更新开始日期和结束日期,以便表单在提交时具有开始日期和结束日期。 问题答案: 您需要在父作用域中使用一个对象(不是原始对象),然后就可以直接从子作用域中更新它 上级: ctrl

  • 问题内容: 如何从其父范围调用在子范围中定义的方法? http://jsfiddle.net/wUPdW/ 问题答案: 您可以从父母到孩子使用: 工作jsfiddle:http : //jsfiddle.net/wUPdW/2/ 更新 :还有另一个版本,耦合性更低,更易于测试: jsfiddle:http : //jsfiddle.net/uypo360u/

  • 问题内容: 我尝试编写一个小指令,以将其内容包装在另一个模板文件中。 这段代码: 应该有以下输出: 因为布局“默认”具有以下代码: 这里的指令代码: }); 我的问题: 例如,当我在模板(在布局模板中或在布局标签内部)中使用范围变量时。它只是最初工作。如果我更新变量,则该指令不再更新。整个链接功能只会被触发一次。 我认为,AngularJS不知道,该指令使用范围变量,因此不会被更新。但是我不知道如

  • 问题内容: 我有一个numpy数组,我想强制将小于零的每个元素都设为零,并将每个大于255的元素强制降低到255。 例如。x =(-1,7,255,299)=>(0,7,255,255) 是否有一个不太复杂的单行代码可以完成此任务? 问题答案: 答案是numpy.clip 关于标题中的问题:不可以。您可以使用向量化将lambda函数应用于每个元素,但这并不是最佳选择。