Angular UI路由器:调用子状态控制器

时间:2016-05-31 19:52:50

标签: angularjs angular-ui-router

我一直在使用角度ui-router,一个问题不断出现。我希望你们中的一些人可以给我建议如何以干净,非黑客的方式解决这个问题。

考虑以下情况:

enter image description here

在左侧,我有一个带有联系人列表的侧面导航栏。点击联系人后,所选联系人的详细信息将显示在app.contacts.details状态。一旦我选择了联系人,标题中就会显示一些控件,例如。 "编辑"和"删除" (仅以它们为例,实际上这些动作更复杂)。

理想情况下,这些按钮只会调用detailStateController的函数,例如。 detailStateController.delete()删除当前选定的联系人,或detailStateController.edit()编辑所选联系人(您明白了)。当然这不起作用,因为编辑和删除按钮不在app.contacts.details州的视图内,因此detailStateController不在其范围内。

我知道这可以通过广播事件来解决,但我想尽可能避免使用事件。

你会如何解决这个问题?

非常感谢任何建议。

3 个答案:

答案 0 :(得分:1)

工厂是单身人士,可用于跨控制器共享数据和功能。你可以这样写:

app.factory("DataService", ["$http", function($http){
    var contacts = [];

    return {
        //sharing functions
        postItem: function(url, item) {
            return $http({
                url: url,
                method: 'POST',
                data: item
            });
        },
        putItem: function(url, item) {
            return $http({
                url: url,
                method: 'PUT',
                data: item
            });
        },
        deleteItem: function(url, item) {
            return $http({
                url: url,
                data: item,
                method: 'DELETE'
            });
        },
        setContacts = function(contacts) {
            contacts = contacts;
        },
        addContacts = function(contact) {
            contacts.push(contact);
        },
        deleteContact = function(contact) {
            var idx = this.contacts.indexOf(contact);
            contacts.splice(idx, 1);
        }
    };
}]);

然后,在你的控制器中:

app.controller("ContactDetailsCtrl", ["$scope", "DataService", function($scope, DataService){
    $scope.deleteContact = function() {
        DataService.deleteItem('path/to/delete', { contactId: 123 }).then(function(response) {
            //remove from client-side array once it's removed form db
            DataService.deleteContact(contact);
        }).catch(function(response){
            //an error occurred
        });
    }
}]);

答案 1 :(得分:0)

我已经离开了这种风格,只需从控制器和列表中处理所有内容。如果从详细控制器中删除项目或编辑父控制器中显示的字段,则最终还是必须更新列表控制器。当我按照你现在这样做的方式做这件事时,似乎我必须跳过很多额外的箍,这是因为一个控制器中的细节和另一个控制器中的列表。我通常只有一个list属性,它是我的控制器上的数组和当前行属性,它是显示的完整记录。然后我使用ng-if检查当前行并正确显示。单击一行时,我使用$ location.search来更新URL,并在启动时检查$ location搜索以进行深层链接。这导致单个控制器有点大,但它仍然小于2个控制器的总和。如果我只处理几个字段,我会在列表中包含所有字段。如果有大量数据,我会在更改列表中的当前项目以获取currentRow的数据并更新currentRow时进行服务调用。

答案 2 :(得分:0)

我个人喜欢在这种情况下创建以下结构。

路由器声明:

  • app.contacts.index - 用于包含详细信息/列表视图的工具栏
  • app.contacts.list - 列表
  • app.contacts.detail - 详情
  

控制器(对于每个州的resp):

function IndexCtrl($scope)
{
   $scope.contact = {}; // For containing the selected contact
   $scope.contacts = []; // List of contacts also on the parent view

   // Define Detail View functions here
   $scope.edit = Edit;
   $scope.delete = Delete;

   // Perform operations on $scope.contact/$scope.contacts
   function Edit() {}
   function Delete() {}
}

function DetailCtrl($scope)
{
    $scope.contact = $scope.$parent.contact = $scope.$parent.contacts[id]; // This way we work with the parent contact defined in IndexCtrl
}

function ListCtrl($scope, Contacts) 
{
    $scope.contacts = $scope.parent.contacts = Contacts.list(); // Contacts Service to retrieve the contact list
}