【问题标题】:angular js model relationships角度js模型关系
【发布时间】:2013-01-09 21:58:08
【问题描述】:

过去几天我一直在尝试 Angular JS,但我不知道如何处理模型之间的关系。

我正在处理的项目有一个用户模型和一个帐户模型。我在我的数据库中设置了每个帐户都有一个名为“ownedBy”的字段,该字段是对拥有该帐户的用户 ID 的外键引用。

在 Angular 中,我在名为 main.js 的文件中设置了以下内容

var myApp = angular.module('myApp', ['ngResource']);

var Users = myApp.factory('Users', function($resource) {
    var User = $resource('http://api.mydomain.ca/users/:id',
        {id:'@id'},
    {});
    return User;
});

var Accounts = myApp.factory('Accounts', function($resource) {
    var Accounts = $resource('http://api.mydomain.ca/accounts/:id',
        {id:'@id'},
    {});
    return Accounts;
});


function UsersCtrl($scope, Users) {
    $scope.users = Users.query();
}

function AccountsCtrl($scope, Accounts) {
    $scope.accounts = Accounts.query();
}

和下面的模板

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Angular Test</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <link rel="stylesheet" href="/bootstrap/css/bootstrap.min.css?v=2.2.1">
</head>
<body>
<div ng-app="myApp">
    <div ng-controller="UsersCtrl">
        <table class="table table-striped">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>First Name</th>
                    <th>Last Name</th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat="user in users">
                    <td>{{user.id}}</td>
                    <td>{{user.firstName}}</td>
                    <td>{{user.lastName}}</td>
                </tr>
            </tbody>
        </table>
    </div>
    <div ng-controller="AccountsCtrl">
        <table class="table table-striped">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Owned By</th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat="account in accounts">
                    <td>{{account.id}}</td>
                    <td>{{account.ownedBy}}</td>
                </tr>
            </tbody>
        </table>
    </div>
</div>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular-resource.min.js"></script>
<script src="/bootstrap/js/bootstrap.min.js?v=2.2.1"></script>
<script src="js/main.js"></script>
</body>
</html>

这是有效的。它从我的 REST 服务器中提取 JSON 资源并将其显示在表格中。我需要采取什么下一步才能最终得到一个显示用户及其帐号的表格? (相当于数据库JOIN?)对于一对多关系是否有不同的方法? (即……一个帐户有很多交易)

感谢您的帮助:)

【问题讨论】:

  • 您可以控制服务器返回的内容吗?在将模型与 Angular 绑定之前,您应该根据需要重新构建模型,而最好的位置是在您的服务器 api 中。
  • @BenFelda 使用 RESTful API,进行客户端连接很常见。
  • 我确实可以控制服务器返回的内容。但我认为最好将用户模型和帐户模型分开(标准化?)。您如何建议我让服务器返回数据?
  • 我会在服务器端构建对象{user: {account, account...}},这样客户端就可以获取数据并将其绑定到我的模型,然后只需调用一次服务器即可获取所有数据。跨度>
  • 我确实在这个帖子中回复了这个:stackoverflow.com/a/17055281/1558820

标签: javascript model-view-controller orm frameworks angularjs


【解决方案1】:

如果我需要 UI 中的关系,我会使用 js-data。该库通常非常优雅地处理关系和数据建模。即使您只是在寻找一个不错的 API 接口,我也发现它更易于使用。我更喜欢它而不是 ngResource。

在您的情况下,您将有一个用户模型和帐户模型

src/app/data/account.model.coffee

angular.module 'app.data' #this can be your module name
  .factory 'Account', (DS) ->
    DS.defineResource
      name: 'account'
      endpoint: 'accounts'
      relations:
        belongsTo:
          user:
            localKey: 'userId'
            localField: 'user'

src/app/data/user.model.coffee

angular.module 'app.data'
  .factory 'User', (DS) ->

    DS.defineResource
      name: 'user'
      endpoint: 'users'
      relations:
        belongsTo:
          account: #make sure this matches the 'name' property of the other model
            foreignKey: 'userId'
            localField: 'account'

【讨论】:

    【解决方案2】:

    $resource 不包含任何处理不由服务器处理的关系的方法,但使用$http 非常简单:

    module.factory( 'UserService', function ( $http, $q ) {
      return {
        get: function getUser( id ) {
          // We create our own promise to return
          var deferred = $q.defer();
    
          $http.get('/users/'+id).then( function ( user ) {
            $http.get('/accounts/'+user.id).then( function ( acct ) {
    
              // Add the account info however you want
              user.account = acct;
    
              // resolve the promise
              deferred.resolve( user );
    
            }, function getAcctError() { deferred.reject(); } );
          }, function getUserError() { deferred.reject(); } );
    
          return deferred.promise;
        }
      };
    });
    

    然后在您的控制器中,您可以像使用任何其他承诺一样使用它:

    UserService.get( $scope.userId ).then( function ( user ) {
      $scope.user = user;
    });
    

    它适用于您的模板!

    <div>
        User: "{{user.firstName}} {{user.lastName}}" with Acct ID "{{user.acct.id}}".
    </div>
    

    【讨论】:

    • 感谢您的回答,看来它会起作用。我认为 $resource 包装了 $http 并且应该在某些方面更胜一筹。如果有的话,我应该在什么时候使用 $resource?
    • 确实 包装了 $http 和 $resource 对于非常典型的 REST 用例来说非常棒。但是,一旦您冒险超越基础知识,$resource 就会开始妨碍您。例如,您可以使用 $resource 来解决这个问题,但它更加棘手和混乱。最常见的抱怨之一(包括我自己的)是 $resource 没有返回承诺,这很容易。
    • 你可以使用承诺 $http 返回而不是 $q ——也就是说,你使用 $q 有什么原因吗?另外,返回“deferred”与返回“deferred.promise”有区别吗?我问是因为我看到 $q API 文档使用后者。我没有尝试运行你的代码(还)。
    • @MarkRajcok 返回deferred 而不是deferred.promise 是一个错字。 :-) 我修好了它。只要对then 的内部调用返回 修改后的对象,我们可能会从$http 返回promise,而不是从$q 中返回我们自己的promise。不过,我不是 100% 确定。我都使用了这种方式,因此我不必对其进行测试,因此幕后发生的事情会更清楚。
    • @AlexMcMillan 在这种情况下,不。但我假设在大多数情况下,服务会希望以某种方式处理错误,而不是在(可能至少)多个控制器中重复处理它。所以我在这里选择了冗长。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    • 1970-01-01
    • 2022-01-12
    • 2017-11-28
    • 2012-05-30
    • 1970-01-01
    相关资源
    最近更新 更多