AngularJS在控制器之间传递数据库数据

时间:2016-09-05 19:41:33

标签: php angularjs ionic-framework

我对如何将控制器中加载的数据库数据传递给另一个控制器感到困惑。

我从服务器加载一些列表项,并在每个项目上单击我想根据其ID在另一个屏幕上打开该项目的详细信息。

我读了一些关于提供服务或使用$ rootScope的问题,但应尽可能避免使用$ rootScope。

在我的案例中,这样做的最佳方法是什么,你能告诉我怎么做吗?我应该在服务中加载数据还是在我的情况下最简单的方法?

使用第一个控制器列出项目:

<div class="item item-body list-container" id="temporada2016-list-item-container4" ng-model="item_id" ng-repeat="x in items" item="x" href="#/x/{{x.ID}}" ng-click="open_item(x)" ng-show="news_list">

        <div id="temporada2016-markdown7" style="margin-top:0px;color:#666666;">
            <h2 style="color:#008BBB;">{{ x.TITLE }}</h2>
        </div>

</div>

第一个控制器

.controller('temporada2016Ctrl', ['$scope', '$http', function ($scope, $http) {

$scope.active_news_btn = true;
$scope.search_news = true;
$scope.news_list = true;
$scope.albums_list = false;

$http.get("http://localhost/select-news.php").then(function(response){

    console.log(response);
    console.log(JSON.stringify(response));

    $scope.items = response.data;

});

$scope.open_item = function(x){

    //alert("Item id: " + x.ID);
    $http.post("http://localhost/select-news-by-id.php", {'item_id': x.ID}).then(function(response){

    console.log(response);
    console.log(JSON.stringify(response));

    $scope.all = response;
    $scope.title = response.data[0].TITLE;
    $scope.body = response.data[0].BODY;


 });


 }
}])

第二个屏幕(详细信息)使用第二个控制器,我想加载相同的标题和新闻主体

<ion-view title="Detalhes" id="page4" style="background-color:#FFFFFF;">
  <ion-content padding="true" class="has-header">
    <h3 id="detalhes-heading1" style="color:#008BBB;font-weight:600;font-style:italic;">{{title}}</h3>
    <div id="detalhes-markdown3" style="color:#000000;">
        <p>{{body}}</p>
    </div>
    <form id="detalhes-form4" class="list">
        <button id="detalhes-button6" style="color:#008BBB;text-align:left;border-radius:9px 9px 9px 9px;" class="button button-calm  button-clear icon ion-ios-heart-outline like_btn"></button>
        <label class="item item-input" id="detalhes-textarea1">
            <span class="input-label"></span><textarea placeholder=""></textarea>
        </label>
    </form>
    <button id="detalhes-button17" style="color:#FFFFFF;" class="button button-positive">Comment</button>
  </ion-content>
</ion-view>

第二个控制器

.controller('detalhesCtrl', ['$scope', '$stateParams', function ($scope, $stateParams) {


}])

PHP

<?php 

include_once('conn.php');

$data = json_decode(file_get_contents("php://input"));

if(property_exists($data, 'item_id')){

$item_id = $data->item_id;
$sql = $mysqli->query("SELECT * FROM news WHERE id = '".$item_id."'");

if($sql->num_rows > 0){
        while($row = $sql->fetch_array(MYSQLI_BOTH)){
            $registro = array(
                "ID" => $row['id'],
                "TITLE" => $row['title'],
                "BODY" => $row['body']
                );

        $retorno[] = $registro;

        }   
}

    $mysqli->close();
    $retorno = json_encode($retorno);
    echo $retorno;

}

?>

3 个答案:

答案 0 :(得分:1)

app-config

$stateProvider
      .state('master', {
        url: '/master',
        templateUrl: 'views/master.html',
        controller: 'MasterCtrl',
        data: {
          someThingToPassToMasterState: false
        }
      })
      .state('details', {
        url: '/details',
        data : {
          somethingToPassToDetailsState: false
        },
        templateUrl: 'views/details.html',
        controller: 'DetailsCtrl'
      });

然后在你的MasterCtrl

$scope.onClick = function(obj) {
  var dataToPass = {};
  dataToPass.obj = obj;
  dataToPass.somethingElse = 'blah blah';
  $state.go('details', {somethingToPassToDetailsState: dataToPass});
}

// Now in the DetailsCtrl
if(!$state.params.somethingToPassToDetailsState) {
  // handle this  
  // maybe do a $state.go('default') and then return to end execution of this controller
}

// Some code

在master.html中,使用ng-repeat模拟主 - 详细信息页面重定向

<div ng-repeat="o in objects">
  <div ng-click="redirectTo(o)">{{o.name}}</div>
</div>

这个想法是在状态转换时将一天直接从一个州传递到另一个州。您可以支付我的费用并在转换到这些新状态后进行api调用或从api获得响应,然后将所需的数据发送到下一个状态

答案 1 :(得分:0)

在两个控制器之间共享数据并不是一种好的做法。

我们需要将数据投入使用,可以轻松与任意数量的控制器共享

服务:MyService

this.dbDataSearch = function(parameters){
  // Search record from database
  this.resultData = data;
}

在Convtoller 1中:

 $scope.data = MyService.resultData;

在Convtoller 2中:

 $scope.data = MyService.resultData;

...

在Convtoller n:

 $scope.data = MyService.resultData;

一旦服务变量将更新所有这些控制器变量自动更新。

答案 2 :(得分:0)

首先,强烈建议您在工厂或服务中进行http调用。这将使您的代码更具可重用性,它看起来像这样:

app.factory("responseFactory", function($http) {
  return {
      getData: function() {
          //Code for making http call goes in here
          $http.get("http://localhost/select-news.php").then(function(response){
            return(response.data);
          });
      },
      postData: function(x) {
          $http.post("http://localhost/select-news-by-id.php", {'item_id': x.ID})
          .then(function(response){
            return(response.data);
          });
      }
  };
});

您可以稍后通过在控制器中注入此工厂并调用此工厂来调用您的控制器:

app.controller('temporada2016Ctrl', ['$scope', 'responseFactory', function ($scope, responseFactory) {
    $scope.items = responseFactory.getData();
    $scope.opnItem = function(x){
        $scope.all = responseFactory.postData(x);
        $scope.title = all.TITLE;
        $scope.body = all.BODY;
    }
}]);

现在,为了在第二个控制器中提供数据,您可以做一些事情。

  1. 将其传递给$ rootScope,正如您已经说过的那样,应尽可能避免使用rootScope,以免使rootScope混乱。它可能会产生很多后果。 - 不推荐

  2. 从第二个控制器拨打服务电话,您将获得api所需的所有数据。但是,如果您编辑第一个控制器中的数据并希望在第二个控制器中提供已编辑的数据,则使用此方法将无法实现。此外,进行http调用的成本很高,强烈建议最大限度地减少应用中的http调用次数。 - 不推荐

  3. 使用Angular服务/工厂 - 强烈推荐

    app.factory('commonData', function() {
        var data;
    
        return{
            setData: setData,
            getData: getData
        };
    
        //setter
        function setData(dataToBeShared) {
            data = dataToBeShared;
        }
    
        //getter
        function getData() {
            return data;
        }
    
    });
    

    现在您可以将此工厂注入您的控制器并轻松使用setter和getter方法。不要忘记注入我们之前创建的responseFactory! 将它注入第一个控制器后,可以调用commonData工厂并使用setter方法设置数据,如下所示:

    app.controller('temporada2016Ctrl', ['$scope', 'responseFactory', 'commonData', function ($scope, responseFactory, commonData) {
    
        //All your controller code, including calling the factory like I earlier explained...it all goes here
    
        commonData.setData(passTheDataThatYouWantToShare);
    
    }]);
    
  4. 现在,要获取其他控制器中的数据,您只需访问工厂的getter方法即可获得数据!这将是这样的:

        app.controller('detalhesCtrl', ['$scope', '$stateParams', 'commonData', function ($scope, $stateParams, commonData) {
            $scope.commonData = commonData.getData();
            //Use $scope.commonData to use all the data that has come in from first controller
        }]);
    

    现在,从控制器1传递的数据存储在工厂中,可以随时在第二个控制器中检索。假设您希望将它们显示为窗格,彼此相邻,您可能希望添加观察者,否则此方法应该适合您。

    注意:这可以在不使用setter和getter方法的情况下实现,但使用它们是一种很好的做法,并且在应用程序变大时非常有用。

    1. 使用Angular UI路由器通过状态参数传递数据。在我看来,你正在使用与离子捆绑的Angular UI路由器。在路由时也可以使用它。在撰写此答案时,此线程的另一个答案(由SLearner提供)已经解释了这种方法,如果建议与否,或多或少是您的选择,具体取决于您想要的功能级别。但是,在我看来,我不会接受这个解决方案。您可以在此主题上找到关于此主题的更多答案:AngularJS: Pass an object into a state using ui-router
    2. 所以,总结我的答案,在我看来,你最好去一个有角度的工厂。恕我直言,这是最好的解决方案。希望您的疑问得到解答。

      干杯!