简体   繁体   English

在ngDialog中提交表单后,角度视图不会更新范围更改

[英]Angular view not updating on scope change after form submit in ngDialog

I'm new to Angular and I'm attempting to build a robust todo app for learning purposes. 我是Angular的新手,我正在尝试为学习目的构建一个强大的todo应用程序。 There's probably something basic I'm doing wrong, but can't figure it out. 可能有一些基本的我做错了,但无法搞清楚。 I assume it's something with the way I have my controllers and templates configured. 我认为这与我配置控制器和模板的方式有关。 I've tried some of the recommendations found in similar questions but none that solve my issue. 我尝试过在类似问题中找到的一些建议,但没有一个可以解决我的问题。 I've tried using $scope.$apply() but I get the "apply/digest already in progress" error. 我已经尝试过使用$scope.$apply()但我得到了“apply / digest has in progress”错误。

I'm using ngRoute so when someone goes to /profile it calls the profileController and loads in templates/profile.html . 我正在使用ngRoute,所以当有人去/profile时调用profileController并加载templates/profile.html This controller doesn't really do anything other than setup the current user and attach to $rootScope . 除了设置当前用户并附加到$rootScope之外,该控制器实际上没有做任何其他事情。 Inside of the profile view I have a nested controller called listController . 在配置文件视图中,我有一个名为listController的嵌套控制器。 I'm passing in the List resource to listController to make http requests. 我将List资源传递给listController以发出http请求。 Everything is working correctly as far as routing and the get/post requests. 就路由和get / post请求而言,一切正常。

Here's a simplified example of my controller: 这是我的控制器的简化示例:

var myApp = angular.module('todo', ['ngRoute', 'ngResource'])
    // config stuff...
    .controller('listController', ['$scope', 'List', 'ngDialog', function ($scope, List, ngDialog) { 
        // This correctly returns all lists for the current user
        $scope.lists = List.query();

        // Open modal form function
        $scope.openModal = function () {
            ngDialog.open({
                template: 'templates/partials/new-list.html',
                className: 'ngdialog-theme-default'
            });
        };

        $scope.createList = function () {
            List.save({}, {
                name: $scope.list.name,
                description: $scope.list.description
            }).$promise.then(function(result) {
                $scope.lists.push(result);
            });
        };
    }]);

Here's the relevant part of templates/profile.html which correctly displays all lists retrieved from List.query() : 这是templates/profile.html的相关部分,它正确显示从List.query()检索的所有列表:

<div class="todo-sidebar" ng-controller="listController">
    <h3>Your lists <a href="#" ng-click="openModal()"><span>New list</span></a></h3>
        <ul>
            <li ng-repeat="list in lists">
                <a href="#"><span class="list-name">{{list.name}}</span></a>
        </li>
    </ul>
</div>

The problem is when I call the createList function from inside my templates/partials/new-list.html partial: 问题是当我从templates/partials/new-list.html partial中调用createList函数时:

<div class="dialog-contents" ng-controller="listController">
    <h3>New list</h3>
    <form ng-submit="createList()">
        <div class="form-group">
            <label>Name</label>
            <input type="text" name="name" ng-model="list.name">
            <textarea name="description" ng-model="list.description" rows="10"></textarea>
            <button type="submit" class="button">Create list</button>
        </div>
    </form>
</div>

The form posts correctly and I can see the new list in my database, but the view does not update in real-time. 表单正确发布,我可以在我的数据库中看到新列表,但视图不会实时更新。 When I console.log($scope) inside the promise it appears that my new list has been added to the scope. 当我在promise中记录console.log($scope) ,我的新列表已经添加到范围中。

I have a feeling it's not best practice to attach a controller to multiple elements/templates, but I'm not sure how else to structure this. 我觉得将控制器连接到多个元素/模板并不是最好的做法,但我不确定如何构建它。

Okay so after a little research I think I have a solution for you. 好的,经过一番研究后,我想我有一个解决方案。 So what is happening is that you're not resolving the close of the dialog box correctly. 所以发生的事情是你没有正确解析对话框的关闭。

For reference here is the link I used: 这里参考我使用的链接:

https://github.com/likeastore/ngDialog#api https://github.com/likeastore/ngDialog#api

Scope 范围

What you're dealing with here is a scope issue. 你在这里处理的是范围问题。 When the dialog box is opened up, it is generating a separate module with it's own controller. 打开对话框时,它会生成一个带有自己控制器的独立模块。 This controller's scope is a one-way binding, and will not be seen by the parent scope upon resolution. 此控制器的作用域是单向绑定,在解析时不会被父作用域看到。 So this is the why to the reason that your scope is not updating on the parent scope level. 因此,这就是为什么您的范围未在父范围级别更新的原因。

For the how, please see the next section regarding promises. 有关方法,请参阅有关承诺的下一部分。

Promises 承诺

To manage the scope at the parent level you're going to need something called a promise function, or in simpler terms a function that happens after the close of the dialog resolves fully. 要在父级别管理范围,您将需要一个称为promise函数的东西,或者更简单地说,一个在对话框关闭后完全解析的函数。 When dealing with the promise function there will be some kind of initial callback that allows you to pass data to the promise, and when you initialize the promise this is when you'll be able to access that data, which will then cooperate with the parent-level scope variables. 在处理promise函数时,会有某种初始回调,允许您将数据传递给promise,当您初始化promise时,这将是您能够访问该数据的时间,然后这些数据将与父级合作级别范围变量。

For this solution I have provided you a bit of updated code that might be helpful for you. 对于此解决方案,我已经为您提供了一些可能对您有所帮助的更新代码。

updated Code 更新的代码

If I'm understanding how your code works along with how the module works your updated functions should look something like the following. 如果我理解你的代码如何工作以及模块如何工作,你的更新函数应该如下所示。 I would give this a shot: 我会试一试:

var myApp = angular.module('todo', ['ngRoute', 'ngResource'])
// config stuff...
.controller('listController', ['$scope', 'List', 'ngDialog', function     ($scope, List, ngDialog) { 
    // This correctly returns all lists for the current user
    $scope.lists = List.query();

    // Open modal form function
    $scope.openModal = function () {
        var dialog = ngDialog.open({
            template: 'templates/partials/new-list.html',
            className: 'ngdialog-theme-default',
            controller : function($scope){  
                $scope.createList = function(){
                    dialog.close($scope.list); // where data is the list data
                };
            }
        });
        dialog.closePromise.then(function(data){
            // at this point data is your list and then you can update the value as you see with like normal
            List.save({}, {
               name: $scope.list.name,
                description: $scope.list.description
            }).$promise.then(function(result) {
               $scope.lists.push(result);
            });
        });
    };
}]);

Again this is just a rough template for what you'd need to do, but this is how you would implement it nonetheless. 对于您需要做的事情,这只是一个粗略的模板,但这仍然是您实现它的方式。

I hope this helps, please ask if you have any more questions. 我希望这有帮助,请问你是否还有其他问题。

You're dealing with a $scope issue I think. 您正在处理我认为的范围问题。 The values are there, but you're not referencing what you think you are. 价值观在那里,但你没有参考你的想法。 Referencing the "lists" via controllerAs, like so... 通过controllerAs引用“列表”,就像这样......

<li ng-repeat="list in MyController.lists"> 

should fix your problem. 应该解决你的问题。

Hope that helps. 希望有所帮助。

This will explain it far better than I will be able to. 这将解释它比我能够做得更好。 https://github.com/angular/angular.js/wiki/Understanding-Scopes#ngRepeat https://github.com/angular/angular.js/wiki/Understanding-Scopes#ngRepeat

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM